fakeseeker.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package readers
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. )
  7. // FakeSeeker adapts an io.Seeker into an io.ReadSeeker
  8. type FakeSeeker struct {
  9. in io.Reader
  10. readErr error
  11. length int64
  12. offset int64
  13. read bool
  14. }
  15. // NewFakeSeeker creates a fake io.ReadSeeker from an io.Reader
  16. //
  17. // This can be seeked before reading to discover the length passed in.
  18. func NewFakeSeeker(in io.Reader, length int64) io.ReadSeeker {
  19. if rs, ok := in.(io.ReadSeeker); ok {
  20. return rs
  21. }
  22. return &FakeSeeker{
  23. in: in,
  24. length: length,
  25. }
  26. }
  27. // Seek the stream - possible only before reading
  28. func (r *FakeSeeker) Seek(offset int64, whence int) (abs int64, err error) {
  29. if r.readErr != nil {
  30. return 0, r.readErr
  31. }
  32. if r.read {
  33. return 0, fmt.Errorf("FakeSeeker: can't Seek(%d, %d) after reading", offset, whence)
  34. }
  35. switch whence {
  36. case io.SeekStart:
  37. abs = offset
  38. case io.SeekCurrent:
  39. abs = r.offset + offset
  40. case io.SeekEnd:
  41. abs = r.length + offset
  42. default:
  43. return 0, errors.New("FakeSeeker: invalid whence")
  44. }
  45. if abs < 0 {
  46. return 0, errors.New("FakeSeeker: negative position")
  47. }
  48. r.offset = abs
  49. return abs, nil
  50. }
  51. // Read data from the stream. Will give an error if seeked.
  52. func (r *FakeSeeker) Read(p []byte) (n int, err error) {
  53. if r.readErr != nil {
  54. return 0, r.readErr
  55. }
  56. if !r.read && r.offset != 0 {
  57. return 0, errors.New("FakeSeeker: not at start: can't read")
  58. }
  59. n, err = r.in.Read(p)
  60. if n != 0 {
  61. r.read = true
  62. }
  63. if err != nil {
  64. r.readErr = err
  65. }
  66. return n, err
  67. }