]> Sergey Matveev's repositories - btrtrc.git/blob - metainfo/piece.go
cmd/btrtrc client
[btrtrc.git] / metainfo / piece.go
1 package metainfo
2
3 import (
4         g "github.com/anacrolix/generics"
5 )
6
7 type Piece struct {
8         Info *Info // Can we embed the fields here instead, or is it something to do with saving memory?
9         i    pieceIndex
10 }
11
12 type pieceIndex = int
13
14 func (p Piece) Length() int64 {
15         if p.Info.HasV2() {
16                 var offset int64
17                 pieceLength := p.Info.PieceLength
18                 lastFileEnd := int64(0)
19                 done := false
20                 p.Info.FileTree.upvertedFiles(pieceLength, func(fi FileInfo) {
21                         if done {
22                                 return
23                         }
24                         fileStartPiece := int(offset / pieceLength)
25                         if fileStartPiece > p.i {
26                                 done = true
27                                 return
28                         }
29                         lastFileEnd = offset + fi.Length
30                         offset = (lastFileEnd + pieceLength - 1) / pieceLength * pieceLength
31                 })
32                 ret := min(lastFileEnd-int64(p.i)*pieceLength, pieceLength)
33                 if ret <= 0 {
34                         panic(ret)
35                 }
36                 return ret
37         }
38         return p.V1Length()
39 }
40
41 func (p Piece) V1Length() int64 {
42         i := p.i
43         lastPiece := p.Info.NumPieces() - 1
44         switch {
45         case 0 <= i && i < lastPiece:
46                 return p.Info.PieceLength
47         case lastPiece >= 0 && i == lastPiece:
48                 files := p.Info.UpvertedFiles()
49                 lastFile := files[len(files)-1]
50                 length := lastFile.TorrentOffset + lastFile.Length - int64(i)*p.Info.PieceLength
51                 if length <= 0 || length > p.Info.PieceLength {
52                         panic(length)
53                 }
54                 return length
55         default:
56                 panic(i)
57         }
58 }
59
60 func (p Piece) Offset() int64 {
61         return int64(p.i) * p.Info.PieceLength
62 }
63
64 func (p Piece) V1Hash() (ret g.Option[Hash]) {
65         if !p.Info.HasV1() {
66                 return
67         }
68         copy(ret.Value[:], p.Info.Pieces[p.i*HashSize:(p.i+1)*HashSize])
69         ret.Ok = true
70         return
71 }
72
73 func (p Piece) Index() int {
74         return p.i
75 }