github.com/aavshr/aws-sdk-go@v1.41.3/service/s3/s3manager/buffered_read_seeker.go (about) 1 package s3manager 2 3 import ( 4 "io" 5 6 "github.com/aavshr/aws-sdk-go/internal/sdkio" 7 ) 8 9 // BufferedReadSeeker is buffered io.ReadSeeker 10 type BufferedReadSeeker struct { 11 r io.ReadSeeker 12 buffer []byte 13 readIdx, writeIdx int 14 } 15 16 // NewBufferedReadSeeker returns a new BufferedReadSeeker 17 // if len(b) == 0 then the buffer will be initialized to 64 KiB. 18 func NewBufferedReadSeeker(r io.ReadSeeker, b []byte) *BufferedReadSeeker { 19 if len(b) == 0 { 20 b = make([]byte, 64*1024) 21 } 22 return &BufferedReadSeeker{r: r, buffer: b} 23 } 24 25 func (b *BufferedReadSeeker) reset(r io.ReadSeeker) { 26 b.r = r 27 b.readIdx, b.writeIdx = 0, 0 28 } 29 30 // Read will read up len(p) bytes into p and will return 31 // the number of bytes read and any error that occurred. 32 // If the len(p) > the buffer size then a single read request 33 // will be issued to the underlying io.ReadSeeker for len(p) bytes. 34 // A Read request will at most perform a single Read to the underlying 35 // io.ReadSeeker, and may return < len(p) if serviced from the buffer. 36 func (b *BufferedReadSeeker) Read(p []byte) (n int, err error) { 37 if len(p) == 0 { 38 return n, err 39 } 40 41 if b.readIdx == b.writeIdx { 42 if len(p) >= len(b.buffer) { 43 n, err = b.r.Read(p) 44 return n, err 45 } 46 b.readIdx, b.writeIdx = 0, 0 47 48 n, err = b.r.Read(b.buffer) 49 if n == 0 { 50 return n, err 51 } 52 53 b.writeIdx += n 54 } 55 56 n = copy(p, b.buffer[b.readIdx:b.writeIdx]) 57 b.readIdx += n 58 59 return n, err 60 } 61 62 // Seek will position then underlying io.ReadSeeker to the given offset 63 // and will clear the buffer. 64 func (b *BufferedReadSeeker) Seek(offset int64, whence int) (int64, error) { 65 n, err := b.r.Seek(offset, whence) 66 67 b.reset(b.r) 68 69 return n, err 70 } 71 72 // ReadAt will read up to len(p) bytes at the given file offset. 73 // This will result in the buffer being cleared. 74 func (b *BufferedReadSeeker) ReadAt(p []byte, off int64) (int, error) { 75 _, err := b.Seek(off, sdkio.SeekStart) 76 if err != nil { 77 return 0, err 78 } 79 80 return b.Read(p) 81 }