// 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"
	"v.io/v23/verror"
)

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)
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
}

type decoder81 struct {
	buf        *decbuf
	flag       decFlag
	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
)

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 }

// 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)
	typeDec := newTypeDecoderInternal(buf)
	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) 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.stack = append(d.stack, decStackEntry{
		Type:    wireTypeType,
		Index:   -1,
		LenHint: 1, // wireType is a union
	})
	d.flag = d.flag.Set(decFlagIgnoreNextStartValue)
	if err := __VDLRead_wireType(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.stack = append(d.stack, 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) {
	// 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.Skip(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 !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
	}
	top := d.top()
	if 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
		} else {
			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() (string, error) {
	top := d.top()
	if top == nil {
		return "", 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 "", fmt.Errorf("vom: NextField called after done, stack: %+v", d.stack)
		}
	default:
		return "", 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 "", nil
		}
		// Decode the union field index.
		switch index, err := binaryDecodeUint(d.buf); {
		case err != nil:
			return "", err
		case index >= uint64(top.Type.NumField()):
			return "", verror.New(errIndexOutOfRange, nil)
		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:
		// Decode the struct field index.
		switch index, ctrl, err := binaryDecodeUintWithControl(d.buf); {
		case err != nil:
			return "", err
		case ctrl == WireCtrlEnd:
			// Set Index=LenHint to ensure repeated calls will fail.
			top.Index = top.LenHint
			return "", nil
		case ctrl != 0:
			return "", verror.New(errUnexpectedControlByte, nil, ctrl)
		case index >= uint64(top.Type.NumField()):
			return "", verror.New(errIndexOutOfRange, nil)
		default:
			field = int(index)
			top.Index = field
		}
	}
	return top.Type.Field(field).Name, 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 {
		// Becuase 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) {
	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) {
	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)
}
