offset_reader.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package request
  2. import (
  3. "io"
  4. "sync"
  5. )
  6. // offsetReader is a thread-safe io.ReadCloser to prevent racing
  7. // with retrying requests
  8. type offsetReader struct {
  9. buf io.ReadSeeker
  10. lock sync.Mutex
  11. closed bool
  12. }
  13. func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
  14. reader := &offsetReader{}
  15. buf.Seek(offset, 0)
  16. reader.buf = buf
  17. return reader
  18. }
  19. // Close will close the instance of the offset reader's access to
  20. // the underlying io.ReadSeeker.
  21. func (o *offsetReader) Close() error {
  22. o.lock.Lock()
  23. defer o.lock.Unlock()
  24. o.closed = true
  25. return nil
  26. }
  27. // Read is a thread-safe read of the underlying io.ReadSeeker
  28. func (o *offsetReader) Read(p []byte) (int, error) {
  29. o.lock.Lock()
  30. defer o.lock.Unlock()
  31. if o.closed {
  32. return 0, io.EOF
  33. }
  34. return o.buf.Read(p)
  35. }
  36. // Seek is a thread-safe seeking operation.
  37. func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
  38. o.lock.Lock()
  39. defer o.lock.Unlock()
  40. return o.buf.Seek(offset, whence)
  41. }
  42. // CloseAndCopy will return a new offsetReader with a copy of the old buffer
  43. // and close the old buffer.
  44. func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
  45. o.Close()
  46. return newOffsetReader(o.buf, offset)
  47. }