+++ /dev/null
-// Package blockchain provides the tools for encoding
-// data primitives in blockchain structures
-package blockchain
-
-import (
- "encoding/binary"
- "errors"
- "io"
- "math"
- "sync"
-
- "github.com/vapor/encoding/bufpool"
-)
-
-var bufPool = sync.Pool{New: func() interface{} { return new([9]byte) }}
-
-var ErrRange = errors.New("value out of range")
-
-// Reader wraps a buffer and provides utilities for decoding
-// data primitives in blockchain structures. Its various read
-// calls may return a slice of the underlying buffer.
-type Reader struct {
- buf []byte
-}
-
-// NewReader constructs a new reader with the provided bytes. It
-// does not create a copy of the bytes, so the caller is responsible
-// for copying the bytes if necessary.
-func NewReader(b []byte) *Reader {
- return &Reader{buf: b}
-}
-
-// Len returns the number of unread bytes.
-func (r *Reader) Len() int {
- return len(r.buf)
-}
-
-// ReadByte reads and returns the next byte from the input.
-//
-// It implements the io.ByteReader interface.
-func (r *Reader) ReadByte() (byte, error) {
- if len(r.buf) == 0 {
- return 0, io.EOF
- }
-
- b := r.buf[0]
- r.buf = r.buf[1:]
- return b, nil
-}
-
-// Read reads up to len(p) bytes into p. It implements
-// the io.Reader interface.
-func (r *Reader) Read(p []byte) (n int, err error) {
- n = copy(p, r.buf)
- r.buf = r.buf[n:]
- if len(r.buf) == 0 {
- err = io.EOF
- }
- return
-}
-
-func ReadVarint31(r *Reader) (uint32, error) {
- val, err := binary.ReadUvarint(r)
- if err != nil {
- return 0, err
- }
- if val > math.MaxInt32 {
- return 0, ErrRange
- }
- return uint32(val), nil
-}
-
-func ReadVarint63(r *Reader) (uint64, error) {
- val, err := binary.ReadUvarint(r)
- if err != nil {
- return 0, err
- }
- if val > math.MaxInt64 {
- return 0, ErrRange
- }
- return val, nil
-}
-
-func ReadVarstr31(r *Reader) ([]byte, error) {
- l, err := ReadVarint31(r)
- if err != nil {
- return nil, err
- }
- if l == 0 {
- return nil, nil
- }
- if int(l) > len(r.buf) {
- return nil, io.ErrUnexpectedEOF
- }
- str := r.buf[:l]
- r.buf = r.buf[l:]
- return str, nil
-}
-
-// ReadVarstrList reads a varint31 length prefix followed by
-// that many varstrs.
-func ReadVarstrList(r *Reader) (result [][]byte, err error) {
- nelts, err := ReadVarint31(r)
- if err != nil {
- return nil, err
- }
- if nelts == 0 {
- return nil, nil
- }
-
- for ; nelts > 0 && err == nil; nelts-- {
- var s []byte
- s, err = ReadVarstr31(r)
- result = append(result, s)
- }
- if len(result) < int(nelts) {
- err = io.ErrUnexpectedEOF
- }
- return result, err
-}
-
-// ReadExtensibleString reads a varint31 length prefix and that many
-// bytes from r. It then calls the given function to consume those
-// bytes, returning any unconsumed suffix.
-func ReadExtensibleString(r *Reader, f func(*Reader) error) (suffix []byte, err error) {
- s, err := ReadVarstr31(r)
- if err != nil {
- return nil, err
- }
-
- sr := NewReader(s)
- err = f(sr)
- if err != nil {
- return nil, err
- }
- return sr.buf, nil
-}
-
-func WriteVarint31(w io.Writer, val uint64) (int, error) {
- if val > math.MaxInt32 {
- return 0, ErrRange
- }
- buf := bufPool.Get().(*[9]byte)
- n := binary.PutUvarint(buf[:], val)
- b, err := w.Write(buf[:n])
- bufPool.Put(buf)
- return b, err
-}
-
-func WriteVarint63(w io.Writer, val uint64) (int, error) {
- if val > math.MaxInt64 {
- return 0, ErrRange
- }
- buf := bufPool.Get().(*[9]byte)
- n := binary.PutUvarint(buf[:], val)
- b, err := w.Write(buf[:n])
- bufPool.Put(buf)
- return b, err
-}
-
-func WriteVarstr31(w io.Writer, str []byte) (int, error) {
- n, err := WriteVarint31(w, uint64(len(str)))
- if err != nil {
- return n, err
- }
- n2, err := w.Write(str)
- return n + n2, err
-}
-
-// WriteVarstrList writes a varint31 length prefix followed by the
-// elements of l as varstrs.
-func WriteVarstrList(w io.Writer, l [][]byte) (int, error) {
- n, err := WriteVarint31(w, uint64(len(l)))
- if err != nil {
- return n, err
- }
- for _, s := range l {
- n2, err := WriteVarstr31(w, s)
- n += n2
- if err != nil {
- return n, err
- }
- }
- return n, err
-}
-
-// WriteExtensibleString sends the output of the given function, plus
-// the given suffix, to w, together with a varint31 length prefix.
-func WriteExtensibleString(w io.Writer, suffix []byte, f func(io.Writer) error) (int, error) {
- buf := bufpool.Get()
- defer bufpool.Put(buf)
- err := f(buf)
- if err != nil {
- return 0, err
- }
- if len(suffix) > 0 {
- _, err := buf.Write(suffix)
- if err != nil {
- return 0, err
- }
- }
- return WriteVarstr31(w, buf.Bytes())
-}