// Copyright 2015 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 vdl

// Naming conventions to distinguish this package from reflect:
//   tt - refers to *Type
//   vv - refers to *Value
//   rt - refers to reflect.Type
//   rv - refers to reflect.Value

import (
	"errors"
	"fmt"
	"reflect"
)

var (
	ErrFieldNoExist = errors.New("field doesn't exist")

	errTargetInvalid    = errors.New("invalid target")
	errTargetUnsettable = errors.New("unsettable target")
	errArrayIndex       = errors.New("array index out of range")
)

// convTarget represents the state and logic for value conversion.
//
// TODO(toddw): Split convTarget apart into reflectTarget and valueTarget.
type convTarget struct {
	// Conceptually this is a disjoint union between the two types of destination
	// values: *Value and reflect.Value.  Only one of the vv and rv fields is
	// ever valid.  We split into two fields and perform "if vv == nil" checks in
	// each method rather than using an interface for performance reasons.
	//
	// The tt field is always non-nil, and represents the type of the value.
	tt *Type
	vv *Value
	rv reflect.Value
}

// TODO(bprosnitz) Remove this -- it exists to get the reflect value for VOM and avoid package dependency cycles.
func (c convTarget) HackGetRv() reflect.Value {
	return c.rv
}

// ReflectTarget returns a conversion Target based on the given reflect.Value.
// Some rules depending on the type of rv:
//   o If rv is a valid *Value, it is filled in directly.
//   o Otherwise rv must be a settable value (i.e. it must be a pointer).
//   o Pointers are followed, and logically "flattened".
//   o New values are automatically created for nil pointers.
//   o Targets convertible to *Type and *Value are filled in directly.
func ReflectTarget(rv reflect.Value) (Target, error) {
	if !rv.IsValid() {
		return nil, errTargetInvalid
	}
	if vv := extractValue(rv); vv.IsValid() {
		return valueConv(vv), nil
	}
	tt, err := TypeFromReflect(rv.Type())
	if err != nil {
		return nil, err
	}
	if !rv.CanSet() && rv.Kind() == reflect.Ptr && !rv.IsNil() {
		// Dereference the pointer a single time to make rv settable.
		rv = rv.Elem()
	}
	target, err := reflectConv(rv, tt)
	if err != nil {
		return nil, err
	}
	return target, nil
}

// ValueTarget returns a conversion Target based on the given Value.
// Returns an error if the given Value isn't valid.
func ValueTarget(vv *Value) (Target, error) {
	if !vv.IsValid() {
		return nil, errTargetInvalid
	}
	return valueConv(vv), nil
}

func reflectConv(rv reflect.Value, tt *Type) (convTarget, error) {
	if !rv.IsValid() {
		return convTarget{}, errTargetInvalid
	}
	if vv := extractValue(rv); vv.IsValid() {
		return valueConv(vv), nil
	}
	if !rv.CanSet() {
		return convTarget{}, errTargetUnsettable
	}
	return convTarget{tt: tt, rv: rv}, nil
}

func valueConv(vv *Value) convTarget {
	return convTarget{tt: vv.Type(), vv: vv}
}

func extractValue(rv reflect.Value) *Value {
	for rv.Kind() == reflect.Ptr && !rv.IsNil() {
		if rv.Type().ConvertibleTo(rtPtrToValue) {
			return rv.Convert(rtPtrToValue).Interface().(*Value)
		}
		rv = rv.Elem()
	}
	return nil
}

// startConvert prepares to fill in c, converting from type ttFrom.  Returns fin
// and fill which are used by finishConvert to finish the conversion; fin
// represents the final target to assign to, and fill represents the target to
// actually fill in.
func startConvert(c convTarget, ttFrom *Type) (fin, fill convTarget, err error) {
	if ttFrom.Kind() == Any {
		return convTarget{}, convTarget{}, fmt.Errorf("can't convert from type %q - either call target.FromNil or target.From* for the element value", ttFrom)
	}
	if !Compatible(c.tt, ttFrom) {
		return convTarget{}, convTarget{}, fmt.Errorf("types %q and %q aren't compatible", c.tt, ttFrom)
	}
	fin = createFinTarget(c, ttFrom)
	fill, err = createFillTarget(fin, ttFrom)
	if err != nil {
		return convTarget{}, convTarget{}, err
	}
	return fin, fill, nil
}

// setZeroVDLValue checks whether rv is convertible to *Value, and if so,
// sets rv to the zero value of ttFrom, returning the resulting value.
func setZeroVDLValue(rv reflect.Value, ttFrom *Type) *Value {
	if rv.Type().ConvertibleTo(rtPtrToValue) {
		vv := rv.Convert(rtPtrToValue).Interface().(*Value)
		if !vv.IsValid() {
			vv = ZeroValue(ttFrom)
			rv.Set(reflect.ValueOf(vv).Convert(rv.Type()))
		}
		return vv
	}
	return nil
}

// createFinTarget returns the fin target for the conversion, flattening
// pointers and creating new non-nil values as necessary.
func createFinTarget(c convTarget, ttFrom *Type) convTarget {
	if c.vv == nil {
		// Create new pointers down to the final non-pointer value.
		for c.rv.Kind() == reflect.Ptr {
			// Handle case where rv is *Value; fill it in directly.
			if vv := setZeroVDLValue(c.rv, ttFrom); vv.IsValid() {
				if vv.Kind() == Optional {
					vv.Assign(NonNilZeroValue(vv.Type()))
					return convTarget{tt: ttFrom, vv: vv.Elem()}
				}
				return convTarget{tt: ttFrom, vv: vv}
			}
			// Set nil pointers to new pointers.
			if c.rv.IsNil() {
				c.rv.Set(reflect.New(c.rv.Type().Elem()))
			}
			// Stop at *Type to allow TypeObject values to be assigned.
			if c.rv.Type().Elem() == rtType {
				return c
			}
			c.rv = c.rv.Elem()
		}
		if c.tt.Kind() == Optional {
			c.tt = c.tt.Elem() // flatten c.tt to match c.rv
		}
	} else {
		// Create a non-nil value for optional types.
		if c.tt.Kind() == Optional {
			c.vv.Assign(NonNilZeroValue(c.tt))
			c.tt, c.vv = c.tt.Elem(), c.vv.Elem()
		}
	}
	return c
}

// createFillTarget returns the fill target for the conversion, creating new
// values of the appropriate type if necessary.  The fill target must be a
// concrete type; if fin has type interface/any, we'll create a concrete type,
// and finishConvert will assign fin from the fill target.  The type we choose
// to create is either a special-case (error or union), or based on the ttFrom
// type we're converting *from*.
//
// If fin is already a concrete type it's used directly as the fill target.
//
// TODO(toddw): The conversion logic is way too complicated, with many similar
// branches; rewrite this entire file..
func createFillTarget(fin convTarget, ttFrom *Type) (convTarget, error) {
	if fin.vv == nil {
		// Handle case where fin.rv is the native error type; create the standard
		// WireError struct to fill in.
		if ni, err := nativeInfoForError(); err == nil && fin.rv.Type() == ni.NativeType {
			return reflectConv(reflect.New(rtWireError).Elem(), ErrorType.Elem())
		}
		// Handle case where fin.rv is a native type; return the wire type as the
		// fill target, and rely on finishConvert to perform the final step of
		// converting from the wire type to the native type.
		//
		// TODO(toddw): This doesn't handle pointer native types.
		if ni := nativeInfoFromNative(fin.rv.Type()); ni != nil {
			tt, err := TypeFromReflect(ni.WireType)
			if err != nil {
				return convTarget{}, err
			}
			return reflectConv(reflect.New(ni.WireType).Elem(), tt)
		}
		if fin.rv.Kind() == reflect.Interface {
			// We're converting into an interface, so we can't just fill into the fin
			// target directly.  Return the appropriate fill value.
			switch {
			case fin.rv.Type() == rtError || ttFrom == ErrorType:
				// Create the standard WireError struct to fill in, with the pointer.
				return reflectConv(reflect.New(rtWireError).Elem(), ErrorType)
			case ttFrom == ErrorType.Elem():
				// Create the standard WireError struct to fill in, without the pointer.
				return reflectConv(reflect.New(rtWireError).Elem(), ErrorType.Elem())
			case fin.tt.Kind() == Union:
				return reflectConv(reflect.New(fin.rv.Type()).Elem(), fin.tt)
			case fin.tt.Kind() != Any:
				return convTarget{}, fmt.Errorf("internal error - cannot convert to Go type %v vdl type %v from %v", fin.rv.Type(), fin.tt, ttFrom)
			}
			// We're converting into any, and ttFrom is the type we're converting
			// *from*.  First handle the special-case *Type.
			if ttFrom.Kind() == TypeObject {
				return reflectConv(reflect.New(rtPtrToType).Elem(), TypeObjectType)
			}
			// Try to create a reflect.Type out of ttFrom, and if it exists, create a real
			// object to fill in.
			if rt := TypeToReflect(ttFrom); rt != nil {
				if rt.Kind() == reflect.Ptr && ttFrom.Kind() == Optional {
					rt = rt.Elem()
				}
				// Handle case where rt is a native type; return the wire type as the
				// fill target, and rely on finishConvert to perform the final step of
				// converting from the wire type to the native type.
				if ni := nativeInfoFromNative(rt); ni != nil {
					return reflectConv(reflect.New(ni.WireType).Elem(), ttFrom)
				}
				rv := reflect.New(rt).Elem()
				for rv.Kind() == reflect.Ptr {
					rv.Set(reflect.New(rv.Type().Elem()))
					rv = rv.Elem()
				}
				return reflectConv(rv, ttFrom)
			}
			// We don't have the type name in our registry, so create a concrete
			// *Value to fill in, based on ttFrom.
			if ttFrom.Kind() == Optional {
				return convTarget{tt: ttFrom, vv: ZeroValue(ttFrom.Elem())}, nil
			}
			return convTarget{tt: ttFrom, vv: ZeroValue(ttFrom)}, nil
		}
		// We're not converting into an interface, so we can fill into the fin
		// target directly.  Assign an appropriate zero value.
		fin.rv.Set(rvSettableZeroValue(fin.rv.Type(), ttFrom))
	} else {
		switch fin.vv.Kind() {
		case Any:
			if ttFrom.Kind() == Optional {
				return convTarget{tt: ttFrom, vv: ZeroValue(ttFrom.Elem())}, nil
			}
			return convTarget{tt: ttFrom, vv: ZeroValue(ttFrom)}, nil
		default:
			fin.vv.Assign(nil) // start with zero item
		}
	}
	return fin, nil
}

// finishConvert finishes converting a value, taking the fin and fill returned
// by startConvert.  This is necessary since interface/any values are assigned
// by value, and can't be filled in by reference.
func finishConvert(fin, fill convTarget) error {
	// The logic here mirrors the logic in createFillTarget.
	if fin.vv == nil {
		// Handle mirrored case in createFillTarget where fin.rv is the native error
		// type; fill.rv is WireError.
		if ni, err := nativeInfoForError(); err == nil && fin.rv.Type() == ni.NativeType {
			return ni.ToNative(fill.rv, fin.rv.Addr())
		}
		// Handle mirrored case in createFillTarget where fin.rv is a native type;
		// fill.rv is the wire type that has been filled in.
		if ni := nativeInfoFromNative(fin.rv.Type()); ni != nil {
			rvFill := fill.rv
			return ni.ToNative(rvFill, fin.rv.Addr())
		}
		if fin.rv.Kind() == reflect.Interface {
			// The fill value may be set to either rv or vv in startConvert above.
			var rvFill reflect.Value
			if fill.vv == nil {
				rvFill = fill.rv
				// Note: this if statement and the one in the else if block do not correctly
				// support the case of optional wiretypes.
				// TODO(bprosnitz) Fix this
				if fill.rv.Type() == rtWireError && fin.rv.Type() != rtWireError {
					// Handle case where fill.rv has type WireError; if error conversions
					// have been registered with the vdl package, we need to convert to
					// the standard error interface.
					if ni, err := nativeInfoForError(); err == nil {
						newNative := reflect.New(ni.NativeType)
						if err := ni.ToNative(fill.rv, newNative); err != nil {
							return err
						}
						rvFill = newNative.Elem()
					}
				} else if ni := nativeInfoFromWire(fill.rv.Type()); ni != nil && fin.rv.Type() != ni.WireType {
					// Handle case where fill.rv is a wire type with a native type; set
					// rvFill to a new native type and call ToNative to fill it in.
					newNative := reflect.New(ni.NativeType)
					if err := ni.ToNative(fill.rv, newNative); err != nil {
						return err
					}
					rvFill = newNative.Elem()
				}
				if fill.tt.Kind() == Optional {
					// Convert rvFill into a pointer if it should be optional.
					if rvFill.CanAddr() {
						rvFill = rvFill.Addr()
					} else {
						rvNew := reflect.New(rvFill.Type())
						rvNew.Elem().Set(rvFill)
						rvFill = rvNew
					}
				}
			} else {
				switch fill.tt.Kind() {
				case Optional:
					rvFill = reflect.ValueOf(OptionalValue(fill.vv))
				default:
					rvFill = reflect.ValueOf(fill.vv)
				}
			}
			if to, from := fin.rv.Type(), rvFill.Type(); !from.AssignableTo(to) {
				return fmt.Errorf("%v not assignable from %v", to, from)
			}
			fin.rv.Set(rvFill)
		}
	} else {
		switch fin.vv.Kind() {
		case Any:
			if fill.tt.Kind() == Optional {
				fin.vv.Assign(OptionalValue(fill.vv))
			} else {
				fin.vv.Assign(fill.vv)
			}
		}
	}
	return nil
}

var typeobjectOrUnionKind []Kind = []Kind{TypeObject, Union}

// rvSettableZeroValue returns a settable zero value corresponding to rt / tt.
// This isn't trivial since VDL and Go define zero values slightly differently.
// In particular in VDL:
//    TypeObject: AnyType
//    Union:      zero value of the type at index 0
// These are translated into Go as follows, with their standard Go zero values:
//    *Type: nil
//    interface: nil
// Thus we must special-case values of these types.
//
// TODO(toddw): This logic is recursive and complicated because our convTarget
// methods don't take the convTarget as a pointer receiver, so we can't mutate
// the target as we decode.  When we split convTarget into separate valueTarget
// and reflectTarget objects, we should also take the target as a pointer
// receiver.  That'll simplify this logic.
func rvSettableZeroValue(rt reflect.Type, tt *Type) reflect.Value {
	rv := reflect.New(rt).Elem()
	// Easy fastpath; if the type doesn't contain inline typeobject or union, the
	// regular Go zero value is good enough.
	if !tt.ContainsKind(WalkInline, typeobjectOrUnionKind...) {
		return rv
	}
	// Handle typeobject, which has the zero value of AnyType.
	if rtPtrToType.ConvertibleTo(rt) {
		return reflect.ValueOf(AnyType).Convert(rt)
	}
	// Handle composite types with inline subtypes.
	switch {
	case tt.Kind() == Union:
		if nativeInfoFromNative(rt) != nil {
			return rv
		}
		if rt.Kind() == reflect.Struct {
			// Union struct, which represents a single field.
			rv.Field(0).Set(rvSettableZeroValue(rt.Field(0).Type, tt.Field(0).Type))
			return rv
		}
		// Union interface, which represents one of the fields.  Initialize with the
		// zero value of the type at index 0.
		ri, _, err := deriveReflectInfo(rt)
		if err != nil {
			panic(fmt.Errorf("vdl: invalid union type rt: %v tt: %v err: %v", rt, tt, err))
		}
		rv.Set(rvSettableZeroValue(ri.UnionFields[0].RepType, tt.Field(0).Type))
		return rv
	case rt.Kind() == reflect.Array:
		for ix := 0; ix < rt.Len(); ix++ {
			rv.Index(ix).Set(rvSettableZeroValue(rt.Elem(), tt.Elem()))
		}
		return rv
	case rt.Kind() == reflect.Struct:
		for ix := 0; ix < rt.NumField(); ix++ {
			rtField := rt.Field(ix)
			ttField, index := tt.FieldByName(rtField.Name)
			if index < 0 {
				// Ignore fields that aren't described in tt; e.g. unexported fields.
				continue
			}
			rv.Field(ix).Set(rvSettableZeroValue(rtField.Type, ttField.Type))
		}
		return rv
	}
	panic(fmt.Errorf("vdl: rvSettableZeroValue unhandled rt: %v tt: %v", rt, tt))
}

func removeOptional(tt *Type) *Type {
	if tt.Kind() == Optional {
		tt = tt.Elem()
	}
	return tt
}

// makeDirectTarget returns the target representing the underlying value, if the
// underlying value supports direct target access.
func (c convTarget) makeDirectTarget() Target {
	if c.vv == nil {
		rv := c.rv
		if rv.Type().Implements(rtTargeter) {
			if rv.Kind() == reflect.Ptr && rv.IsNil() {
				rv.Set(reflect.New(rv.Type().Elem()))
			}
			return rv.Interface().(Targeter).MakeVDLTarget()
		}
		if rv.CanAddr() {
			rv = rv.Addr()
			if rv.Type().Implements(rtTargeter) {
				return rv.Interface().(Targeter).MakeVDLTarget()
			}
		}
	}
	return nil
}

// FromNil implements the Target interface method.
func (c convTarget) FromNil(tt *Type) error {
	if c.tt == AnyType {
		// Optional is not currently supported for FromNil() direct targets
		// because there is no way to get a generated optional struct target
		// for an arbitrary struct. (the struct target itself doesn't support
		// the FromNil method).
		if target := c.makeDirectTarget(); target != nil {
			return target.FromNil(tt)
		}
	}
	if !Compatible(c.tt, tt) {
		return fmt.Errorf("types %q and %q aren't compatible", c.tt, tt)
	}
	if !tt.CanBeNil() || !c.tt.CanBeNil() {
		return fmt.Errorf("invalid conversion from %v(nil) to %v", tt, c.tt)
	}
	if c.vv == nil {
		// The strategy is to create new pointers down to either a single pointer,
		// or the final interface, and set that to nil.  We create all the pointers
		// to be consistent with our behavior in the non-nil case, where we
		// similarly create all the pointers.  It also makes the tests simpler.
		rv := c.rv
		for rv.Kind() == reflect.Ptr {
			if vv := setZeroVDLValue(rv, tt); vv.IsValid() {
				return nil
			}
			if k := rv.Type().Elem().Kind(); k != reflect.Ptr && k != reflect.Interface {
				break
			}
			// Next elem is a pointer or interface, keep looping.
			if rv.IsNil() {
				rv.Set(reflect.New(rv.Type().Elem()))
			}
			rv = rv.Elem()
		}
		// Now rv.Type is either a single pointer or an interface.  If it is an
		// interface, check to see whether we can create a Go object from tt.
		rt := rv.Type()
		if rv.Kind() == reflect.Interface {
			if rtFromTT := TypeToReflect(tt); rtFromTT != nil {
				rt = rtFromTT
			}
		}
		// Set the zero value of the pointer or interface, which will give us nil of
		// the correct type.
		rv.Set(reflect.Zero(rt))
	} else {
		vvNil := ZeroValue(tt)
		if to, from := c.vv.Type(), vvNil; !to.AssignableFrom(from) {
			return fmt.Errorf("%v not assignable from %v", to, from)
		}
		c.vv.Assign(vvNil)
	}
	return nil
}

// FromBool implements the Target interface method.
func (c convTarget) FromBool(src bool, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromBool(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromBool(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromUint implements the Target interface method.
func (c convTarget) FromUint(src uint64, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromUint(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromUint(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromInt implements the Target interface method.
func (c convTarget) FromInt(src int64, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromInt(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromInt(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromFloat implements the Target interface method.
func (c convTarget) FromFloat(src float64, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromFloat(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromFloat(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromBytes implements the Target interface method.
func (c convTarget) FromBytes(src []byte, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromBytes(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromBytes(src, tt); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromString implements the Target interface method.
func (c convTarget) FromString(src string, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromString(src, tt)
	}
	fin, fill, err := startConvert(c, tt)
	if err != nil {
		return err
	}
	if err := fill.fromString(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

// FromEnumLabel implements the Target interface method.
func (c convTarget) FromEnumLabel(src string, tt *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromEnumLabel(src, tt)
	}
	return c.FromString(src, tt)
}

// FromTypeObject implements the Target interface method.
func (c convTarget) FromTypeObject(src *Type) error {
	if target := c.makeDirectTarget(); target != nil {
		return target.FromTypeObject(src)
	}
	fin, fill, err := startConvert(c, TypeObjectType)
	if err != nil {
		return err
	}
	if err := fill.fromTypeObject(src); err != nil {
		return err
	}
	return finishConvert(fin, fill)
}

func (c convTarget) fromBool(src bool) error {
	if c.vv == nil {
		if c.rv.Kind() == reflect.Bool {
			c.rv.SetBool(src)
			return nil
		}
	} else {
		if c.vv.Kind() == Bool {
			c.vv.AssignBool(src)
			return nil
		}
	}
	return fmt.Errorf("invalid conversion from bool to %v", c.tt)
}

func (c convTarget) fromUint(src uint64) error {
	if c.vv == nil {
		switch kind := c.rv.Kind(); kind {
		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
			if !overflowUint(src, bitlenR(kind)) {
				c.rv.SetUint(src)
				return nil
			}
		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
			if isrc, ok := convertUintToInt(src, bitlenR(kind)); ok {
				c.rv.SetInt(isrc)
				return nil
			}
		case reflect.Float32, reflect.Float64:
			if fsrc, ok := convertUintToFloat(src, bitlenR(kind)); ok {
				c.rv.SetFloat(fsrc)
				return nil
			}
		}
	} else {
		switch kind := c.vv.Kind(); kind {
		case Byte, Uint16, Uint32, Uint64:
			if !overflowUint(src, bitlenV(kind)) {
				c.vv.AssignUint(src)
				return nil
			}
		case Int8, Int16, Int32, Int64:
			if isrc, ok := convertUintToInt(src, bitlenV(kind)); ok {
				c.vv.AssignInt(isrc)
				return nil
			}
		case Float32, Float64:
			if fsrc, ok := convertUintToFloat(src, bitlenV(kind)); ok {
				c.vv.AssignFloat(fsrc)
				return nil
			}
		}
	}
	return fmt.Errorf("invalid conversion from uint(%d) to %v", src, c.tt)
}

func (c convTarget) fromInt(src int64) error {
	if c.vv == nil {
		switch kind := c.rv.Kind(); kind {
		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
			if usrc, ok := convertIntToUint(src, bitlenR(kind)); ok {
				c.rv.SetUint(usrc)
				return nil
			}
		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
			if !overflowInt(src, bitlenR(kind)) {
				c.rv.SetInt(src)
				return nil
			}
		case reflect.Float32, reflect.Float64:
			if fsrc, ok := convertIntToFloat(src, bitlenR(kind)); ok {
				c.rv.SetFloat(fsrc)
				return nil
			}
		}
	} else {
		switch kind := c.vv.Kind(); kind {
		case Byte, Uint16, Uint32, Uint64:
			if usrc, ok := convertIntToUint(src, bitlenV(kind)); ok {
				c.vv.AssignUint(usrc)
				return nil
			}
		case Int8, Int16, Int32, Int64:
			if !overflowInt(src, bitlenV(kind)) {
				c.vv.AssignInt(src)
				return nil
			}
		case Float32, Float64:
			if fsrc, ok := convertIntToFloat(src, bitlenV(kind)); ok {
				c.vv.AssignFloat(fsrc)
				return nil
			}
		}
	}
	return fmt.Errorf("invalid conversion from int(%d) to %v", src, c.tt)
}

func (c convTarget) fromFloat(src float64) error {
	if c.vv == nil {
		switch kind := c.rv.Kind(); kind {
		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
			if usrc, ok := convertFloatToUint(src, bitlenR(kind)); ok {
				c.rv.SetUint(usrc)
				return nil
			}
		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
			if isrc, ok := convertFloatToInt(src, bitlenR(kind)); ok {
				c.rv.SetInt(isrc)
				return nil
			}
		case reflect.Float32, reflect.Float64:
			c.rv.SetFloat(convertFloatToFloat(src, bitlenR(kind)))
			return nil
		}
	} else {
		switch kind := c.vv.Kind(); kind {
		case Byte, Uint16, Uint32, Uint64:
			if usrc, ok := convertFloatToUint(src, bitlenV(kind)); ok {
				c.vv.AssignUint(usrc)
				return nil
			}
		case Int8, Int16, Int32, Int64:
			if isrc, ok := convertFloatToInt(src, bitlenV(kind)); ok {
				c.vv.AssignInt(isrc)
				return nil
			}
		case Float32, Float64:
			c.vv.AssignFloat(convertFloatToFloat(src, bitlenV(kind)))
			return nil
		}
	}
	return fmt.Errorf("invalid conversion from float(%g) to %v", src, c.tt)
}

func (c convTarget) fromBytes(src []byte, tt *Type) error {
	if c.tt.IsBytes() {
		return c.fromBytesToBytes(src)
	}
	elemType := tt.Elem()
	for i, b := range src {
		elem, err := c.startElem(i)
		if err != nil {
			return err
		}
		if err := elem.FromUint(uint64(b), elemType); err != nil {
			return err
		}
		if err := c.finishElem(elem); err != nil {
			return err
		}
	}
	return nil
}

func (c convTarget) fromBytesToBytes(src []byte) error {
	if c.vv == nil {
		switch {
		case c.rv.Kind() == reflect.Array:
			if c.rv.Type().Elem() == rtByte && c.rv.Len() == len(src) {
				reflect.Copy(c.rv, reflect.ValueOf(src))
				return nil
			}
		case c.rv.Kind() == reflect.Slice:
			if c.rv.Type().Elem() == rtByte {
				if len(src) == 0 {
					c.rv.SetBytes(nil)
				} else {
					cp := make([]byte, len(src))
					copy(cp, src)
					c.rv.SetBytes(cp)
				}
				return nil
			}
		}
	} else {
		switch c.vv.Kind() {
		case Array:
			if c.vv.Type().Len() == len(src) {
				c.vv.AssignBytes(src)
				return nil
			}
		case List:
			c.vv.AssignBytes(src)
			return nil
		}
	}
	return fmt.Errorf("invalid conversion from bytes to %v", c.tt)
}

// settable exists to avoid a call to reflect.Call() to invoke Set()
// which results in an allocation
type settable interface {
	Set(string) error
}

func (c convTarget) fromString(src string) error {
	if c.vv == nil {
		tt := removeOptional(c.tt)
		switch {
		case tt.Kind() == Enum:
			// Handle special-case enum first, by calling the Assign method.  Note
			// that TypeFromReflect has already validated the Assign method, so we
			// can call without error checking.
			if c.rv.CanAddr() {
				err := c.rv.Addr().Interface().(settable).Set(src)
				if err != nil {
					return err
				}
				return nil
			}
		case c.rv.Kind() == reflect.String:
			c.rv.SetString(src) // TODO(toddw): check utf8
			return nil
		}
	} else {
		switch c.vv.Kind() {
		case String:
			c.vv.AssignString(src) // TODO(toddw): check utf8
			return nil
		case Enum:
			if index := c.vv.Type().EnumIndex(src); index >= 0 {
				c.vv.AssignEnumIndex(index)
				return nil
			}
		}
	}
	return fmt.Errorf("invalid conversion from string or enum to %v", c.tt)
}

func (c convTarget) fromTypeObject(src *Type) error {
	if c.vv == nil {
		if rtPtrToType.ConvertibleTo(c.rv.Type()) {
			c.rv.Set(reflect.ValueOf(src).Convert(c.rv.Type()))
			return nil
		}
	} else {
		if c.vv.Kind() == TypeObject {
			c.vv.AssignTypeObject(src)
			return nil
		}
	}
	return fmt.Errorf("invalid conversion from typeobject to %v", c.tt)
}

// wrappedListTarget is used to implement FinishList for direct targets.
type wrappedListTarget struct {
	ListTarget
	Target Target
}

// StartList implements the Target interface method.
func (c convTarget) StartList(tt *Type, len int) (ListTarget, error) {
	if target := c.makeDirectTarget(); target != nil {
		listTarget, err := target.StartList(tt, len)
		if err != nil {
			return nil, err
		}
		return wrappedListTarget{listTarget, target}, nil
	}
	// TODO(bprosnitz) Re-think allocation strategy and possibly use len (currently unused).
	fin, fill, err := startConvert(c, tt)
	return compConvTarget{fin, fill}, err
}

// FinishList implements the Target interface method.
func (c convTarget) FinishList(x ListTarget) error {
	if wrapped, ok := x.(wrappedListTarget); ok {
		return wrapped.Target.FinishList(wrapped.ListTarget)
	}
	cc := x.(compConvTarget)
	return finishConvert(cc.fin, cc.fill)
}

// wrappedSetTarget is used to implement FinishSet for direct targets.
type wrappedSetTarget struct {
	SetTarget
	Target Target
}

// StartSet implements the Target interface method.
func (c convTarget) StartSet(tt *Type, len int) (SetTarget, error) {
	if target := c.makeDirectTarget(); target != nil {
		setTarget, err := target.StartSet(tt, len)
		if err != nil {
			return nil, err
		}
		return wrappedSetTarget{setTarget, target}, nil
	}
	fin, fill, err := startConvert(c, tt)
	return compConvTarget{fin, fill}, err
}

// FinishSet implements the Target interface method.
func (c convTarget) FinishSet(x SetTarget) error {
	if wrapped, ok := x.(wrappedSetTarget); ok {
		return wrapped.Target.FinishSet(wrapped.SetTarget)
	}
	cc := x.(compConvTarget)
	return finishConvert(cc.fin, cc.fill)
}

// wrappedMapTarget is used to implement FinishMap for direct targets.
type wrappedMapTarget struct {
	MapTarget
	Target Target
}

// StartMap implements the Target interface method.
func (c convTarget) StartMap(tt *Type, len int) (MapTarget, error) {
	if target := c.makeDirectTarget(); target != nil {
		mapTarget, err := target.StartMap(tt, len)
		if err != nil {
			return nil, err
		}
		return wrappedMapTarget{mapTarget, target}, nil
	}
	fin, fill, err := startConvert(c, tt)
	return compConvTarget{fin, fill}, err
}

// FinishMap implements the Target interface method.
func (c convTarget) FinishMap(x MapTarget) error {
	if wrapped, ok := x.(wrappedMapTarget); ok {
		return wrapped.Target.FinishMap(wrapped.MapTarget)
	}
	cc := x.(compConvTarget)
	return finishConvert(cc.fin, cc.fill)
}

// wrappedFieldsTarget is used to implement FinishFields for direct targets.
type wrappedFieldsTarget struct {
	FieldsTarget
	Target Target
}

// StartFields implements the Target interface method.
func (c convTarget) StartFields(tt *Type) (FieldsTarget, error) {
	if target := c.makeDirectTarget(); target != nil {
		fieldsTarget, err := target.StartFields(tt)
		if err != nil {
			return nil, err
		}
		return wrappedFieldsTarget{fieldsTarget, target}, nil
	}
	if c.vv == nil && c.rv.Kind() == reflect.Interface {
		// TODO(bprosnitz) Union targets are not used for explicit union field structs
		// It is possible to generate and use targets in this case. Consider
		// if it is useful.
		ri, _, err := deriveReflectInfo(c.rv.Type())
		if err != nil {
			return nil, err
		}
		if ri.UnionTargetFactory != nil {
			if ni := nativeInfoFromWire(c.rv.Type()); ni == nil {
				// Wire types are not supported by the generated union target.
				rv := c.rv.Addr()
				target, err := ri.UnionTargetFactory.VDLMakeUnionTarget(rv.Interface())
				if err != nil {
					return nil, err
				}
				fieldsTarget, err := target.StartFields(tt)
				if err != nil {
					return nil, err
				}
				return wrappedFieldsTarget{fieldsTarget, target}, nil
			}
		}
	}
	fin, fill, err := startConvert(c, tt)
	return compConvTarget{fin, fill}, err
}

// FinishFields implements the Target interface method.
func (c convTarget) FinishFields(x FieldsTarget) error {
	if wrapped, ok := x.(wrappedFieldsTarget); ok {
		return wrapped.Target.FinishFields(wrapped.FieldsTarget)
	}
	cc := x.(compConvTarget)
	return finishConvert(cc.fin, cc.fill)
}

// compConvTarget represents the state and logic for composite value conversion.
type compConvTarget struct {
	fin, fill convTarget // fields returned by startConvert.
}

// TODO(bprosnitz) Remove this -- it exists to get the reflect value for VOM and avoid package dependency cycles.
func (c compConvTarget) HackGetRv() reflect.Value {
	return c.fin.rv
}

// StartElem implements the ListTarget interface method.
func (cc compConvTarget) StartElem(index int) (elem Target, _ error) {
	return cc.fill.startElem(index)
}

// FinishElem implements the ListTarget interface method.
func (cc compConvTarget) FinishElem(elem Target) error {
	return cc.fill.finishElem(elem.(convTarget))
}

// StartKey implements the SetTarget and MapTarget interface method.
func (cc compConvTarget) StartKey() (key Target, _ error) {
	return cc.fill.startKey()
}

// FinishKeyStartField implements the MapTarget interface method.
func (cc compConvTarget) FinishKeyStartField(key Target) (field Target, _ error) {
	return cc.fill.finishKeyStartField(key.(convTarget))
}

// FinishField implements the MapTarget and FieldsTarget interface method.
func (cc compConvTarget) FinishField(key, field Target) error {
	return cc.fill.finishField(key.(convTarget), field.(convTarget))
}

// StartField implements the FieldsTarget interface method.
func (cc compConvTarget) StartField(name string) (key, field Target, _ error) {
	var err error
	if key, err = cc.StartKey(); err != nil {
		return nil, nil, err
	}
	if err = key.FromString(name, StringType); err != nil {
		return nil, nil, err
	}
	if field, err = cc.FinishKeyStartField(key); err != nil {
		return nil, nil, err
	}
	return
}

// FinishKey implements the SetTarget interface method.
func (cc compConvTarget) FinishKey(key Target) error {
	field, err := cc.FinishKeyStartField(key)
	if err != nil {
		return err
	}
	return cc.FinishField(key, field)
}

func (c convTarget) startElem(index int) (convTarget, error) {
	if c.vv == nil {
		tt := removeOptional(c.tt)
		switch c.rv.Kind() {
		case reflect.Array:
			if index >= c.rv.Len() {
				return convTarget{}, errArrayIndex
			}
			return reflectConv(c.rv.Index(index), tt.Elem())
		case reflect.Slice:
			newlen := index + 1
			if newlen < c.rv.Len() {
				newlen = c.rv.Len()
			}
			if newlen > c.rv.Cap() {
				rvNew := reflect.MakeSlice(c.rv.Type(), newlen, newlen*2)
				reflect.Copy(rvNew, c.rv)
				c.rv.Set(rvNew)
			} else {
				c.rv.SetLen(newlen)
			}
			return reflectConv(c.rv.Index(index), tt.Elem())
		}
	} else {
		switch c.vv.Kind() {
		case Array:
			if index >= c.vv.Len() {
				return convTarget{}, errArrayIndex
			}
			return valueConv(c.vv.Index(index)), nil
		case List:
			newlen := index + 1
			if newlen < c.vv.Len() {
				newlen = c.vv.Len()
			}
			return valueConv(c.vv.AssignLen(newlen).Index(index)), nil
		}
	}
	return convTarget{}, fmt.Errorf("type %v doesn't support StartElem", c.tt)
}

func (c convTarget) finishElem(elem convTarget) error {
	if c.vv == nil {
		switch c.rv.Kind() {
		case reflect.Array, reflect.Slice:
			return nil
		}
	} else {
		switch c.vv.Kind() {
		case Array, List:
			return nil
		}
	}
	return fmt.Errorf("type %v doesn't support FinishElem", c.tt)
}

func (c convTarget) startKey() (convTarget, error) {
	if c.vv == nil {
		tt := removeOptional(c.tt)
		switch c.rv.Kind() {
		case reflect.Map:
			return reflectConv(rvSettableZeroValue(c.rv.Type().Key(), tt.Key()), tt.Key())
		case reflect.Struct, reflect.Interface:
			// The key for struct and union is the field name, which is a string.
			return reflectConv(reflect.New(rtString).Elem(), StringType)
		}
	} else {
		switch c.vv.Kind() {
		case Set, Map:
			return valueConv(ZeroValue(c.vv.Type().Key())), nil
		case Struct, Union:
			// The key for struct and union is the field name, which is a string.
			return valueConv(ZeroValue(StringType)), nil
		}
	}
	return convTarget{}, fmt.Errorf("type %v doesn't support StartKey", c.tt)
}

func (c convTarget) finishKeyStartField(key convTarget) (convTarget, error) {
	// There are various special-cases regarding bool values below.  These are to
	// handle different representations of sets; the following types are all
	// convertible to each other:
	//   set[string], map[string]bool, struct{X, Y, Z bool}
	//
	// To deal with these cases in a uniform manner, we return a bool field for
	// set[string], and initialize bool fields to true.
	if c.vv == nil {
		tt := removeOptional(c.tt)
		switch c.rv.Kind() {
		case reflect.Map:
			var ttField *Type
			var rvField reflect.Value
			switch rtField := c.rv.Type().Elem(); {
			case tt.Kind() == Set:
				// The map actually represents a set
				ttField = BoolType
				rvField = reflect.New(rtBool).Elem()
				rvField.SetBool(true)
			case rtField.Kind() == reflect.Bool:
				ttField = tt.Elem()
				rvField = reflect.New(rtField).Elem()
				rvField.SetBool(true)
			default:
				// TODO(toddw): This doesn't work correctly for map[_]any.
				ttField = tt.Elem()
				rvField = rvSettableZeroValue(rtField, ttField)
			}
			return reflectConv(rvField, ttField)
		case reflect.Struct:
			if tt.Kind() == Union {
				// Special-case: the fill target is a union concrete field struct.  This
				// means that we should only return a field if the field name matches.
				name := c.rv.Interface().(nameable).Name()
				if name != key.rv.String() {
					return convTarget{}, ErrFieldNoExist
				}
				ttField, _ := tt.FieldByName(name)
				return reflectConv(c.rv.FieldByName("Value"), ttField.Type)
			}
			// TODO(toddw): How should we handle anonymous (aka embedded) fields?
			// Note that unexported embedded fields may themselves have exported
			// fields.  See https://github.com/golang/go/issues/12367
			rvField := c.rv.FieldByName(key.rv.String())
			ttField, index := tt.FieldByName(key.rv.String())
			if !rvField.IsValid() || index < 0 {
				// TODO(toddw): Add a way to track extra and missing fields.
				return convTarget{}, ErrFieldNoExist
			}
			if rvField.Kind() == reflect.Bool {
				rvField.SetBool(true)
			}
			return reflectConv(rvField, ttField.Type)
		case reflect.Interface:
			if tt.Kind() == Union {
				ri, _, err := deriveReflectInfo(c.rv.Type())
				if err != nil {
					return convTarget{}, err
				}
				ttField, index := tt.FieldByName(key.rv.String())
				fld, found := ri.UnionFields[index].RepType.FieldByName("Value")
				if !found {
					return convTarget{}, fmt.Errorf("concrete union type %q missing required Value field", ri.UnionFields[index].RepType)
				}
				rvValue := reflect.New(fld.Type).Elem()
				return reflectConv(rvValue, ttField.Type)
			}
		}
	} else {
		switch c.vv.Kind() {
		case Set:
			return valueConv(BoolValue(true)), nil
		case Map:
			vvField := ZeroValue(c.vv.Type().Elem())
			if vvField.Kind() == Bool {
				vvField.AssignBool(true)
			}
			return valueConv(vvField), nil
		case Struct:
			_, index := c.vv.Type().FieldByName(key.vv.RawString())
			if index < 0 {
				// TODO(toddw): Add a way to track extra and missing fields.
				return convTarget{}, ErrFieldNoExist
			}
			vvField := c.vv.StructField(index)
			if vvField.Kind() == Bool {
				vvField.AssignBool(true)
			}
			return valueConv(vvField), nil
		case Union:
			f, index := c.vv.Type().FieldByName(key.vv.RawString())
			if index < 0 {
				return convTarget{}, ErrFieldNoExist
			}
			vvField := ZeroValue(f.Type)
			return valueConv(vvField), nil
		}
	}
	return convTarget{}, fmt.Errorf("type %v doesn't support FinishKeyStartField", c.tt)
}

func (c convTarget) finishField(key, field convTarget) error {
	// The special-case handling of bool fields matches the special-cases in
	// FinishKeyStartField.
	if c.vv == nil {
		tt := removeOptional(c.tt)
		switch c.rv.Kind() {
		case reflect.Map:
			rvField := field.rv
			if tt.Kind() == Set {
				// The map actually represents a set
				if !field.rv.Bool() {
					return fmt.Errorf("%v can only be converted from true fields", tt)
				}
				rvField = reflect.Zero(c.rv.Type().Elem())
			}
			if c.rv.IsNil() {
				c.rv.Set(reflect.MakeMap(c.rv.Type()))
			}
			c.rv.SetMapIndex(key.rv, rvField)
			return nil
		case reflect.Struct:
			return nil
		case reflect.Interface:
			if tt.Kind() == Union {
				ri, _, err := deriveReflectInfo(c.rv.Type())
				if err != nil {
					return err
				}
				_, index := c.tt.FieldByName(key.rv.String())
				rvField := reflect.New(ri.UnionFields[index].RepType).Elem()
				rvField.FieldByName("Value").Set(field.rv)
				c.rv.Set(rvField)
				return nil
			}
		}
	} else {
		switch c.vv.Kind() {
		case Set:
			if !field.vv.Bool() {
				return fmt.Errorf("%v can only be converted from true fields", c.vv.Type())
			}
			c.vv.AssignSetKey(key.vv)
			return nil
		case Map:
			c.vv.AssignMapIndex(key.vv, field.vv)
			return nil
		case Struct:
			return nil
		case Union:
			_, index := c.vv.Type().FieldByName(key.vv.RawString())
			c.vv.AssignUnionField(index, field.vv)
			return nil
		}
	}
	return fmt.Errorf("type %v doesn't support FinishField", c.tt)
}
