github.com/2lambda123/git-lfs@v2.5.2+incompatible/tools/copycallback.go (about) 1 package tools 2 3 import ( 4 "bytes" 5 "io" 6 ) 7 8 type CopyCallback func(totalSize int64, readSoFar int64, readSinceLast int) error 9 10 type BodyWithCallback struct { 11 c CopyCallback 12 totalSize int64 13 readSize int64 14 ReadSeekCloser 15 } 16 17 func NewByteBodyWithCallback(by []byte, totalSize int64, cb CopyCallback) *BodyWithCallback { 18 return NewBodyWithCallback(NewByteBody(by), totalSize, cb) 19 } 20 21 func NewBodyWithCallback(body ReadSeekCloser, totalSize int64, cb CopyCallback) *BodyWithCallback { 22 return &BodyWithCallback{ 23 c: cb, 24 totalSize: totalSize, 25 ReadSeekCloser: body, 26 } 27 } 28 29 // Read wraps the underlying Reader's "Read" method. It also captures the number 30 // of bytes read, and calls the callback. 31 func (r *BodyWithCallback) Read(p []byte) (int, error) { 32 n, err := r.ReadSeekCloser.Read(p) 33 34 if n > 0 { 35 r.readSize += int64(n) 36 37 if (err == nil || err == io.EOF) && r.c != nil { 38 err = r.c(r.totalSize, r.readSize, n) 39 } 40 } 41 return n, err 42 } 43 44 // Seek wraps the underlying Seeker's "Seek" method, updating the number of 45 // bytes that have been consumed by this reader. 46 func (r *BodyWithCallback) Seek(offset int64, whence int) (int64, error) { 47 switch whence { 48 case io.SeekStart: 49 r.readSize = offset 50 case io.SeekCurrent: 51 r.readSize += offset 52 case io.SeekEnd: 53 r.readSize = r.totalSize + offset 54 } 55 56 return r.ReadSeekCloser.Seek(offset, whence) 57 } 58 59 // ResetProgress calls the callback with a negative read size equal to the 60 // total number of bytes read so far, effectively "resetting" the progress. 61 func (r *BodyWithCallback) ResetProgress() error { 62 return r.c(r.totalSize, r.readSize, -int(r.readSize)) 63 } 64 65 type CallbackReader struct { 66 C CopyCallback 67 TotalSize int64 68 ReadSize int64 69 io.Reader 70 } 71 72 func (w *CallbackReader) Read(p []byte) (int, error) { 73 n, err := w.Reader.Read(p) 74 75 if n > 0 { 76 w.ReadSize += int64(n) 77 78 if (err == nil || err == io.EOF) && w.C != nil { 79 err = w.C(w.TotalSize, w.ReadSize, n) 80 } 81 } 82 return n, err 83 } 84 85 // prevent import cycle 86 type ReadSeekCloser interface { 87 io.Seeker 88 io.ReadCloser 89 } 90 91 func NewByteBody(by []byte) ReadSeekCloser { 92 return &closingByteReader{Reader: bytes.NewReader(by)} 93 } 94 95 type closingByteReader struct { 96 *bytes.Reader 97 } 98 99 func (r *closingByteReader) Close() error { 100 return nil 101 }