-
Notifications
You must be signed in to change notification settings - Fork 73
/
section.go
71 lines (61 loc) · 1.77 KB
/
section.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
package filesection
import "io"
// FileSection of a file.
type FileSection struct {
File ReadWriterAt
Offset int64
Length int64
Name string
}
// ReadWriterAt combines the io.ReaderAt and io.WriterAt interfaces.
type ReadWriterAt interface {
io.ReaderAt
io.WriterAt
}
// Piece is contiguous sections of files. When piece hashes in torrent file is being calculated
// all files are concatenated and splitted into pieces in length specified in the torrent file.
type Piece []FileSection
// ReadAt implements io.ReaderAt interface.
// It reads bytes from s at given offset into p.
// Used when uploading blocks of a piece.
func (p Piece) ReadAt(b []byte, off int64) (int, error) {
var readers []io.Reader
var i int
var pos int64
// Skip sections up to offset
for ; i < len(p); i++ {
pos += p[i].Length
if pos >= off {
break
}
}
// Add half section
advance := p[i].Length - (pos - off)
readers = append(readers, io.NewSectionReader(p[i].File, p[i].Offset+advance, p[i].Length-advance))
// Add remaining sections
for i++; i < len(p); i++ {
readers = append(readers, io.NewSectionReader(p[i].File, p[i].Offset, p[i].Length))
pos += p[i].Length
if pos >= off+int64(len(b)) {
break
}
}
return io.ReadFull(io.MultiReader(readers...), b)
}
// Write implements io.Writer interface.
// It writes the bytes in p into files in s.
// Used when writing a downloaded piece (all blocks) after hash check is done.
// Calling write does not change the current position in s,
// so len(p) must be equal to total length of the all files in s in order to issue a full write.
func (p Piece) Write(b []byte) (n int, err error) {
var m int
for _, sec := range p {
m, err = sec.File.WriteAt(b[:sec.Length], sec.Offset)
n += m
if err != nil {
return
}
b = b[m:]
}
return
}