github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/lib/readers/repeatable.go (about) 1 package readers 2 3 import ( 4 "io" 5 "sync" 6 7 "github.com/pkg/errors" 8 ) 9 10 // A RepeatableReader implements the io.ReadSeeker it allow to seek cached data 11 // back and forth within the reader but will only read data from the internal Reader as necessary 12 // and will play nicely with the Account and io.LimitedReader to reflect current speed 13 type RepeatableReader struct { 14 mu sync.Mutex // protect against concurrent use 15 in io.Reader // Input reader 16 i int64 // current reading index 17 b []byte // internal cache buffer 18 } 19 20 var _ io.ReadSeeker = (*RepeatableReader)(nil) 21 22 // Seek implements the io.Seeker interface. 23 // If seek position is passed the cache buffer length the function will return 24 // the maximum offset that can be used and "fs.RepeatableReader.Seek: offset is unavailable" Error 25 func (r *RepeatableReader) Seek(offset int64, whence int) (int64, error) { 26 r.mu.Lock() 27 defer r.mu.Unlock() 28 29 var abs int64 30 cacheLen := int64(len(r.b)) 31 switch whence { 32 case io.SeekStart: 33 abs = offset 34 case io.SeekCurrent: 35 abs = r.i + offset 36 case io.SeekEnd: 37 abs = cacheLen + offset 38 default: 39 return 0, errors.New("fs.RepeatableReader.Seek: invalid whence") 40 } 41 if abs < 0 { 42 return 0, errors.New("fs.RepeatableReader.Seek: negative position") 43 } 44 if abs > cacheLen { 45 return offset - (abs - cacheLen), errors.New("fs.RepeatableReader.Seek: offset is unavailable") 46 } 47 r.i = abs 48 return abs, nil 49 } 50 51 // Read data from original Reader into bytes 52 // Data is either served from the underlying Reader or from cache if was already read 53 func (r *RepeatableReader) Read(b []byte) (n int, err error) { 54 r.mu.Lock() 55 defer r.mu.Unlock() 56 57 cacheLen := int64(len(r.b)) 58 if r.i == cacheLen { 59 n, err = r.in.Read(b) 60 if n > 0 { 61 r.b = append(r.b, b[:n]...) 62 } 63 } else { 64 n = copy(b, r.b[r.i:]) 65 } 66 r.i += int64(n) 67 return n, err 68 } 69 70 // NewRepeatableReader create new repeatable reader from Reader r 71 func NewRepeatableReader(r io.Reader) *RepeatableReader { 72 return &RepeatableReader{in: r} 73 } 74 75 // NewRepeatableReaderSized create new repeatable reader from Reader r 76 // with an initial buffer of size. 77 func NewRepeatableReaderSized(r io.Reader, size int) *RepeatableReader { 78 return &RepeatableReader{ 79 in: r, 80 b: make([]byte, 0, size), 81 } 82 } 83 84 // NewRepeatableLimitReader create new repeatable reader from Reader r 85 // with an initial buffer of size wrapped in an io.LimitReader to read 86 // only size. 87 func NewRepeatableLimitReader(r io.Reader, size int) *RepeatableReader { 88 return NewRepeatableReaderSized(io.LimitReader(r, int64(size)), size) 89 } 90 91 // NewRepeatableReaderBuffer create new repeatable reader from Reader r 92 // using the buffer passed in. 93 func NewRepeatableReaderBuffer(r io.Reader, buf []byte) *RepeatableReader { 94 return &RepeatableReader{ 95 in: r, 96 b: buf[:0], 97 } 98 } 99 100 // NewRepeatableLimitReaderBuffer create new repeatable reader from 101 // Reader r and buf wrapped in an io.LimitReader to read only size. 102 func NewRepeatableLimitReaderBuffer(r io.Reader, buf []byte, size int64) *RepeatableReader { 103 return NewRepeatableReaderBuffer(io.LimitReader(r, size), buf) 104 }