/
decoder.go
822 lines (766 loc) · 23.9 KB
/
decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vom
import (
"errors"
"fmt"
"io"
"math"
"os"
"v.io/v23/vdl"
)
const (
// IEEE 754 represents float64 using 52 bits to represent the mantissa, with
// an extra implied leading bit. That gives us 53 bits to store integers
// without overflow - i.e. [0, (2^53)-1]. And since 2^53 is a small power of
// two, it can also be stored without loss via mantissa=1 exponent=53. Thus
// we have our max and min values. Ditto for float32, which uses 23 bits with
// an extra implied leading bit.
float64MaxInt = (1 << 53)
float64MinInt = -(1 << 53)
float32MaxInt = (1 << 24)
float32MinInt = -(1 << 24)
)
var (
errEmptyDecoderStack = errors.New("vom: empty decoder stack")
errReadRawBytesAlreadyStarted = errors.New("vom: read into vom.RawBytes after StartValue called")
errReadRawBytesFromNonAny = errors.New("vom: read into vom.RawBytes only supported on any values")
)
// This is only used for debugging; add this as the first line of NewDecoder to
// dump formatted vom bytes to stdout:
// r = teeDump(r)
//nolint:deadcode,unused
func teeDump(r io.Reader) io.Reader {
return io.TeeReader(r, NewDumper(NewDumpWriter(os.Stdout)))
}
// Decoder manages the receipt and unmarshalling of typed values from the other
// side of a connection.
type Decoder struct {
dec decoder81
}
const reservedCodec81StackSize = 2
type decoder81 struct {
buf *decbuf
flag decFlag
stackStorage [reservedCodec81StackSize]decStackEntry
stack []decStackEntry
refTypes referencedTypes
refAnyLens referencedAnyLens
typeDec *TypeDecoder
}
type decStackEntry struct {
Type *vdl.Type // Type of the value that we're decoding.
Index int // Index of the key, elem or field.
LenHint int // Length of the value, or -1 for unknown.
NextEntryType *vdl.Type // type for NextEntryValue* methods
Flag decStackFlag // properties of this stack entry
NextEntryData nextEntryData // properties of the next entry
}
// decFlag holds properties of the decoder.
type decFlag uint
const (
decFlagIgnoreNextStartValue decFlag = 0x1 // ignore the next call to StartValue
decFlagIsParentBytes decFlag = 0x2 // parent type is []byte or [N]byte
decFlagTypeIncomplete decFlag = 0x4 // type has dependencies on unsent types
decFlagSeparateTypeDec decFlag = 0x8 // type decoder is separate
// In FinishValue we need to clear both of these bits.
decFlagFinishValue decFlag = decFlagIgnoreNextStartValue | decFlagIsParentBytes
)
func (f decFlag) Set(bits decFlag) decFlag { return f | bits }
func (f decFlag) Clear(bits decFlag) decFlag { return f &^ bits }
func (f decFlag) IgnoreNextStartValue() bool { return f&decFlagIgnoreNextStartValue != 0 }
func (f decFlag) IsParentBytes() bool { return f&decFlagIsParentBytes != 0 }
func (f decFlag) TypeIncomplete() bool { return f&decFlagTypeIncomplete != 0 }
func (f decFlag) SeparateTypeDec() bool { return f&decFlagSeparateTypeDec != 0 }
// decStackFlag holds type or value properties of the stack entry.
type decStackFlag uint
const (
decStackFlagIsMapKey decStackFlag = 0x1 // key or elem for dfsNextType
decStackFlagIsAny decStackFlag = 0x2 // the static type is Any
decStackFlagIsOptional decStackFlag = 0x4 // the static type is Optional
decStackFlagFastRead decStackFlag = 0x8 // subtypes use ReadValue fastpath
)
func (f decStackFlag) FlipIsMapKey() decStackFlag { return f ^ decStackFlagIsMapKey }
func (f decStackFlag) IsMapKey() bool { return f&decStackFlagIsMapKey != 0 }
func (f decStackFlag) IsAny() bool { return f&decStackFlagIsAny != 0 }
func (f decStackFlag) IsOptional() bool { return f&decStackFlagIsOptional != 0 }
func (f decStackFlag) FastRead() bool { return f&decStackFlagFastRead != 0 }
// NewDecoder returns a new Decoder that reads from the given reader. The
// Decoder understands all formats generated by the Encoder.
func NewDecoder(r io.Reader) *Decoder {
buf := newDecbuf(r)
dec := &decoder81{buf: buf}
typeDec := newTypeDecoderInternal(dec)
return &Decoder{decoder81{
buf: buf,
typeDec: typeDec,
}}
}
// NewDecoderWithTypeDecoder returns a new Decoder that reads from the given
// reader. Types are decoded separately through the typeDec.
func NewDecoderWithTypeDecoder(r io.Reader, typeDec *TypeDecoder) *Decoder {
return &Decoder{decoder81{
buf: newDecbuf(r),
typeDec: typeDec,
flag: decFlagSeparateTypeDec,
}}
}
// Decoder returns d as a vdl.Decoder.
func (d *Decoder) Decoder() vdl.Decoder {
return &d.dec
}
// Decode reads the next value and stores it in value v. The type of v need not
// exactly match the type of the originally encoded value; decoding succeeds as
// long as the values are convertible.
func (d *Decoder) Decode(v interface{}) error {
return vdl.Read(&d.dec, v)
}
func (d *decoder81) reset(buf *decbuf) {
d.buf = buf
d.flag = 0
d.stack = d.stackStorage[:0]
d.refTypes = referencedTypes{}
d.refAnyLens = referencedAnyLens{}
d.typeDec = nil
}
func (d *decoder81) appendStack(entry decStackEntry) {
// TODO(cnicolaou): get rid of this test by ensuring that the
// stack is properly initialized when a decoder81 is
// created.
if d.stack == nil {
d.stack = d.stackStorage[:0]
}
d.stack = append(d.stack, entry)
}
func (d *decoder81) IgnoreNextStartValue() {
d.flag = d.flag.Set(decFlagIgnoreNextStartValue)
}
func (d *decoder81) decodeWireType(wt *wireType) (TypeId, error) {
// Type messages are just a regularly encoded wireType, which is a union. To
// decode we pre-populate the stack with an entry for the wire type, and run
// the code-generated __VDLRead_wireType method.
tid, err := d.nextMessage()
if err != nil {
return 0, err
}
d.appendStack(decStackEntry{
Type: wireTypeType,
Index: -1,
LenHint: 1, // wireType is a union
})
d.flag = d.flag.Set(decFlagIgnoreNextStartValue)
if err := vdlReadwireType(d, wt); err != nil {
return 0, err
}
return tid, nil
}
// readRawBytes fills in raw with the next value. It can be called for both
// top-level and internal values.
func (d *decoder81) readRawBytes(raw *RawBytes) error {
if d.flag.IgnoreNextStartValue() {
// If the user has already called StartValue on the decoder, it's harder to
// capture all the raw bytes, since the optional flag and length hints have
// already been decoded. So we simply disallow this from happening.
return errReadRawBytesAlreadyStarted
}
tt, err := d.dfsNextType()
if err != nil {
return err
}
// Handle top-level values. All types of values are supported, since we can
// simply copy the message bytes.
if len(d.stack) == 0 {
anyLen, err := d.peekValueByteLen(tt)
if err != nil {
return err
}
if err := d.decodeRaw(tt, anyLen, raw); err != nil {
return err
}
return d.endMessage()
}
// Handle internal values. Only any values are supported at the moment, since
// they come with a header that tells us the exact length to read.
//
// TODO(toddw): Handle other types, either by reading and skipping bytes based
// on the type, or by falling back to a decode / re-encode slowpath.
if tt.Kind() != vdl.Any {
return errReadRawBytesFromNonAny
}
ttElem, anyLen, err := d.readAnyHeader()
if err != nil {
return err
}
if ttElem == nil {
// This is a nil any value, which has already been read by readAnyHeader.
// We simply fill in RawBytes with the single WireCtrlNil byte.
raw.Version = d.buf.version
raw.Type = vdl.AnyType
raw.RefTypes = nil
raw.AnyLengths = nil
raw.Data = []byte{WireCtrlNil}
return nil
}
return d.decodeRaw(ttElem, anyLen, raw)
}
func (d *decoder81) StartValue(want *vdl.Type) error {
if d.flag.IgnoreNextStartValue() {
d.flag = d.flag.Clear(decFlagIgnoreNextStartValue)
return nil
}
tt, err := d.dfsNextType()
if err != nil {
return err
}
tt, lenHint, flag, err := d.setupType(tt, want)
if err != nil {
return err
}
d.appendStack(decStackEntry{
Type: tt,
Index: -1,
LenHint: lenHint,
Flag: flag,
})
return nil
}
func (d *decoder81) setupType(tt, want *vdl.Type) (_ *vdl.Type, lenHint int, flag decStackFlag, _ error) { //nolint:gocyclo
// Handle any, which may be nil. We "dereference" non-nil any to the inner
// type. If that happens to be an optional, it's handled below.
if tt.Kind() == vdl.Any {
flag |= decStackFlagIsAny
var err error
switch tt, _, err = d.readAnyHeader(); {
case err != nil:
return nil, 0, 0, err
case tt == nil:
tt = vdl.AnyType // nil any
}
}
// Handle optional, which may be nil. Similar to any, we "dereference"
// non-nil optional to the inner type, which is never allowed to be another
// optional or any type.
if tt.Kind() == vdl.Optional {
flag |= decStackFlagIsOptional
// Read the WireCtrlNil code, but if it's not WireCtrlNil we need to keep
// the buffer as-is, since it's the first byte of the value, which may
// itself be another control code.
switch ctrl, err := binaryPeekControl(d.buf); {
case err != nil:
return nil, 0, 0, err
case ctrl == WireCtrlNil:
d.buf.SkipAvailable(1) // nil optional
default:
tt = tt.Elem() // non-nil optional
}
}
// Check compatibility between the actual type and the want type. Since
// compatibility applies to the entire static type, we only need to perform
// this check for top-level decoded values, and subsequently for decoded any
// values. We skip checking non-composite want types, since those will be
// naturally caught by the Decode* calls anyways.
if want != nil && (len(d.stack) == 0 || flag.IsAny()) {
switch want.Kind() {
case vdl.Optional, vdl.Array, vdl.List, vdl.Set, vdl.Map, vdl.Struct, vdl.Union:
if tt == want {
// Set FastRead flag, which will let us use the fastpath for ReadValue*
// in common cases. We can only use this fastpath if tt and want are
// identical, which ensures we don't need to perform any conversions.
if !flag.IsAny() && isFastReadParent(tt) {
flag |= decStackFlagFastRead
}
// Regardless of whether we can use the fastpath, there's no need to
// check compatibility if tt and want are identical.
} else {
if !vdl.Compatible(tt, want) {
return nil, 0, 0, errIncompatibleDecode(tt, want)
}
}
}
}
// Initialize LenHint for composite types.
switch tt.Kind() {
case vdl.Array, vdl.List, vdl.Set, vdl.Map:
// TODO(toddw): Handle sentry-terminated collections without a length hint.
len, err := binaryDecodeLenOrArrayLen(d.buf, tt)
if err != nil {
return nil, 0, 0, err
}
lenHint = len
case vdl.Union:
// Union shouldn't have a LenHint, but we abuse it in NextField as a
// convenience for detecting when fields are done, so we initialize it here.
// It has to be at least 1, since 0 will cause NextField to think that the
// union field has already been decoded.
lenHint = 1
case vdl.Struct:
// Struct shouldn't have a LenHint, but we abuse it in NextField as a
// convenience for detecting when fields are done, so we initialize it here.
lenHint = tt.NumField()
default:
lenHint = -1
}
if top := d.top(); top != nil && top.Type.IsBytes() {
d.flag = d.flag.Set(decFlagIsParentBytes)
} else {
d.flag = d.flag.Clear(decFlagIsParentBytes)
}
return tt, lenHint, flag, nil
}
func errIncompatibleDecode(tt *vdl.Type, want interface{}) error {
return fmt.Errorf("vom: incompatible decode from %v into %v", tt, want)
}
func (d *decoder81) FinishValue() error {
d.flag = d.flag.Clear(decFlagFinishValue)
stackTop := len(d.stack) - 1
if stackTop == -1 {
return errEmptyDecoderStack
}
d.stack = d.stack[:stackTop]
if stackTop == 0 {
return d.endMessage()
}
return nil
}
func (d *decoder81) top() *decStackEntry {
if stackTop := len(d.stack) - 1; stackTop >= 0 {
return &d.stack[stackTop]
}
return nil
}
// dfsNextType determines the type of the next value that we will decode, by
// walking the static type in DFS order. To bootstrap we retrieve the top-level
// type from the VOM value message.
func (d *decoder81) dfsNextType() (*vdl.Type, error) {
top := d.top()
if top == nil {
// Bootstrap: start decoding a new top-level value.
if !d.flag.SeparateTypeDec() {
if err := d.decodeTypeDefs(); err != nil {
return nil, err
}
}
tid, err := d.nextMessage()
if err != nil {
return nil, err
}
return d.typeDec.lookupType(tid)
}
// Return the next type from our composite types.
tt := top.Type
switch tt.Kind() {
case vdl.Array, vdl.List:
return tt.Elem(), nil
case vdl.Set:
return tt.Key(), nil
case vdl.Map:
top.Flag = top.Flag.FlipIsMapKey()
if top.Flag.IsMapKey() {
return tt.Key(), nil
}
return tt.Elem(), nil
case vdl.Union, vdl.Struct:
return tt.Field(top.Index).Type, nil
}
return nil, fmt.Errorf("vom: can't StartValue on %v", tt)
}
func (d *decoder81) NextEntry() (bool, error) {
// Our strategy is to increment top.Index until it reaches top.LenHint.
// Currently the LenHint is always set, so it's stronger than a hint.
//
// TODO(toddw): Handle sentry-terminated collections without a LenHint.
top := d.top()
if top == nil {
return false, errEmptyDecoderStack
}
// Increment index and check errors.
top.Index++
switch top.Type.Kind() {
case vdl.Array, vdl.List, vdl.Set, vdl.Map:
if top.Index > top.LenHint && top.LenHint >= 0 {
return false, fmt.Errorf("vom: NextEntry called after done, stack: %+v", d.stack)
}
default:
return false, fmt.Errorf("vom: NextEntry called on invalid type, stack: %+v", d.stack)
}
return top.Index == top.LenHint, nil
}
func (d *decoder81) NextField() (int, error) { //nolint:gocyclo
top := d.top()
if top == nil {
return -1, errEmptyDecoderStack
}
// Increment index and check errors. Note that the actual top.Index is
// decoded from the buf data stream; we use top.LenHint to help detect when
// the fields are done, and to detect invalid calls after we're done.
top.Index++
switch top.Type.Kind() {
case vdl.Union, vdl.Struct:
if top.Index > top.LenHint {
return -1, fmt.Errorf("vom: NextField called after done, stack: %+v", d.stack)
}
default:
return -1, fmt.Errorf("vom: NextField called on invalid type, stack: %+v", d.stack)
}
var field int
switch top.Type.Kind() {
case vdl.Union:
if top.Index == top.LenHint {
// We know we're done since we set LenHint=Index+1 the first time around,
// and we incremented the index above.
return -1, nil
}
// Decode the union field index.
switch index, err := binaryDecodeUint(d.buf); {
case err != nil:
return -1, err
case index >= uint64(top.Type.NumField()):
return -1, errIndexOutOfRange
default:
// Set LenHint=Index+1 so that we'll know we're done next time around.
field = int(index)
top.Index = field
top.LenHint = field + 1
}
case vdl.Struct:
// Handle the end-of-struct sentry.
switch ok, err := binaryDecodeControlOnly(d.buf, WireCtrlEnd); {
case err != nil:
return -1, err
case ok:
// Set Index=LenHint to ensure repeated calls will fail.
top.Index = top.LenHint
return -1, nil
}
// Decode the struct field index.
switch index, err := binaryDecodeUint(d.buf); {
case err != nil:
return -1, err
case index >= uint64(top.Type.NumField()):
return -1, errIndexOutOfRange
default:
field = int(index)
top.Index = field
}
}
return field, nil
}
func (d *decoder81) Type() *vdl.Type {
if top := d.top(); top != nil {
return top.Type
}
return nil
}
func (d *decoder81) IsAny() bool {
if top := d.top(); top != nil {
return top.Flag.IsAny()
}
return false
}
func (d *decoder81) IsOptional() bool {
if top := d.top(); top != nil {
return top.Flag.IsOptional()
}
return false
}
func (d *decoder81) IsNil() bool {
if top := d.top(); top != nil {
// Because of the "dereferencing" we do, the only time the type is any or
// optional is when it's nil.
return top.Type == vdl.AnyType || top.Type.Kind() == vdl.Optional
}
return false
}
func (d *decoder81) Index() int {
if top := d.top(); top != nil {
return top.Index
}
return -1
}
func (d *decoder81) LenHint() int {
if top := d.top(); top != nil {
// Note that union and struct shouldn't have a LenHint, but we abuse it in
// NextField as a convenience for detecting when fields are done, so an
// "arbitrary" value is returned here. Users shouldn't be looking at it for
// union and struct anyways.
return top.LenHint
}
return -1
}
func (d *decoder81) DecodeBool() (bool, error) {
tt := d.Type()
if tt == nil {
return false, errEmptyDecoderStack
}
if tt.Kind() == vdl.Bool {
return binaryDecodeBool(d.buf)
}
return false, errIncompatibleDecode(tt, "bool")
}
func (d *decoder81) DecodeString() (string, error) {
tt := d.Type()
if tt == nil {
return "", errEmptyDecoderStack
}
switch tt.Kind() {
case vdl.String:
return binaryDecodeString(d.buf)
case vdl.Enum:
return d.binaryDecodeEnum(tt)
}
return "", errIncompatibleDecode(tt, "string")
}
func (d *decoder81) binaryDecodeEnum(tt *vdl.Type) (string, error) {
index, err := binaryDecodeUint(d.buf)
switch {
case err != nil:
return "", err
case index >= uint64(tt.NumEnumLabel()):
return "", fmt.Errorf("vom: enum index %d out of range, %v", index, tt)
}
return tt.EnumLabel(int(index)), nil
}
func (d *decoder81) binaryDecodeByte() (byte, error) {
// Handle a special-case where normally single bytes are written out as
// variable sized numbers, which use 2 bytes to encode bytes > 127. But each
// byte contained in a list or array is written out as one byte. E.g.
// byte(0x81) -> 0xFF81 : single byte with variable-size
// []byte("\x81\x82") -> 0x028182 : each elem byte encoded as one byte
if d.flag.IsParentBytes() {
return d.buf.ReadByte()
}
x, err := binaryDecodeUint(d.buf)
return byte(x), err
}
func (d *decoder81) DecodeUint(bitlen int) (uint64, error) {
tt := d.Type()
if tt == nil {
return 0, errEmptyDecoderStack
}
return d.decodeUint(tt, uint(bitlen))
}
func (d *decoder81) decodeUint(tt *vdl.Type, ubitlen uint) (uint64, error) {
const errFmt = "vom: conversion from %v into uint%d loses precision: %v"
switch tt.Kind() {
case vdl.Byte:
x, err := d.binaryDecodeByte()
if err != nil {
return 0, err
}
return uint64(x), err
case vdl.Uint16, vdl.Uint32, vdl.Uint64:
x, err := binaryDecodeUint(d.buf)
if err != nil {
return 0, err
}
if shift := 64 - ubitlen; x != (x<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return x, nil
case vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64:
x, err := binaryDecodeInt(d.buf)
if err != nil {
return 0, err
}
ux := uint64(x)
if shift := 64 - ubitlen; x < 0 || ux != (ux<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return ux, nil
case vdl.Float32, vdl.Float64:
x, err := binaryDecodeFloat(d.buf)
if err != nil {
return 0, err
}
ux := uint64(x)
if shift := 64 - ubitlen; x != float64(ux) || ux != (ux<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return ux, nil
}
return 0, errIncompatibleDecode(tt, fmt.Sprintf("uint%d", ubitlen))
}
func (d *decoder81) DecodeInt(bitlen int) (int64, error) {
tt := d.Type()
if tt == nil {
return 0, errEmptyDecoderStack
}
return d.decodeInt(tt, uint(bitlen))
}
func (d *decoder81) decodeInt(tt *vdl.Type, ubitlen uint) (int64, error) { //nolint:gocyclo
const errFmt = "vom: conversion from %v into int%d loses precision: %v"
switch tt.Kind() {
case vdl.Byte:
x, err := d.binaryDecodeByte()
if err != nil {
return 0, err
}
// The only case that fails is if we're converting byte(x) to int8, and x
// uses more than 7 bits (i.e. is greater than 127).
if ubitlen <= 8 && x > 0x7f {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return int64(x), nil
case vdl.Uint16, vdl.Uint32, vdl.Uint64:
x, err := binaryDecodeUint(d.buf)
if err != nil {
return 0, err
}
ix := int64(x)
// The shift uses 65 since the topmost bit is the sign bit. I.e. 32 bit
// numbers should be shifted by 33 rather than 32.
if shift := 65 - ubitlen; ix < 0 || x != (x<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return ix, nil
case vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64:
x, err := binaryDecodeInt(d.buf)
if err != nil {
return 0, err
}
if shift := 64 - ubitlen; x != (x<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return x, nil
case vdl.Float32, vdl.Float64:
x, err := binaryDecodeFloat(d.buf)
if err != nil {
return 0, err
}
ix := int64(x)
if shift := 64 - ubitlen; x != float64(ix) || ix != (ix<<shift)>>shift {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return ix, nil
}
return 0, errIncompatibleDecode(tt, fmt.Sprintf("int%d", ubitlen))
}
func (d *decoder81) DecodeFloat(bitlen int) (float64, error) {
tt := d.Type()
if tt == nil {
return 0, errEmptyDecoderStack
}
return d.decodeFloat(tt, uint(bitlen))
}
func (d *decoder81) decodeFloat(tt *vdl.Type, ubitlen uint) (float64, error) { //nolint:gocyclo
const errFmt = "vom: conversion from %v into float%d loses precision: %v"
switch tt.Kind() {
case vdl.Byte:
x, err := d.binaryDecodeByte()
if err != nil {
return 0, err
}
return float64(x), nil
case vdl.Uint16, vdl.Uint32, vdl.Uint64:
x, err := binaryDecodeUint(d.buf)
if err != nil {
return 0, err
}
var max uint64
if ubitlen > 32 {
max = float64MaxInt
} else {
max = float32MaxInt
}
if x > max {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return float64(x), nil
case vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64:
x, err := binaryDecodeInt(d.buf)
if err != nil {
return 0, err
}
var min, max int64
if ubitlen > 32 {
min, max = float64MinInt, float64MaxInt
} else {
min, max = float32MinInt, float32MaxInt
}
if x < min || x > max {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return float64(x), nil
case vdl.Float32, vdl.Float64:
x, err := binaryDecodeFloat(d.buf)
if err != nil {
return 0, err
}
if ubitlen <= 32 && (x < -math.MaxFloat32 || x > math.MaxFloat32) {
return 0, fmt.Errorf(errFmt, tt, ubitlen, x)
}
return x, nil
}
return 0, errIncompatibleDecode(tt, fmt.Sprintf("float%d", ubitlen))
}
func (d *decoder81) DecodeBytes(fixedLen int, v *[]byte) error {
top := d.top()
if top == nil {
return errEmptyDecoderStack
}
tt := top.Type
if !tt.IsBytes() {
return vdl.DecodeConvertedBytes(d, fixedLen, v)
}
return d.decodeBytes(tt, top.LenHint, fixedLen, v)
}
func (d *decoder81) decodeBytes(tt *vdl.Type, lenHint, fixedLen int, v *[]byte) error {
switch {
case lenHint == -1:
return fmt.Errorf("vom: LenHint is currently required, %v", tt)
case fixedLen >= 0 && fixedLen != lenHint:
return fmt.Errorf("vom: got %d bytes, want fixed len %d, %v", lenHint, fixedLen, tt)
case lenHint == 0:
*v = nil
return nil
case fixedLen >= 0:
// Only re-use the existing buffer if we're filling in an array. This
// sacrifices some performance, but also avoids bugs when repeatedly
// decoding into the same value.
*v = (*v)[:lenHint]
default:
*v = make([]byte, lenHint)
}
return d.buf.ReadIntoBuf(*v)
}
func (d *decoder81) DecodeTypeObject() (*vdl.Type, error) {
tt := d.Type()
if tt == nil {
return nil, errEmptyDecoderStack
}
if tt != vdl.TypeObjectType {
return nil, errIncompatibleDecode(tt, "typeobject")
}
return d.binaryDecodeType()
}
func (d *decoder81) binaryDecodeType() (*vdl.Type, error) {
typeIndex, err := binaryDecodeUint(d.buf)
if err != nil {
return nil, err
}
tid, err := d.refTypes.ReferencedTypeID(typeIndex)
if err != nil {
return nil, err
}
return d.typeDec.lookupType(tid)
}
func (d *decoder81) SkipValue() error {
tt, err := d.dfsNextType()
if err != nil {
return err
}
if len(d.stack) == 0 {
// Handle top-level values. It's easy to determine the byte length of the
// value, so we can just skip the bytes.
valueLen, err := d.peekValueByteLen(tt)
if err != nil {
return err
}
if err := d.buf.Skip(valueLen); err != nil {
return err
}
return d.endMessage()
}
return d.skipValue(tt)
}