piece.go 1.5 KB

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