@@ -10,7 +10,6 @@ import (
10
10
"encoding/binary"
11
11
"errors"
12
12
"fmt"
13
- "io"
14
13
"math/bits"
15
14
"slices"
16
15
"strings"
@@ -120,61 +119,42 @@ func (f FieldString) String() string {
120
119
}
121
120
122
121
func Unmarshal (data []byte , v interface {}) error {
123
- r := bytes .NewReader (data )
124
122
switch m := v .(type ) {
125
123
case * Message :
126
- messageLen := 1
127
- tmpVer := make ([]byte , messageLen )
128
- _ , err := r .Read (tmpVer )
129
- if err != nil {
130
- return err
131
- }
132
- m .Version = tmpVer [0 ] >> 1
133
-
134
- err = Unmarshal (data [messageLen :], & m .Format )
124
+ m .Version = data [0 ] >> 1
125
+ err := Unmarshal (data [1 :], & m .Format )
135
126
if err != nil {
136
127
return err
137
128
}
138
129
case * Format :
139
- formatLen := 2
140
- tmpFormat := make ([]byte , formatLen )
141
- _ , err := r .Read (tmpFormat )
142
- if err != nil {
143
- return err
144
- }
145
- m .Size = uint64 (tmpFormat [0 ] >> 1 )
146
- m .LastNonIgnorableField = int (tmpFormat [1 ] >> 1 )
130
+ pos := uint64 (0 )
131
+ m .Size = uint64 (data [pos ] >> 1 )
132
+ pos ++
133
+ m .LastNonIgnorableField = int (data [pos ] >> 1 )
134
+ pos ++
147
135
148
136
for i := 0 ; i < len (m .Fields ); i ++ {
149
- tmpField := make ([]byte , 1 )
150
- _ , err := r .Read (tmpField )
151
- if err != nil {
152
- if errors .Is (err , io .EOF ) {
153
- break
154
- }
155
- return err
156
- }
157
- if int (tmpField [0 ]/ 2 ) != i {
137
+ if int (pos )+ 1 > len (data ) || int (data [pos ]>> 1 ) != i {
158
138
// The field number we got doesn't match what we expect,
159
- // so a field was skipped. Rewind the reader and skip.
139
+ // so a field was skipped.
160
140
m .Fields [i ].ID = i
161
141
m .Fields [i ].Skipped = true
162
- _ , err := r .Seek (- 1 , io .SeekCurrent )
163
- if err != nil {
164
- return err
165
- }
166
142
continue
167
143
}
168
- m .Fields [i ].ID = int (tmpField [0 ] >> 1 )
144
+ m .Fields [i ].ID = int (data [pos ] >> 1 )
145
+ pos ++
146
+ var n uint64
147
+ var err error
169
148
switch f := m .Fields [i ].Type .(type ) {
170
149
case FieldIntFixed :
171
- f .Value , err = decodeFixed (r , f .Length )
150
+ f .Value , n , err = decodeFixed (data , pos , f .Length )
172
151
if err != nil {
173
152
return err
174
153
}
175
154
m .Fields [i ].Type = f
176
155
case FieldUintVar :
177
- val , err := decodeVar (r , true )
156
+ var val interface {}
157
+ val , n , err = decodeVar (data , pos , true )
178
158
if err != nil {
179
159
return err
180
160
}
@@ -185,7 +165,8 @@ func Unmarshal(data []byte, v interface{}) error {
185
165
}
186
166
m .Fields [i ].Type = f
187
167
case FieldIntVar :
188
- val , err := decodeVar (r , false )
168
+ var val interface {}
169
+ val , n , err = decodeVar (data , pos , false )
189
170
if err != nil {
190
171
return err
191
172
}
@@ -196,14 +177,15 @@ func Unmarshal(data []byte, v interface{}) error {
196
177
}
197
178
m .Fields [i ].Type = f
198
179
case FieldString :
199
- f .Value , err = decodeString (r )
180
+ f .Value , n , err = decodeString (data , pos )
200
181
if err != nil {
201
182
return err
202
183
}
203
184
m .Fields [i ].Type = f
204
185
default :
205
186
return fmt .Errorf ("unsupported field type: %T" , m .Fields [i ].Type )
206
187
}
188
+ pos = n
207
189
}
208
190
209
191
default :
@@ -212,105 +194,88 @@ func Unmarshal(data []byte, v interface{}) error {
212
194
return nil
213
195
}
214
196
215
- func decodeString (r io.Reader ) (string , error ) {
216
- firstByte := make ([]byte , 1 )
217
- _ , err := r .Read (firstByte )
218
- if err != nil {
219
- return "" , err
197
+ func decodeString (data []byte , pos uint64 ) (string , uint64 , error ) {
198
+ if len (data ) < int (pos )+ 1 {
199
+ return "" , pos , errors .New ("string truncated, expected at least one byte" )
220
200
}
221
- strBytes := make ([] byte , firstByte [ 0 ] >> 1 )
222
- n , err := r . Read ( strBytes )
223
- if err != nil {
224
- return "" , err
201
+ strLen := int ( data [ pos ] >> 1 )
202
+ pos ++
203
+ if len ( data ) < int ( pos ) + strLen {
204
+ return "" , pos , fmt . Errorf ( "string truncated, expected length: %d" , strLen )
225
205
}
226
- if n != int (firstByte [0 ] >> 1 ) {
227
- return "" , fmt .Errorf ("only read %d bytes, expected %d" , n , firstByte [0 ]/ 2 )
228
- }
229
- return string (strBytes ), nil
206
+ return string (data [pos : pos + uint64 (strLen )]), pos + uint64 (strLen ), nil
230
207
}
231
208
232
- func decodeFixed (r io. Reader , len int ) ([]byte , error ) {
209
+ func decodeFixed (data [] byte , pos uint64 , intlen int ) ([]byte , uint64 , error ) {
233
210
var b bytes.Buffer
234
211
235
- tmpInt := make ([]byte , 1 )
236
212
for {
237
- _ , err := r .Read (tmpInt )
238
- if err != nil {
239
- return nil , err
213
+ if len (data ) < int (pos )+ 1 {
214
+ return b .Bytes (), pos , errors .New ("data truncated" )
240
215
}
241
- if tmpInt [ 0 ]% 2 == 0 {
242
- b .WriteByte (tmpInt [ 0 ] >> 1 )
216
+ if data [ pos ]% 2 == 0 {
217
+ b .WriteByte (data [ pos ] >> 1 )
243
218
} else {
244
- tmpInt2 := make ([]byte , 1 )
245
- _ , err := r .Read (tmpInt2 )
246
- if err != nil {
247
- return nil , err
219
+ if len (data ) < int (pos )+ 2 {
220
+ return b .Bytes (), pos , errors .New ("data truncated" )
248
221
}
249
- switch tmpInt2 [ 0 ] {
222
+ switch data [ pos + 1 ] {
250
223
case 0x2 :
251
- b .WriteByte ((tmpInt [ 0 ] >> 2 ) + 0x80 )
224
+ b .WriteByte ((data [ pos ] >> 2 ) + 0x80 )
252
225
case 0x3 :
253
- b .WriteByte ((tmpInt [ 0 ] >> 2 ) + 0xc0 )
226
+ b .WriteByte ((data [ pos ] >> 2 ) + 0xc0 )
254
227
default :
255
- return nil , fmt .Errorf ("unknown decoding for %v" , tmpInt2 [ 0 ])
228
+ return nil , pos , fmt .Errorf ("unknown decoding for %v" , data [ pos ])
256
229
}
230
+ pos ++
257
231
}
258
- if b .Len () == len {
232
+ pos ++
233
+ if b .Len () == intlen {
259
234
break
260
235
}
261
236
}
262
- return b .Bytes (), nil
237
+ return b .Bytes (), pos , nil
263
238
}
264
239
265
- func decodeVar (r io.ReadSeeker , unsigned bool ) (interface {}, error ) {
266
- firstByte := make ([]byte , 1 )
267
- _ , err := r .Read (firstByte )
268
- if err != nil {
269
- return 0 , err
270
- }
271
- tb := trailingOneBitCount (firstByte [0 ])
272
- _ , err = r .Seek (- 1 , io .SeekCurrent )
273
- if err != nil {
274
- return 0 , err
275
- }
276
- fieldBytes := make ([]byte , tb + 1 )
277
- n , err := r .Read (fieldBytes )
278
- if err != nil {
279
- return 0 , err
240
+ func decodeVar (data []byte , pos uint64 , unsigned bool ) (interface {}, uint64 , error ) {
241
+ if len (data ) < int (pos )+ 1 {
242
+ return 0 , pos , errors .New ("data truncated" )
280
243
}
281
- if n != tb + 1 {
282
- return 0 , fmt .Errorf ("only read %d bytes, expected %d" , n , tb + 1 )
244
+ flen := trailingOneBitCount (data [pos ]) + 1
245
+ if len (data ) < int (pos )+ flen {
246
+ return 0 , pos , fmt .Errorf ("truncated data, expected length: %d" , flen )
283
247
}
284
248
var tNum uint64
285
- switch len ( fieldBytes ) {
249
+ switch flen {
286
250
case 1 :
287
- tNum = uint64 (fieldBytes [ 0 ])
251
+ tNum = uint64 (data [ pos ])
288
252
case 2 :
289
- tNum = uint64 (binary .LittleEndian .Uint16 (fieldBytes ))
253
+ tNum = uint64 (binary .LittleEndian .Uint16 (data [ pos : int ( pos ) + flen ] ))
290
254
case 3 :
291
255
tNum = uint64 (binary .LittleEndian .Uint32 (
292
- slices .Concat (fieldBytes , []byte {0x0 })))
256
+ slices .Concat (data [ pos : int ( pos ) + flen ] , []byte {0x0 })))
293
257
case 4 :
294
- tNum = uint64 (binary .LittleEndian .Uint32 (fieldBytes ))
258
+ tNum = uint64 (binary .LittleEndian .Uint32 (data [ pos : int ( pos ) + flen ] ))
295
259
case 5 :
296
260
tNum = binary .LittleEndian .Uint64 (
297
- slices .Concat (fieldBytes , []byte {0x0 , 0x0 , 0x0 }))
261
+ slices .Concat (data [ pos : int ( pos ) + flen ] , []byte {0x0 , 0x0 , 0x0 }))
298
262
case 6 :
299
263
tNum = binary .LittleEndian .Uint64 (
300
- slices .Concat (fieldBytes , []byte {0x0 , 0x0 }))
264
+ slices .Concat (data [ pos : int ( pos ) + flen ] , []byte {0x0 , 0x0 }))
301
265
case 7 :
302
266
tNum = binary .LittleEndian .Uint64 (
303
- slices .Concat (fieldBytes , []byte {0x0 }))
267
+ slices .Concat (data [ pos : int ( pos ) + flen ] , []byte {0x0 }))
304
268
case 8 :
305
- tNum = binary .LittleEndian .Uint64 (fieldBytes )
269
+ tNum = binary .LittleEndian .Uint64 (data [ pos : int ( pos ) + flen ] )
306
270
}
271
+ pos += uint64 (flen )
307
272
if unsigned {
308
- return tNum >> ( tb + 1 ) , nil
273
+ return tNum >> flen , pos , nil
309
274
}
310
- if positive := (tNum >> ( tb + 1 ) )& 1 == 0 ; positive {
311
- return int64 (tNum >> (tb + 2 )) , nil
275
+ if positive := (tNum >> flen )& 1 == 0 ; positive {
276
+ return int64 (tNum >> (flen + 1 )), pos , nil
312
277
}
313
- return int64 (- (1 + (tNum >> (tb + 2 )))), nil
278
+ return int64 (- (1 + (tNum >> (flen + 1 )))), pos , nil
314
279
}
315
280
316
281
func trailingOneBitCount (b byte ) int {
0 commit comments