pattern_reader.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package readers
  2. import (
  3. "errors"
  4. "io"
  5. )
  6. // This is the smallest prime less than 256
  7. //
  8. // Using a prime here means we are less likely to hit repeating patterns
  9. const patternReaderModulo = 251
  10. // NewPatternReader creates a reader, that returns a deterministic byte pattern.
  11. // After length bytes are read
  12. func NewPatternReader(length int64) io.ReadSeeker {
  13. return &patternReader{
  14. length: length,
  15. }
  16. }
  17. type patternReader struct {
  18. offset int64
  19. length int64
  20. c byte
  21. }
  22. func (r *patternReader) Read(p []byte) (n int, err error) {
  23. for i := range p {
  24. if r.offset >= r.length {
  25. return n, io.EOF
  26. }
  27. p[i] = r.c
  28. r.c = (r.c + 1) % patternReaderModulo
  29. r.offset++
  30. n++
  31. }
  32. return
  33. }
  34. // Seek implements the io.Seeker interface.
  35. func (r *patternReader) Seek(offset int64, whence int) (abs int64, err error) {
  36. switch whence {
  37. case io.SeekStart:
  38. abs = offset
  39. case io.SeekCurrent:
  40. abs = r.offset + offset
  41. case io.SeekEnd:
  42. abs = r.length + offset
  43. default:
  44. return 0, errors.New("patternReader: invalid whence")
  45. }
  46. if abs < 0 {
  47. return 0, errors.New("patternReader: negative position")
  48. }
  49. r.offset = abs
  50. r.c = byte(abs % patternReaderModulo)
  51. return abs, nil
  52. }