io.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package multihash
  2. import (
  3. "errors"
  4. "io"
  5. "math"
  6. "github.com/multiformats/go-varint"
  7. )
  8. // Reader is an io.Reader wrapper that exposes a function
  9. // to read a whole multihash, parse it, and return it.
  10. type Reader interface {
  11. io.Reader
  12. ReadMultihash() (Multihash, error)
  13. }
  14. // Writer is an io.Writer wrapper that exposes a function
  15. // to write a whole multihash.
  16. type Writer interface {
  17. io.Writer
  18. WriteMultihash(Multihash) error
  19. }
  20. // NewReader wraps an io.Reader with a multihash.Reader
  21. func NewReader(r io.Reader) Reader {
  22. return &mhReader{r}
  23. }
  24. // NewWriter wraps an io.Writer with a multihash.Writer
  25. func NewWriter(w io.Writer) Writer {
  26. return &mhWriter{w}
  27. }
  28. type mhReader struct {
  29. r io.Reader
  30. }
  31. func (r *mhReader) Read(buf []byte) (n int, err error) {
  32. return r.r.Read(buf)
  33. }
  34. func (r *mhReader) ReadByte() (byte, error) {
  35. if br, ok := r.r.(io.ByteReader); ok {
  36. return br.ReadByte()
  37. }
  38. var b [1]byte
  39. n, err := r.r.Read(b[:])
  40. if n == 1 {
  41. return b[0], nil
  42. }
  43. if err == nil {
  44. if n != 0 {
  45. panic("reader returned an invalid length")
  46. }
  47. err = io.ErrNoProgress
  48. }
  49. return 0, err
  50. }
  51. func (r *mhReader) ReadMultihash() (Multihash, error) {
  52. code, err := varint.ReadUvarint(r)
  53. if err != nil {
  54. return nil, err
  55. }
  56. length, err := varint.ReadUvarint(r)
  57. if err != nil {
  58. return nil, err
  59. }
  60. if length > math.MaxInt32 {
  61. return nil, errors.New("digest too long, supporting only <= 2^31-1")
  62. }
  63. buf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(length)+int(length))
  64. n := varint.PutUvarint(buf, code)
  65. n += varint.PutUvarint(buf[n:], length)
  66. if _, err := io.ReadFull(r.r, buf[n:]); err != nil {
  67. return nil, err
  68. }
  69. return Cast(buf)
  70. }
  71. type mhWriter struct {
  72. w io.Writer
  73. }
  74. func (w *mhWriter) Write(buf []byte) (n int, err error) {
  75. return w.w.Write(buf)
  76. }
  77. func (w *mhWriter) WriteMultihash(m Multihash) error {
  78. _, err := w.w.Write([]byte(m))
  79. return err
  80. }