@@ -25,6 +25,14 @@ const (
25
25
minByteSliceLen = minVarIntLen
26
26
minDBNodeLen = minMaybeByteSliceLen + minVarIntLen
27
27
minChildLen = minVarIntLen + minSerializedPathLen + ids .IDLen
28
+
29
+ estimatedKeyLen = 64
30
+ estimatedValueLen = 64
31
+ estimatedCompressedPathLen = 8
32
+ // Child index, child compressed path, child ID
33
+ estimatedNodeChildLen = minVarIntLen + estimatedCompressedPathLen + ids .IDLen
34
+ // Child index, child ID
35
+ hashValuesChildLen = minVarIntLen + ids .IDLen
28
36
)
29
37
30
38
var (
33
41
trueBytes = []byte {trueByte }
34
42
falseBytes = []byte {falseByte }
35
43
36
- errDecodeNil = errors .New ("can't decode nil" )
37
44
errNegativeNumChildren = errors .New ("number of children is negative" )
38
45
errTooManyChildren = fmt .Errorf ("length of children list is larger than branching factor of %d" , NodeBranchFactor )
39
46
errChildIndexTooLarge = fmt .Errorf ("invalid child index. Must be less than branching factor of %d" , NodeBranchFactor )
@@ -61,6 +68,7 @@ type encoder interface {
61
68
}
62
69
63
70
type decoder interface {
71
+ // Assumes [n] is non-nil.
64
72
decodeDBNode (bytes []byte , n * dbNode ) error
65
73
}
66
74
@@ -81,26 +89,37 @@ type codecImpl struct {
81
89
}
82
90
83
91
func (c * codecImpl ) encodeDBNode (n * dbNode ) []byte {
84
- buf := & bytes.Buffer {}
92
+ var (
93
+ numChildren = len (n .children )
94
+ // Estimate size of [n] to prevent memory allocations
95
+ estimatedLen = estimatedValueLen + minVarIntLen + estimatedNodeChildLen * numChildren
96
+ buf = bytes .NewBuffer (make ([]byte , 0 , estimatedLen ))
97
+ )
98
+
85
99
c .encodeMaybeByteSlice (buf , n .value )
86
- childrenLength := len (n .children )
87
- c .encodeInt (buf , childrenLength )
100
+ c .encodeInt (buf , numChildren )
101
+ // Note we insert children in order of increasing index
102
+ // for determinism.
88
103
for index := byte (0 ); index < NodeBranchFactor ; index ++ {
89
104
if entry , ok := n .children [index ]; ok {
90
105
c .encodeInt (buf , int (index ))
91
106
path := entry .compressedPath .Serialize ()
92
- c .encodeSerializedPath (path , buf )
107
+ c .encodeSerializedPath (buf , path )
93
108
_ , _ = buf .Write (entry .id [:])
94
109
}
95
110
}
96
111
return buf .Bytes ()
97
112
}
98
113
99
114
func (c * codecImpl ) encodeHashValues (hv * hashValues ) []byte {
100
- buf := & bytes.Buffer {}
115
+ var (
116
+ numChildren = len (hv .Children )
117
+ // Estimate size [hv] to prevent memory allocations
118
+ estimatedLen = minVarIntLen + numChildren * hashValuesChildLen + estimatedValueLen + estimatedKeyLen
119
+ buf = bytes .NewBuffer (make ([]byte , 0 , estimatedLen ))
120
+ )
101
121
102
- length := len (hv .Children )
103
- c .encodeInt (buf , length )
122
+ c .encodeInt (buf , numChildren )
104
123
105
124
// ensure that the order of entries is consistent
106
125
for index := byte (0 ); index < NodeBranchFactor ; index ++ {
@@ -110,33 +129,28 @@ func (c *codecImpl) encodeHashValues(hv *hashValues) []byte {
110
129
}
111
130
}
112
131
c .encodeMaybeByteSlice (buf , hv .Value )
113
- c .encodeSerializedPath (hv .Key , buf )
132
+ c .encodeSerializedPath (buf , hv .Key )
114
133
115
134
return buf .Bytes ()
116
135
}
117
136
118
137
func (c * codecImpl ) decodeDBNode (b []byte , n * dbNode ) error {
119
- if n == nil {
120
- return errDecodeNil
121
- }
122
138
if minDBNodeLen > len (b ) {
123
139
return io .ErrUnexpectedEOF
124
140
}
125
141
126
- var (
127
- src = bytes .NewReader (b )
128
- err error
129
- )
142
+ src := bytes .NewReader (b )
130
143
131
- if n .value , err = c .decodeMaybeByteSlice (src ); err != nil {
144
+ value , err := c .decodeMaybeByteSlice (src )
145
+ if err != nil {
132
146
return err
133
147
}
148
+ n .value = value
134
149
135
150
numChildren , err := c .decodeInt (src )
136
- if err != nil {
137
- return err
138
- }
139
151
switch {
152
+ case err != nil :
153
+ return err
140
154
case numChildren < 0 :
141
155
return errNegativeNumChildren
142
156
case numChildren > NodeBranchFactor :
@@ -148,21 +162,21 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
148
162
n .children = make (map [byte ]child , NodeBranchFactor )
149
163
previousChild := - 1
150
164
for i := 0 ; i < numChildren ; i ++ {
151
- var index int
152
- if index , err = c . decodeInt ( src ); err != nil {
165
+ index , err := c . decodeInt ( src )
166
+ if err != nil {
153
167
return err
154
168
}
155
- if index <= previousChild || index > NodeBranchFactor - 1 {
169
+ if index <= previousChild || index >= NodeBranchFactor {
156
170
return errChildIndexTooLarge
157
171
}
158
172
previousChild = index
159
173
160
- var compressedPath SerializedPath
161
- if compressedPath , err = c . decodeSerializedPath ( src ); err != nil {
174
+ compressedPath , err := c . decodeSerializedPath ( src )
175
+ if err != nil {
162
176
return err
163
177
}
164
- var childID ids. ID
165
- if childID , err = c . decodeID ( src ); err != nil {
178
+ childID , err := c . decodeID ( src )
179
+ if err != nil {
166
180
return err
167
181
}
168
182
n .children [byte (index )] = child {
@@ -173,7 +187,7 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
173
187
if src .Len () != 0 {
174
188
return errExtraSpace
175
189
}
176
- return err
190
+ return nil
177
191
}
178
192
179
193
func (* codecImpl ) encodeBool (dst * bytes.Buffer , value bool ) {
@@ -186,16 +200,14 @@ func (*codecImpl) encodeBool(dst *bytes.Buffer, value bool) {
186
200
187
201
func (* codecImpl ) decodeBool (src * bytes.Reader ) (bool , error ) {
188
202
boolByte , err := src .ReadByte ()
189
- if err == io .EOF {
203
+ switch {
204
+ case err == io .EOF :
190
205
return false , io .ErrUnexpectedEOF
191
- }
192
- if err != nil {
206
+ case err != nil :
193
207
return false , err
194
- }
195
- switch boolByte {
196
- case trueByte :
208
+ case boolByte == trueByte :
197
209
return true , nil
198
- case falseByte :
210
+ case boolByte == falseByte :
199
211
return false , nil
200
212
default :
201
213
return false , errInvalidBool
@@ -249,8 +261,9 @@ func (c *codecImpl) encodeInt64(dst *bytes.Buffer, value int64) {
249
261
}
250
262
251
263
func (c * codecImpl ) encodeMaybeByteSlice (dst * bytes.Buffer , maybeValue maybe.Maybe [[]byte ]) {
252
- c .encodeBool (dst , ! maybeValue .IsNothing ())
253
- if maybeValue .HasValue () {
264
+ hasValue := maybeValue .HasValue ()
265
+ c .encodeBool (dst , hasValue )
266
+ if hasValue {
254
267
c .encodeByteSlice (dst , maybeValue .Value ())
255
268
}
256
269
}
@@ -277,19 +290,12 @@ func (c *codecImpl) decodeByteSlice(src *bytes.Reader) ([]byte, error) {
277
290
return nil , io .ErrUnexpectedEOF
278
291
}
279
292
280
- var (
281
- length int
282
- err error
283
- result []byte
284
- )
285
- if length , err = c .decodeInt (src ); err != nil {
286
- if err == io .EOF {
287
- return nil , io .ErrUnexpectedEOF
288
- }
289
- return nil , err
290
- }
291
-
293
+ length , err := c .decodeInt (src )
292
294
switch {
295
+ case err == io .EOF :
296
+ return nil , io .ErrUnexpectedEOF
297
+ case err != nil :
298
+ return nil , err
293
299
case length < 0 :
294
300
return nil , errNegativeSliceLength
295
301
case length == 0 :
@@ -298,14 +304,12 @@ func (c *codecImpl) decodeByteSlice(src *bytes.Reader) ([]byte, error) {
298
304
return nil , io .ErrUnexpectedEOF
299
305
}
300
306
301
- result = make ([]byte , length )
302
- if _ , err := io .ReadFull (src , result ); err != nil {
303
- if err == io .EOF {
304
- err = io .ErrUnexpectedEOF
305
- }
306
- return nil , err
307
+ result := make ([]byte , length )
308
+ _ , err = io .ReadFull (src , result )
309
+ if err == io .EOF {
310
+ err = io .ErrUnexpectedEOF
307
311
}
308
- return result , nil
312
+ return result , err
309
313
}
310
314
311
315
func (c * codecImpl ) encodeByteSlice (dst * bytes.Buffer , value []byte ) {
@@ -321,16 +325,14 @@ func (*codecImpl) decodeID(src *bytes.Reader) (ids.ID, error) {
321
325
}
322
326
323
327
var id ids.ID
324
- if _ , err := io .ReadFull (src , id [:]); err != nil {
325
- if err == io .EOF {
326
- err = io .ErrUnexpectedEOF
327
- }
328
- return id , err
328
+ _ , err := io .ReadFull (src , id [:])
329
+ if err == io .EOF {
330
+ err = io .ErrUnexpectedEOF
329
331
}
330
- return id , nil
332
+ return id , err
331
333
}
332
334
333
- func (c * codecImpl ) encodeSerializedPath (s SerializedPath , dst * bytes.Buffer ) {
335
+ func (c * codecImpl ) encodeSerializedPath (dst * bytes.Buffer , s SerializedPath ) {
334
336
c .encodeInt (dst , s .NibbleLength )
335
337
_ , _ = dst .Write (s .Value )
336
338
}
@@ -345,30 +347,30 @@ func (c *codecImpl) decodeSerializedPath(src *bytes.Reader) (SerializedPath, err
345
347
err error
346
348
)
347
349
if result .NibbleLength , err = c .decodeInt (src ); err != nil {
348
- return result , err
350
+ return SerializedPath {} , err
349
351
}
350
352
if result .NibbleLength < 0 {
351
- return result , errNegativeNibbleLength
353
+ return SerializedPath {} , errNegativeNibbleLength
352
354
}
353
355
pathBytesLen := result .NibbleLength >> 1
354
356
hasOddLen := result .hasOddLength ()
355
357
if hasOddLen {
356
358
pathBytesLen ++
357
359
}
358
360
if pathBytesLen > src .Len () {
359
- return result , io .ErrUnexpectedEOF
361
+ return SerializedPath {} , io .ErrUnexpectedEOF
360
362
}
361
363
result .Value = make ([]byte , pathBytesLen )
362
364
if _ , err := io .ReadFull (src , result .Value ); err != nil {
363
365
if err == io .EOF {
364
366
err = io .ErrUnexpectedEOF
365
367
}
366
- return result , err
368
+ return SerializedPath {} , err
367
369
}
368
370
if hasOddLen {
369
371
paddedNibble := result .Value [pathBytesLen - 1 ] & 0x0F
370
372
if paddedNibble != 0 {
371
- return result , errNonZeroNibblePadding
373
+ return SerializedPath {} , errNonZeroNibblePadding
372
374
}
373
375
}
374
376
return result , nil
0 commit comments