section_read_seeker.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package missinggo
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. )
  7. type sectionReadSeeker struct {
  8. base io.ReadSeeker
  9. off, size int64
  10. }
  11. type ReadSeekContexter interface {
  12. io.ReadSeeker
  13. ReadContexter
  14. }
  15. // Returns a ReadSeeker on a section of another ReadSeeker.
  16. func NewSectionReadSeeker(base io.ReadSeeker, off, size int64) (ret ReadSeekContexter) {
  17. ret = &sectionReadSeeker{
  18. base: base,
  19. off: off,
  20. size: size,
  21. }
  22. seekOff, err := ret.Seek(0, io.SeekStart)
  23. if err != nil {
  24. panic(err)
  25. }
  26. if seekOff != 0 {
  27. panic(seekOff)
  28. }
  29. return
  30. }
  31. func (me *sectionReadSeeker) Seek(off int64, whence int) (ret int64, err error) {
  32. switch whence {
  33. case io.SeekStart:
  34. off += me.off
  35. case io.SeekCurrent:
  36. case io.SeekEnd:
  37. off += me.off + me.size
  38. whence = io.SeekStart
  39. default:
  40. err = fmt.Errorf("unhandled whence: %d", whence)
  41. return
  42. }
  43. ret, err = me.base.Seek(off, whence)
  44. ret -= me.off
  45. return
  46. }
  47. func (me *sectionReadSeeker) ReadContext(ctx context.Context, b []byte) (int, error) {
  48. off, err := me.Seek(0, io.SeekCurrent)
  49. if err != nil {
  50. return 0, err
  51. }
  52. left := me.size - off
  53. if left <= 0 {
  54. return 0, io.EOF
  55. }
  56. b = LimitLen(b, left)
  57. if rc, ok := me.base.(ReadContexter); ok {
  58. return rc.ReadContext(ctx, b)
  59. }
  60. if ctx != context.Background() {
  61. // Can't handle cancellation.
  62. panic(ctx)
  63. }
  64. return me.base.Read(b)
  65. }
  66. func (me *sectionReadSeeker) Read(b []byte) (int, error) {
  67. return me.ReadContext(context.Background(), b)
  68. }