OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / encoding / blockchain / blockchain.go
1 // Package blockchain provides the tools for encoding
2 // data primitives in blockchain structures
3 package blockchain
4
5 import (
6         "encoding/binary"
7         "errors"
8         "io"
9         "math"
10         "sync"
11
12         "github.com/vapor/encoding/bufpool"
13 )
14
15 var bufPool = sync.Pool{New: func() interface{} { return new([9]byte) }}
16
17 var ErrRange = errors.New("value out of range")
18
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.
22 type Reader struct {
23         buf []byte
24 }
25
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}
31 }
32
33 // Len returns the number of unread bytes.
34 func (r *Reader) Len() int {
35         return len(r.buf)
36 }
37
38 // ReadByte reads and returns the next byte from the input.
39 //
40 // It implements the io.ByteReader interface.
41 func (r *Reader) ReadByte() (byte, error) {
42         if len(r.buf) == 0 {
43                 return 0, io.EOF
44         }
45
46         b := r.buf[0]
47         r.buf = r.buf[1:]
48         return b, nil
49 }
50
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) {
54         n = copy(p, r.buf)
55         r.buf = r.buf[n:]
56         if len(r.buf) == 0 {
57                 err = io.EOF
58         }
59         return
60 }
61
62 func ReadVarint31(r *Reader) (uint32, error) {
63         val, err := binary.ReadUvarint(r)
64         if err != nil {
65                 return 0, err
66         }
67         if val > math.MaxInt32 {
68                 return 0, ErrRange
69         }
70         return uint32(val), nil
71 }
72
73 func ReadVarint63(r *Reader) (uint64, error) {
74         val, err := binary.ReadUvarint(r)
75         if err != nil {
76                 return 0, err
77         }
78         if val > math.MaxInt64 {
79                 return 0, ErrRange
80         }
81         return val, nil
82 }
83
84 func ReadVarstr31(r *Reader) ([]byte, error) {
85         l, err := ReadVarint31(r)
86         if err != nil {
87                 return nil, err
88         }
89         if l == 0 {
90                 return nil, nil
91         }
92         if int(l) > len(r.buf) {
93                 return nil, io.ErrUnexpectedEOF
94         }
95         str := r.buf[:l]
96         r.buf = r.buf[l:]
97         return str, nil
98 }
99
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)
104         if err != nil {
105                 return nil, err
106         }
107         if nelts == 0 {
108                 return nil, nil
109         }
110
111         for ; nelts > 0 && err == nil; nelts-- {
112                 var s []byte
113                 s, err = ReadVarstr31(r)
114                 result = append(result, s)
115         }
116         if len(result) < int(nelts) {
117                 err = io.ErrUnexpectedEOF
118         }
119         return result, err
120 }
121
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)
127         if err != nil {
128                 return nil, err
129         }
130
131         sr := NewReader(s)
132         err = f(sr)
133         if err != nil {
134                 return nil, err
135         }
136         return sr.buf, nil
137 }
138
139 func WriteVarint31(w io.Writer, val uint64) (int, error) {
140         if val > math.MaxInt32 {
141                 return 0, ErrRange
142         }
143         buf := bufPool.Get().(*[9]byte)
144         n := binary.PutUvarint(buf[:], val)
145         b, err := w.Write(buf[:n])
146         bufPool.Put(buf)
147         return b, err
148 }
149
150 func WriteVarint63(w io.Writer, val uint64) (int, error) {
151         if val > math.MaxInt64 {
152                 return 0, ErrRange
153         }
154         buf := bufPool.Get().(*[9]byte)
155         n := binary.PutUvarint(buf[:], val)
156         b, err := w.Write(buf[:n])
157         bufPool.Put(buf)
158         return b, err
159 }
160
161 func WriteVarstr31(w io.Writer, str []byte) (int, error) {
162         n, err := WriteVarint31(w, uint64(len(str)))
163         if err != nil {
164                 return n, err
165         }
166         n2, err := w.Write(str)
167         return n + n2, err
168 }
169
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)))
174         if err != nil {
175                 return n, err
176         }
177         for _, s := range l {
178                 n2, err := WriteVarstr31(w, s)
179                 n += n2
180                 if err != nil {
181                         return n, err
182                 }
183         }
184         return n, err
185 }
186
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) {
190         buf := bufpool.Get()
191         defer bufpool.Put(buf)
192         err := f(buf)
193         if err != nil {
194                 return 0, err
195         }
196         if len(suffix) > 0 {
197                 _, err := buf.Write(suffix)
198                 if err != nil {
199                         return 0, err
200                 }
201         }
202         return WriteVarstr31(w, buf.Bytes())
203 }