1 // Package blockchain provides the tools for encoding
2 // data primitives in blockchain structures
12 "github.com/bytom/encoding/bufpool"
15 var bufPool = sync.Pool{New: func() interface{} { return new([9]byte) }}
17 var ErrRange = errors.New("value out of range")
19 // Reader wraps a buffer and provides utilities for decoding
20 // data primitives in blockchain structures. Its various read
21 // calls may return a slice of the underlying buffer.
26 // NewReader constructs a new reader with the provided bytes. It
27 // does not create a copy of the bytes, so the caller is responsible
28 // for copying the bytes if necessary.
29 func NewReader(b []byte) *Reader {
30 return &Reader{buf: b}
33 // Len returns the number of unread bytes.
34 func (r *Reader) Len() int {
38 // ReadByte reads and returns the next byte from the input.
40 // It implements the io.ByteReader interface.
41 func (r *Reader) ReadByte() (byte, error) {
51 // Read reads up to len(p) bytes into p. It implements
52 // the io.Reader interface.
53 func (r *Reader) Read(p []byte) (n int, err error) {
62 func ReadVarint31(r *Reader) (uint32, error) {
63 val, err := binary.ReadUvarint(r)
67 if val > math.MaxInt32 {
70 return uint32(val), nil
73 func ReadVarint63(r *Reader) (uint64, error) {
74 val, err := binary.ReadUvarint(r)
78 if val > math.MaxInt64 {
84 func ReadVarstr31(r *Reader) ([]byte, error) {
85 l, err := ReadVarint31(r)
92 if int(l) > len(r.buf) {
93 return nil, io.ErrUnexpectedEOF
100 // ReadVarstrList reads a varint31 length prefix followed by
101 // that many varstrs.
102 func ReadVarstrList(r *Reader) (result [][]byte, err error) {
103 nelts, err := ReadVarint31(r)
111 for ; nelts > 0 && err == nil; nelts-- {
113 s, err = ReadVarstr31(r)
114 result = append(result, s)
116 if len(result) < int(nelts) {
117 err = io.ErrUnexpectedEOF
122 // ReadExtensibleString reads a varint31 length prefix and that many
123 // bytes from r. It then calls the given function to consume those
124 // bytes, returning any unconsumed suffix.
125 func ReadExtensibleString(r *Reader, f func(*Reader) error) (suffix []byte, err error) {
126 s, err := ReadVarstr31(r)
139 func WriteVarint31(w io.Writer, val uint64) (int, error) {
140 if val > math.MaxInt32 {
143 buf := bufPool.Get().(*[9]byte)
144 n := binary.PutUvarint(buf[:], val)
145 b, err := w.Write(buf[:n])
150 func WriteVarint63(w io.Writer, val uint64) (int, error) {
151 if val > math.MaxInt64 {
154 buf := bufPool.Get().(*[9]byte)
155 n := binary.PutUvarint(buf[:], val)
156 b, err := w.Write(buf[:n])
161 func WriteVarstr31(w io.Writer, str []byte) (int, error) {
162 n, err := WriteVarint31(w, uint64(len(str)))
166 n2, err := w.Write(str)
170 // WriteVarstrList writes a varint31 length prefix followed by the
171 // elements of l as varstrs.
172 func WriteVarstrList(w io.Writer, l [][]byte) (int, error) {
173 n, err := WriteVarint31(w, uint64(len(l)))
177 for _, s := range l {
178 n2, err := WriteVarstr31(w, s)
187 // WriteExtensibleString sends the output of the given function, plus
188 // the given suffix, to w, together with a varint31 length prefix.
189 func WriteExtensibleString(w io.Writer, suffix []byte, f func(io.Writer) error) (int, error) {
191 defer bufpool.Put(buf)
197 _, err := buf.Write(suffix)
202 return WriteVarstr31(w, buf.Bytes())