/
blob.go
125 lines (114 loc) · 2.27 KB
/
blob.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package blob
import (
"encoding/hex"
"io"
"log"
"github.com/anacrolix/torrent/metainfo"
)
type data struct {
info *metainfo.Info
store *store
}
func (me *data) pieceHashHex(i int) string {
return hex.EncodeToString(me.info.Pieces[i*20 : (i+1)*20])
}
func (me *data) Close() {}
func (me *data) ReadAt(b []byte, off int64) (n int, err error) {
for len(b) != 0 {
if off >= me.info.TotalLength() {
err = io.EOF
break
}
p := me.info.Piece(int(off / me.info.PieceLength))
f := me.store.pieceRead(p)
if f == nil {
log.Println("piece not found", p)
err = io.ErrUnexpectedEOF
break
}
b1 := b
maxN1 := int(p.Length() - off%me.info.PieceLength)
if len(b1) > maxN1 {
b1 = b1[:maxN1]
}
var n1 int
n1, err = f.ReadAt(b1, off%me.info.PieceLength)
f.Close()
n += n1
off += int64(n1)
b = b[n1:]
if err == io.EOF {
err = nil
break
}
if err != nil {
break
}
}
return
}
func (me *data) WriteAt(p []byte, off int64) (n int, err error) {
i := int(off / me.info.PieceLength)
off %= me.info.PieceLength
for len(p) != 0 {
f := me.store.pieceWrite(me.info.Piece(i))
p1 := p
maxN := me.info.Piece(i).Length() - off
if int64(len(p1)) > maxN {
p1 = p1[:maxN]
}
var n1 int
n1, err = f.WriteAt(p1, off)
f.Close()
n += n1
if err != nil {
return
}
p = p[n1:]
off = 0
i++
}
return
}
func (me *data) pieceReader(piece int, off int64) (ret io.ReadCloser, err error) {
f := me.store.pieceRead(me.info.Piece(piece))
if f == nil {
err = io.ErrUnexpectedEOF
return
}
return struct {
io.Reader
io.Closer
}{
Reader: io.NewSectionReader(f, off, me.info.Piece(piece).Length()-off),
Closer: f,
}, nil
}
func (me *data) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) {
i := int(off / me.info.PieceLength)
off %= me.info.PieceLength
for n != 0 {
var pr io.ReadCloser
pr, err = me.pieceReader(i, off)
if err != nil {
return
}
var n1 int64
n1, err = io.CopyN(w, pr, n)
pr.Close()
written += n1
n -= n1
if err != nil {
return
}
off = 0
i++
}
return
}
func (me *data) PieceCompleted(index int) (err error) {
return me.store.PieceCompleted(me.info.Piece(index))
}
func (me *data) PieceComplete(piece int) bool {
return me.store.pieceComplete(me.info.Piece(piece))
}