+ noCompletedMiddlePieces := roaring.New()
+ noCompletedMiddlePieces.AddRange(bitmap.BitRange(fileFirstPieceIndex), bitmap.BitRange(fileEndPieceIndex))
+ noCompletedMiddlePieces.AndNot(torrentCompletedPieces)
+ noCompletedMiddlePieces.Iterate(func(pieceIndex uint32) bool {
+ i := int(pieceIndex)
+ pieceSizeCompleted := pieceSizeCompletedFn(i)
+ if i == fileFirstPieceIndex {
+ beginOffset := fileTorrentOffset % torrentUsualPieceSize
+ beginSize := torrentUsualPieceSize - beginOffset
+ beginDownLoaded := pieceSizeCompleted - beginOffset
+ if beginDownLoaded < 0 {
+ beginDownLoaded = 0
+ }
+ left += beginSize - beginDownLoaded
+ } else if i == fileEndPieceIndex-1 {
+ endSize := (fileTorrentOffset + fileLength) % torrentUsualPieceSize
+ if endSize == 0 {
+ endSize = torrentUsualPieceSize
+ }
+ endDownloaded := pieceSizeCompleted
+ if endDownloaded > endSize {
+ endDownloaded = endSize
+ }
+ left += endSize - endDownloaded
+ } else {
+ left += torrentUsualPieceSize - pieceSizeCompleted
+ }
+ return true
+ })
+
+ if left > fileLength {
+ left = fileLength
+ }
+ //
+ //numPiecesSpanned := f.EndPieceIndex() - f.BeginPieceIndex()
+ //completedMiddlePieces := f.t._completedPieces.Clone()
+ //completedMiddlePieces.RemoveRange(0, bitmap.BitRange(f.BeginPieceIndex()+1))
+ //completedMiddlePieces.RemoveRange(bitmap.BitRange(f.EndPieceIndex()-1), bitmap.ToEnd)
+ //left += int64(numPiecesSpanned-2-pieceIndex(completedMiddlePieces.GetCardinality())) * torrentUsualPieceSize
+ return
+}
+
+func (f *File) bytesLeft() (left int64) {
+ return fileBytesLeft(int64(f.t.usualPieceSize()), f.BeginPieceIndex(), f.EndPieceIndex(), f.offset, f.length, &f.t._completedPieces, func(pieceIndex int) int64 {
+ return int64(f.t.piece(pieceIndex).numDirtyBytes())
+ })
+}
+
+// The relative file path for a multi-file torrent, and the torrent name for a
+// single-file torrent. Dir separators are '/'.
+func (f *File) DisplayPath() string {
+ return f.displayPath