add vendor
This commit is contained in:
7
vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
generated
vendored
Normal file
7
vendor/github.com/zclconf/go-cty/cty/gocty/doc.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// Package gocty deals with converting between cty Values and native go
|
||||
// values.
|
||||
//
|
||||
// It operates under a similar principle to the encoding/json and
|
||||
// encoding/xml packages in the standard library, using reflection to
|
||||
// populate native Go data structures from cty values and vice-versa.
|
||||
package gocty
|
43
vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
generated
vendored
Normal file
43
vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package gocty
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/set"
|
||||
)
|
||||
|
||||
var valueType = reflect.TypeOf(cty.Value{})
|
||||
var typeType = reflect.TypeOf(cty.Type{})
|
||||
|
||||
var setType = reflect.TypeOf(set.Set{})
|
||||
|
||||
var bigFloatType = reflect.TypeOf(big.Float{})
|
||||
var bigIntType = reflect.TypeOf(big.Int{})
|
||||
|
||||
var emptyInterfaceType = reflect.TypeOf(interface{}(nil))
|
||||
|
||||
var stringType = reflect.TypeOf("")
|
||||
|
||||
// structTagIndices interrogates the fields of the given type (which must
|
||||
// be a struct type, or we'll panic) and returns a map from the cty
|
||||
// attribute names declared via struct tags to the indices of the
|
||||
// fields holding those tags.
|
||||
//
|
||||
// This function will panic if two fields within the struct are tagged with
|
||||
// the same cty attribute name.
|
||||
func structTagIndices(st reflect.Type) map[string]int {
|
||||
ct := st.NumField()
|
||||
ret := make(map[string]int, ct)
|
||||
|
||||
for i := 0; i < ct; i++ {
|
||||
field := st.Field(i)
|
||||
attrName := field.Tag.Get("cty")
|
||||
if attrName != "" {
|
||||
ret[attrName] = i
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
548
vendor/github.com/zclconf/go-cty/cty/gocty/in.go
generated
vendored
Normal file
548
vendor/github.com/zclconf/go-cty/cty/gocty/in.go
generated
vendored
Normal file
@ -0,0 +1,548 @@
|
||||
package gocty
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
"github.com/zclconf/go-cty/cty/set"
|
||||
)
|
||||
|
||||
// ToCtyValue produces a cty.Value from a Go value. The result will conform
|
||||
// to the given type, or an error will be returned if this is not possible.
|
||||
//
|
||||
// The target type serves as a hint to resolve ambiguities in the mapping.
|
||||
// For example, the Go type set.Set tells us that the value is a set but
|
||||
// does not describe the set's element type. This also allows for convenient
|
||||
// conversions, such as populating a set from a slice rather than having to
|
||||
// first explicitly instantiate a set.Set.
|
||||
//
|
||||
// The audience of this function is assumed to be the developers of Go code
|
||||
// that is integrating with cty, and thus the error messages it returns are
|
||||
// presented from Go's perspective. These messages are thus not appropriate
|
||||
// for display to end-users. An error returned from ToCtyValue represents a
|
||||
// bug in the calling program, not user error.
|
||||
func ToCtyValue(val interface{}, ty cty.Type) (cty.Value, error) {
|
||||
// 'path' starts off as empty but will grow for each level of recursive
|
||||
// call we make, so by the time toCtyValue returns it is likely to have
|
||||
// unused capacity on the end of it, depending on how deeply-recursive
|
||||
// the given Type is.
|
||||
path := make(cty.Path, 0)
|
||||
return toCtyValue(reflect.ValueOf(val), ty, path)
|
||||
}
|
||||
|
||||
func toCtyValue(val reflect.Value, ty cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val != (reflect.Value{}) && val.Type().AssignableTo(valueType) {
|
||||
// If the source value is a cty.Value then we'll try to just pass
|
||||
// through to the target type directly.
|
||||
return toCtyPassthrough(val, ty, path)
|
||||
}
|
||||
|
||||
switch ty {
|
||||
case cty.Bool:
|
||||
return toCtyBool(val, path)
|
||||
case cty.Number:
|
||||
return toCtyNumber(val, path)
|
||||
case cty.String:
|
||||
return toCtyString(val, path)
|
||||
case cty.DynamicPseudoType:
|
||||
return toCtyDynamic(val, path)
|
||||
}
|
||||
|
||||
switch {
|
||||
case ty.IsListType():
|
||||
return toCtyList(val, ty.ElementType(), path)
|
||||
case ty.IsMapType():
|
||||
return toCtyMap(val, ty.ElementType(), path)
|
||||
case ty.IsSetType():
|
||||
return toCtySet(val, ty.ElementType(), path)
|
||||
case ty.IsObjectType():
|
||||
return toCtyObject(val, ty.AttributeTypes(), path)
|
||||
case ty.IsTupleType():
|
||||
return toCtyTuple(val, ty.TupleElementTypes(), path)
|
||||
case ty.IsCapsuleType():
|
||||
return toCtyCapsule(val, ty, path)
|
||||
}
|
||||
|
||||
// We should never fall out here
|
||||
return cty.NilVal, path.NewErrorf("unsupported target type %#v", ty)
|
||||
}
|
||||
|
||||
func toCtyBool(val reflect.Value, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Bool), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Bool:
|
||||
return cty.BoolVal(val.Bool()), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to bool", val.Kind())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func toCtyNumber(val reflect.Value, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Number), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return cty.NumberIntVal(val.Int()), nil
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return cty.NumberUIntVal(val.Uint()), nil
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return cty.NumberFloatVal(val.Float()), nil
|
||||
|
||||
case reflect.Struct:
|
||||
if val.Type().AssignableTo(bigIntType) {
|
||||
bigInt := val.Interface().(big.Int)
|
||||
bigFloat := (&big.Float{}).SetInt(&bigInt)
|
||||
val = reflect.ValueOf(*bigFloat)
|
||||
}
|
||||
|
||||
if val.Type().AssignableTo(bigFloatType) {
|
||||
bigFloat := val.Interface().(big.Float)
|
||||
return cty.NumberVal(&bigFloat), nil
|
||||
}
|
||||
|
||||
fallthrough
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to number", val.Kind())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func toCtyString(val reflect.Value, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.String), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.String:
|
||||
return cty.StringVal(val.String()), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to string", val.Kind())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func toCtyList(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.List(ety)), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Slice:
|
||||
if val.IsNil() {
|
||||
return cty.NullVal(cty.List(ety)), nil
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
if val.Len() == 0 {
|
||||
return cty.ListValEmpty(ety), nil
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our index step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
vals := make([]cty.Value, val.Len())
|
||||
for i := range vals {
|
||||
var err error
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
vals[i], err = toCtyValue(val.Index(i), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.ListVal(vals), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.List(ety))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func toCtyMap(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Map(ety)), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Map:
|
||||
if val.IsNil() {
|
||||
return cty.NullVal(cty.Map(ety)), nil
|
||||
}
|
||||
|
||||
if val.Len() == 0 {
|
||||
return cty.MapValEmpty(ety), nil
|
||||
}
|
||||
|
||||
keyType := val.Type().Key()
|
||||
if keyType.Kind() != reflect.String {
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our index step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
vals := make(map[string]cty.Value, val.Len())
|
||||
for _, kv := range val.MapKeys() {
|
||||
k := kv.String()
|
||||
var err error
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.StringVal(k),
|
||||
}
|
||||
vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.MapVal(vals), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Map(ety))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func toCtySet(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Set(ety)), nil
|
||||
}
|
||||
|
||||
var vals []cty.Value
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Slice:
|
||||
if val.IsNil() {
|
||||
return cty.NullVal(cty.Set(ety)), nil
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
if val.Len() == 0 {
|
||||
return cty.SetValEmpty(ety), nil
|
||||
}
|
||||
|
||||
vals = make([]cty.Value, val.Len())
|
||||
for i := range vals {
|
||||
var err error
|
||||
vals[i], err = toCtyValue(val.Index(i), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
if !val.Type().AssignableTo(setType) {
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Type(), cty.Set(ety))
|
||||
}
|
||||
|
||||
rawSet := val.Interface().(set.Set)
|
||||
inVals := rawSet.Values()
|
||||
|
||||
if len(inVals) == 0 {
|
||||
return cty.SetValEmpty(ety), nil
|
||||
}
|
||||
|
||||
vals = make([]cty.Value, len(inVals))
|
||||
for i := range inVals {
|
||||
var err error
|
||||
vals[i], err = toCtyValue(reflect.ValueOf(inVals[i]), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Set(ety))
|
||||
|
||||
}
|
||||
|
||||
return cty.SetVal(vals), nil
|
||||
}
|
||||
|
||||
func toCtyObject(val reflect.Value, attrTypes map[string]cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Object(attrTypes)), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Map:
|
||||
if val.IsNil() {
|
||||
return cty.NullVal(cty.Object(attrTypes)), nil
|
||||
}
|
||||
|
||||
keyType := val.Type().Key()
|
||||
if keyType.Kind() != reflect.String {
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go map with key type %s; key type must be string", keyType)
|
||||
}
|
||||
|
||||
if len(attrTypes) == 0 {
|
||||
return cty.EmptyObjectVal, nil
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our GetAttr step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
haveKeys := make(map[string]struct{}, val.Len())
|
||||
for _, kv := range val.MapKeys() {
|
||||
haveKeys[kv.String()] = struct{}{}
|
||||
}
|
||||
|
||||
vals := make(map[string]cty.Value, len(attrTypes))
|
||||
for k, at := range attrTypes {
|
||||
var err error
|
||||
path[len(path)-1] = cty.GetAttrStep{
|
||||
Name: k,
|
||||
}
|
||||
|
||||
if _, have := haveKeys[k]; !have {
|
||||
vals[k] = cty.NullVal(at)
|
||||
continue
|
||||
}
|
||||
|
||||
vals[k], err = toCtyValue(val.MapIndex(reflect.ValueOf(k)), at, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.ObjectVal(vals), nil
|
||||
|
||||
case reflect.Struct:
|
||||
if len(attrTypes) == 0 {
|
||||
return cty.EmptyObjectVal, nil
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our GetAttr step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
attrFields := structTagIndices(val.Type())
|
||||
|
||||
vals := make(map[string]cty.Value, len(attrTypes))
|
||||
for k, at := range attrTypes {
|
||||
path[len(path)-1] = cty.GetAttrStep{
|
||||
Name: k,
|
||||
}
|
||||
|
||||
if fieldIdx, have := attrFields[k]; have {
|
||||
var err error
|
||||
vals[k], err = toCtyValue(val.Field(fieldIdx), at, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
} else {
|
||||
vals[k] = cty.NullVal(at)
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.ObjectVal(vals), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Object(attrTypes))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func toCtyTuple(val reflect.Value, elemTypes []cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.Tuple(elemTypes)), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Slice:
|
||||
if val.IsNil() {
|
||||
return cty.NullVal(cty.Tuple(elemTypes)), nil
|
||||
}
|
||||
|
||||
if val.Len() != len(elemTypes) {
|
||||
return cty.NilVal, path.NewErrorf("wrong number of elements %d; need %d", val.Len(), len(elemTypes))
|
||||
}
|
||||
|
||||
if len(elemTypes) == 0 {
|
||||
return cty.EmptyTupleVal, nil
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our Index step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
vals := make([]cty.Value, len(elemTypes))
|
||||
for i, ety := range elemTypes {
|
||||
var err error
|
||||
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
|
||||
vals[i], err = toCtyValue(val.Index(i), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.TupleVal(vals), nil
|
||||
|
||||
case reflect.Struct:
|
||||
fieldCount := val.Type().NumField()
|
||||
if fieldCount != len(elemTypes) {
|
||||
return cty.NilVal, path.NewErrorf("wrong number of struct fields %d; need %d", fieldCount, len(elemTypes))
|
||||
}
|
||||
|
||||
if len(elemTypes) == 0 {
|
||||
return cty.EmptyTupleVal, nil
|
||||
}
|
||||
|
||||
// While we work on our elements we'll temporarily grow
|
||||
// path to give us a place to put our Index step.
|
||||
path = append(path, cty.PathStep(nil))
|
||||
|
||||
vals := make([]cty.Value, len(elemTypes))
|
||||
for i, ety := range elemTypes {
|
||||
var err error
|
||||
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
|
||||
vals[i], err = toCtyValue(val.Field(i), ety, path)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
}
|
||||
|
||||
// Discard our extra path segment, retaining it as extra capacity
|
||||
// for future appending to the path.
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return cty.TupleVal(vals), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Kind(), cty.Tuple(elemTypes))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func toCtyCapsule(val reflect.Value, capsuleType cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(capsuleType), nil
|
||||
}
|
||||
|
||||
if val.Kind() != reflect.Ptr {
|
||||
if !val.CanAddr() {
|
||||
return cty.NilVal, path.NewErrorf("source value for capsule %#v must be addressable", capsuleType)
|
||||
}
|
||||
|
||||
val = val.Addr()
|
||||
}
|
||||
|
||||
if !val.Type().Elem().AssignableTo(capsuleType.EncapsulatedType()) {
|
||||
return cty.NilVal, path.NewErrorf("value of type %T not compatible with capsule %#v", val.Interface(), capsuleType)
|
||||
}
|
||||
|
||||
return cty.CapsuleVal(capsuleType, val.Interface()), nil
|
||||
}
|
||||
|
||||
func toCtyDynamic(val reflect.Value, path cty.Path) (cty.Value, error) {
|
||||
if val = toCtyUnwrapPointer(val); !val.IsValid() {
|
||||
return cty.NullVal(cty.DynamicPseudoType), nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
|
||||
case reflect.Struct:
|
||||
if !val.Type().AssignableTo(valueType) {
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Type())
|
||||
}
|
||||
|
||||
return val.Interface().(cty.Value), nil
|
||||
|
||||
default:
|
||||
return cty.NilVal, path.NewErrorf("can't convert Go %s dynamically; only cty.Value allowed", val.Kind())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func toCtyPassthrough(wrappedVal reflect.Value, wantTy cty.Type, path cty.Path) (cty.Value, error) {
|
||||
if wrappedVal = toCtyUnwrapPointer(wrappedVal); !wrappedVal.IsValid() {
|
||||
return cty.NullVal(wantTy), nil
|
||||
}
|
||||
|
||||
givenVal := wrappedVal.Interface().(cty.Value)
|
||||
|
||||
val, err := convert.Convert(givenVal, wantTy)
|
||||
if err != nil {
|
||||
return cty.NilVal, path.NewErrorf("unsuitable value: %s", err)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// toCtyUnwrapPointer is a helper for dealing with Go pointers. It has three
|
||||
// possible outcomes:
|
||||
//
|
||||
// - Given value isn't a pointer, so it's just returned as-is.
|
||||
// - Given value is a non-nil pointer, in which case it is dereferenced
|
||||
// and the result returned.
|
||||
// - Given value is a nil pointer, in which case an invalid value is returned.
|
||||
//
|
||||
// For nested pointer types, like **int, they are all dereferenced in turn
|
||||
// until a non-pointer value is found, or until a nil pointer is encountered.
|
||||
func toCtyUnwrapPointer(val reflect.Value) reflect.Value {
|
||||
for val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
|
||||
if val.IsNil() {
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
686
vendor/github.com/zclconf/go-cty/cty/gocty/out.go
generated
vendored
Normal file
686
vendor/github.com/zclconf/go-cty/cty/gocty/out.go
generated
vendored
Normal file
@ -0,0 +1,686 @@
|
||||
package gocty
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FromCtyValue assigns a cty.Value to a reflect.Value, which must be a pointer,
|
||||
// using a fixed set of conversion rules.
|
||||
//
|
||||
// This function considers its audience to be the creator of the cty Value
|
||||
// given, and thus the error messages it generates are (unlike with ToCtyValue)
|
||||
// presented in cty terminology that is generally appropriate to return to
|
||||
// end-users in applications where cty data structures are built from
|
||||
// user-provided configuration. In particular this means that if incorrect
|
||||
// target types are provided by the calling application the resulting error
|
||||
// messages are likely to be confusing, since we assume that the given target
|
||||
// type is correct and the cty.Value is where the error lies.
|
||||
//
|
||||
// If an error is returned, the target data structure may have been partially
|
||||
// populated, but the degree to which this is true is an implementation
|
||||
// detail that the calling application should not rely on.
|
||||
//
|
||||
// The function will panic if given a non-pointer as the Go value target,
|
||||
// since that is considered to be a bug in the calling program.
|
||||
func FromCtyValue(val cty.Value, target interface{}) error {
|
||||
tVal := reflect.ValueOf(target)
|
||||
if tVal.Kind() != reflect.Ptr {
|
||||
panic("target value is not a pointer")
|
||||
}
|
||||
if tVal.IsNil() {
|
||||
panic("target value is nil pointer")
|
||||
}
|
||||
|
||||
// 'path' starts off as empty but will grow for each level of recursive
|
||||
// call we make, so by the time fromCtyValue returns it is likely to have
|
||||
// unused capacity on the end of it, depending on how deeply-recursive
|
||||
// the given cty.Value is.
|
||||
path := make(cty.Path, 0)
|
||||
return fromCtyValue(val, tVal, path)
|
||||
}
|
||||
|
||||
func fromCtyValue(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
ty := val.Type()
|
||||
|
||||
deepTarget := fromCtyPopulatePtr(target, false)
|
||||
|
||||
// If we're decoding into a cty.Value then we just pass through the
|
||||
// value as-is, to enable partial decoding. This is the only situation
|
||||
// where unknown values are permitted.
|
||||
if deepTarget.Kind() == reflect.Struct && deepTarget.Type().AssignableTo(valueType) {
|
||||
deepTarget.Set(reflect.ValueOf(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Lists and maps can be nil without indirection, but everything else
|
||||
// requires a pointer and we set it immediately to nil.
|
||||
// We also make an exception for capsule types because we want to handle
|
||||
// pointers specially for these.
|
||||
// (fromCtyList and fromCtyMap must therefore deal with val.IsNull, while
|
||||
// other types can assume no nulls after this point.)
|
||||
if val.IsNull() && !val.Type().IsListType() && !val.Type().IsMapType() && !val.Type().IsCapsuleType() {
|
||||
target = fromCtyPopulatePtr(target, true)
|
||||
if target.Kind() != reflect.Ptr {
|
||||
return path.NewErrorf("null value is not allowed")
|
||||
}
|
||||
|
||||
target.Set(reflect.Zero(target.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
target = deepTarget
|
||||
|
||||
if !val.IsKnown() {
|
||||
return path.NewErrorf("value must be known")
|
||||
}
|
||||
|
||||
switch ty {
|
||||
case cty.Bool:
|
||||
return fromCtyBool(val, target, path)
|
||||
case cty.Number:
|
||||
return fromCtyNumber(val, target, path)
|
||||
case cty.String:
|
||||
return fromCtyString(val, target, path)
|
||||
}
|
||||
|
||||
switch {
|
||||
case ty.IsListType():
|
||||
return fromCtyList(val, target, path)
|
||||
case ty.IsMapType():
|
||||
return fromCtyMap(val, target, path)
|
||||
case ty.IsSetType():
|
||||
return fromCtySet(val, target, path)
|
||||
case ty.IsObjectType():
|
||||
return fromCtyObject(val, target, path)
|
||||
case ty.IsTupleType():
|
||||
return fromCtyTuple(val, target, path)
|
||||
case ty.IsCapsuleType():
|
||||
return fromCtyCapsule(val, target, path)
|
||||
}
|
||||
|
||||
// We should never fall out here; reaching here indicates a bug in this
|
||||
// function.
|
||||
return path.NewErrorf("unsupported source type %#v", ty)
|
||||
}
|
||||
|
||||
func fromCtyBool(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Bool:
|
||||
target.SetBool(val.True())
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyNumber(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
bf := val.AsBigFloat()
|
||||
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return fromCtyNumberInt(bf, target, path)
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return fromCtyNumberUInt(bf, target, path)
|
||||
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return fromCtyNumberFloat(bf, target, path)
|
||||
|
||||
case reflect.Struct:
|
||||
return fromCtyNumberBig(bf, target, path)
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyNumberInt(bf *big.Float, target reflect.Value, path cty.Path) error {
|
||||
// Doing this with switch rather than << arithmetic because << with
|
||||
// result >32-bits is not portable to 32-bit systems.
|
||||
var min int64
|
||||
var max int64
|
||||
switch target.Type().Bits() {
|
||||
case 8:
|
||||
min = math.MinInt8
|
||||
max = math.MaxInt8
|
||||
case 16:
|
||||
min = math.MinInt16
|
||||
max = math.MaxInt16
|
||||
case 32:
|
||||
min = math.MinInt32
|
||||
max = math.MaxInt32
|
||||
case 64:
|
||||
min = math.MinInt64
|
||||
max = math.MaxInt64
|
||||
default:
|
||||
panic("weird number of bits in target int")
|
||||
}
|
||||
|
||||
iv, accuracy := bf.Int64()
|
||||
if accuracy != big.Exact || iv < min || iv > max {
|
||||
return path.NewErrorf("value must be a whole number, between %d and %d", min, max)
|
||||
}
|
||||
|
||||
target.SetInt(iv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func fromCtyNumberUInt(bf *big.Float, target reflect.Value, path cty.Path) error {
|
||||
// Doing this with switch rather than << arithmetic because << with
|
||||
// result >32-bits is not portable to 32-bit systems.
|
||||
var max uint64
|
||||
switch target.Type().Bits() {
|
||||
case 8:
|
||||
max = math.MaxUint8
|
||||
case 16:
|
||||
max = math.MaxUint16
|
||||
case 32:
|
||||
max = math.MaxUint32
|
||||
case 64:
|
||||
max = math.MaxUint64
|
||||
default:
|
||||
panic("weird number of bits in target uint")
|
||||
}
|
||||
|
||||
iv, accuracy := bf.Uint64()
|
||||
if accuracy != big.Exact || iv > max {
|
||||
return path.NewErrorf("value must be a whole number, between 0 and %d inclusive", max)
|
||||
}
|
||||
|
||||
target.SetUint(iv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func fromCtyNumberFloat(bf *big.Float, target reflect.Value, path cty.Path) error {
|
||||
switch target.Kind() {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
fv, accuracy := bf.Float64()
|
||||
if accuracy != big.Exact {
|
||||
// We allow the precision to be truncated as part of our conversion,
|
||||
// but we don't want to silently introduce infinities.
|
||||
if math.IsInf(fv, 0) {
|
||||
return path.NewErrorf("value must be between %f and %f inclusive", -math.MaxFloat64, math.MaxFloat64)
|
||||
}
|
||||
}
|
||||
target.SetFloat(fv)
|
||||
return nil
|
||||
default:
|
||||
panic("unsupported kind of float")
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyNumberBig(bf *big.Float, target reflect.Value, path cty.Path) error {
|
||||
switch {
|
||||
|
||||
case bigFloatType.ConvertibleTo(target.Type()):
|
||||
// Easy!
|
||||
target.Set(reflect.ValueOf(bf).Elem().Convert(target.Type()))
|
||||
return nil
|
||||
|
||||
case bigIntType.ConvertibleTo(target.Type()):
|
||||
bi, accuracy := bf.Int(nil)
|
||||
if accuracy != big.Exact {
|
||||
return path.NewErrorf("value must be a whole number")
|
||||
}
|
||||
target.Set(reflect.ValueOf(bi).Elem().Convert(target.Type()))
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyString(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
switch target.Kind() {
|
||||
case reflect.String:
|
||||
target.SetString(val.AsString())
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyList(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Slice:
|
||||
if val.IsNull() {
|
||||
target.Set(reflect.Zero(target.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
length := val.LengthInt()
|
||||
tv := reflect.MakeSlice(target.Type(), length, length)
|
||||
|
||||
path = append(path, nil)
|
||||
|
||||
i := 0
|
||||
var err error
|
||||
val.ForEachElement(func(key cty.Value, val cty.Value) bool {
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
|
||||
targetElem := tv.Index(i)
|
||||
err = fromCtyValue(val, targetElem, path)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
i++
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = path[:len(path)-1]
|
||||
|
||||
target.Set(tv)
|
||||
return nil
|
||||
|
||||
case reflect.Array:
|
||||
if val.IsNull() {
|
||||
return path.NewErrorf("null value is not allowed")
|
||||
}
|
||||
|
||||
length := val.LengthInt()
|
||||
if length != target.Len() {
|
||||
return path.NewErrorf("must be a list of length %d", target.Len())
|
||||
}
|
||||
|
||||
path = append(path, nil)
|
||||
|
||||
i := 0
|
||||
var err error
|
||||
val.ForEachElement(func(key cty.Value, val cty.Value) bool {
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
|
||||
targetElem := target.Index(i)
|
||||
err = fromCtyValue(val, targetElem, path)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
i++
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyMap(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Map:
|
||||
if val.IsNull() {
|
||||
target.Set(reflect.Zero(target.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
tv := reflect.MakeMap(target.Type())
|
||||
et := target.Type().Elem()
|
||||
|
||||
path = append(path, nil)
|
||||
|
||||
var err error
|
||||
val.ForEachElement(func(key cty.Value, val cty.Value) bool {
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: key,
|
||||
}
|
||||
|
||||
ks := key.AsString()
|
||||
|
||||
targetElem := reflect.New(et)
|
||||
err = fromCtyValue(val, targetElem, path)
|
||||
|
||||
tv.SetMapIndex(reflect.ValueOf(ks), targetElem.Elem())
|
||||
|
||||
return err != nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = path[:len(path)-1]
|
||||
|
||||
target.Set(tv)
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtySet(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Slice:
|
||||
if val.IsNull() {
|
||||
target.Set(reflect.Zero(target.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
length := val.LengthInt()
|
||||
tv := reflect.MakeSlice(target.Type(), length, length)
|
||||
|
||||
i := 0
|
||||
var err error
|
||||
val.ForEachElement(func(key cty.Value, val cty.Value) bool {
|
||||
targetElem := tv.Index(i)
|
||||
err = fromCtyValue(val, targetElem, path)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
i++
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target.Set(tv)
|
||||
return nil
|
||||
|
||||
case reflect.Array:
|
||||
if val.IsNull() {
|
||||
return path.NewErrorf("null value is not allowed")
|
||||
}
|
||||
|
||||
length := val.LengthInt()
|
||||
if length != target.Len() {
|
||||
return path.NewErrorf("must be a set of length %d", target.Len())
|
||||
}
|
||||
|
||||
i := 0
|
||||
var err error
|
||||
val.ForEachElement(func(key cty.Value, val cty.Value) bool {
|
||||
targetElem := target.Index(i)
|
||||
err = fromCtyValue(val, targetElem, path)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
i++
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
// TODO: decode into set.Set instance
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyObject(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
attrTypes := val.Type().AttributeTypes()
|
||||
targetFields := structTagIndices(target.Type())
|
||||
|
||||
path = append(path, nil)
|
||||
|
||||
for k, i := range targetFields {
|
||||
if _, exists := attrTypes[k]; !exists {
|
||||
// If the field in question isn't able to represent nil,
|
||||
// that's an error.
|
||||
fk := target.Field(i).Kind()
|
||||
switch fk {
|
||||
case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
|
||||
// okay
|
||||
default:
|
||||
return path.NewErrorf("missing required attribute %q", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range attrTypes {
|
||||
path[len(path)-1] = cty.GetAttrStep{
|
||||
Name: k,
|
||||
}
|
||||
|
||||
fieldIdx, exists := targetFields[k]
|
||||
if !exists {
|
||||
return path.NewErrorf("unsupported attribute %q", k)
|
||||
}
|
||||
|
||||
ev := val.GetAttr(k)
|
||||
|
||||
targetField := target.Field(fieldIdx)
|
||||
err := fromCtyValue(ev, targetField, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyTuple(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
elemTypes := val.Type().TupleElementTypes()
|
||||
fieldCount := target.Type().NumField()
|
||||
|
||||
if fieldCount != len(elemTypes) {
|
||||
return path.NewErrorf("a tuple of %d elements is required", fieldCount)
|
||||
}
|
||||
|
||||
path = append(path, nil)
|
||||
|
||||
for i := range elemTypes {
|
||||
path[len(path)-1] = cty.IndexStep{
|
||||
Key: cty.NumberIntVal(int64(i)),
|
||||
}
|
||||
|
||||
ev := val.Index(cty.NumberIntVal(int64(i)))
|
||||
|
||||
targetField := target.Field(i)
|
||||
err := fromCtyValue(ev, targetField, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
path = path[:len(path)-1]
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
return likelyRequiredTypesError(path, target)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func fromCtyCapsule(val cty.Value, target reflect.Value, path cty.Path) error {
|
||||
|
||||
if target.Kind() == reflect.Ptr {
|
||||
// Walk through indirection until we get to the last pointer,
|
||||
// which we might set to null below.
|
||||
target = fromCtyPopulatePtr(target, true)
|
||||
|
||||
if val.IsNull() {
|
||||
target.Set(reflect.Zero(target.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Since a capsule contains a pointer to an object, we'll preserve
|
||||
// that pointer on the way out and thus allow the caller to recover
|
||||
// the original object, rather than a copy of it.
|
||||
|
||||
eType := val.Type().EncapsulatedType()
|
||||
|
||||
if !eType.AssignableTo(target.Elem().Type()) {
|
||||
// Our interface contract promises that we won't expose Go
|
||||
// implementation details in error messages, so we need to keep
|
||||
// this vague. This can only arise if a calling application has
|
||||
// more than one capsule type in play and a user mixes them up.
|
||||
return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
|
||||
}
|
||||
|
||||
target.Set(reflect.ValueOf(val.EncapsulatedValue()))
|
||||
|
||||
return nil
|
||||
} else {
|
||||
if val.IsNull() {
|
||||
return path.NewErrorf("null value is not allowed")
|
||||
}
|
||||
|
||||
// If our target isn't a pointer then we will attempt to copy
|
||||
// the encapsulated value into it.
|
||||
|
||||
eType := val.Type().EncapsulatedType()
|
||||
|
||||
if !eType.AssignableTo(target.Type()) {
|
||||
// Our interface contract promises that we won't expose Go
|
||||
// implementation details in error messages, so we need to keep
|
||||
// this vague. This can only arise if a calling application has
|
||||
// more than one capsule type in play and a user mixes them up.
|
||||
return path.NewErrorf("incorrect type %s", val.Type().FriendlyName())
|
||||
}
|
||||
|
||||
// We know that EncapsulatedValue is always a pointer, so we
|
||||
// can safely call .Elem on its reflect.Value.
|
||||
target.Set(reflect.ValueOf(val.EncapsulatedValue()).Elem())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// fromCtyPopulatePtr recognizes when target is a pointer type and allocates
|
||||
// a value to assign to that pointer, which it returns.
|
||||
//
|
||||
// If the given value has multiple levels of indirection, like **int, these
|
||||
// will be processed in turn so that the return value is guaranteed to be
|
||||
// a non-pointer.
|
||||
//
|
||||
// As an exception, if decodingNull is true then the returned value will be
|
||||
// the final level of pointer, if any, so that the caller can assign it
|
||||
// as nil to represent a null value. If the given target value is not a pointer
|
||||
// at all then the returned value will be just the given target, so the caller
|
||||
// must test if the returned value is a pointer before trying to assign nil
|
||||
// to it.
|
||||
func fromCtyPopulatePtr(target reflect.Value, decodingNull bool) reflect.Value {
|
||||
for {
|
||||
if target.Kind() == reflect.Interface && !target.IsNil() {
|
||||
e := target.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
target = e
|
||||
}
|
||||
}
|
||||
|
||||
if target.Kind() != reflect.Ptr {
|
||||
break
|
||||
}
|
||||
|
||||
// Stop early if we're decodingNull and we've found our last indirection
|
||||
if target.Elem().Kind() != reflect.Ptr && decodingNull && target.CanSet() {
|
||||
break
|
||||
}
|
||||
|
||||
if target.IsNil() {
|
||||
target.Set(reflect.New(target.Type().Elem()))
|
||||
}
|
||||
|
||||
target = target.Elem()
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
// likelyRequiredTypesError returns an error that states which types are
|
||||
// acceptable by making some assumptions about what types we support for
|
||||
// each target Go kind. It's not a precise science but it allows us to return
|
||||
// an error message that is cty-user-oriented rather than Go-oriented.
|
||||
//
|
||||
// Generally these error messages should be a matter of last resort, since
|
||||
// the calling application should be validating user-provided value types
|
||||
// before decoding anyway.
|
||||
func likelyRequiredTypesError(path cty.Path, target reflect.Value) error {
|
||||
switch target.Kind() {
|
||||
|
||||
case reflect.Bool:
|
||||
return path.NewErrorf("bool value is required")
|
||||
|
||||
case reflect.String:
|
||||
return path.NewErrorf("string value is required")
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
fallthrough
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
fallthrough
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return path.NewErrorf("number value is required")
|
||||
|
||||
case reflect.Slice, reflect.Array:
|
||||
return path.NewErrorf("list or set value is required")
|
||||
|
||||
case reflect.Map:
|
||||
return path.NewErrorf("map or object value is required")
|
||||
|
||||
case reflect.Struct:
|
||||
switch {
|
||||
|
||||
case target.Type().AssignableTo(bigFloatType) || target.Type().AssignableTo(bigIntType):
|
||||
return path.NewErrorf("number value is required")
|
||||
|
||||
case target.Type().AssignableTo(setType):
|
||||
return path.NewErrorf("set or list value is required")
|
||||
|
||||
default:
|
||||
return path.NewErrorf("object or tuple value is required")
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
// We should avoid getting into this path, since this error
|
||||
// message is rather useless.
|
||||
return path.NewErrorf("incorrect type")
|
||||
|
||||
}
|
||||
}
|
108
vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
generated
vendored
Normal file
108
vendor/github.com/zclconf/go-cty/cty/gocty/type_implied.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
package gocty
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ImpliedType takes an arbitrary Go value (as an interface{}) and attempts
|
||||
// to find a suitable cty.Type instance that could be used for a conversion
|
||||
// with ToCtyValue.
|
||||
//
|
||||
// This allows -- for simple situations at least -- types to be defined just
|
||||
// once in Go and the cty types derived from the Go types, but in the process
|
||||
// it makes some assumptions that may be undesirable so applications are
|
||||
// encouraged to build their cty types directly if exacting control is
|
||||
// required.
|
||||
//
|
||||
// Not all Go types can be represented as cty types, so an error may be
|
||||
// returned which is usually considered to be a bug in the calling program.
|
||||
// In particular, ImpliedType will never use capsule types in its returned
|
||||
// type, because it cannot know the capsule types supported by the calling
|
||||
// program.
|
||||
func ImpliedType(gv interface{}) (cty.Type, error) {
|
||||
rt := reflect.TypeOf(gv)
|
||||
var path cty.Path
|
||||
return impliedType(rt, path)
|
||||
}
|
||||
|
||||
func impliedType(rt reflect.Type, path cty.Path) (cty.Type, error) {
|
||||
switch rt.Kind() {
|
||||
|
||||
case reflect.Ptr:
|
||||
return impliedType(rt.Elem(), path)
|
||||
|
||||
// Primitive types
|
||||
case reflect.Bool:
|
||||
return cty.Bool, nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return cty.Number, nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return cty.Number, nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return cty.Number, nil
|
||||
case reflect.String:
|
||||
return cty.String, nil
|
||||
|
||||
// Collection types
|
||||
case reflect.Slice:
|
||||
path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.Number)})
|
||||
ety, err := impliedType(rt.Elem(), path)
|
||||
if err != nil {
|
||||
return cty.NilType, err
|
||||
}
|
||||
return cty.List(ety), nil
|
||||
case reflect.Map:
|
||||
if !stringType.AssignableTo(rt.Key()) {
|
||||
return cty.NilType, path.NewErrorf("no cty.Type for %s (must have string keys)", rt)
|
||||
}
|
||||
path := append(path, cty.IndexStep{Key: cty.UnknownVal(cty.String)})
|
||||
ety, err := impliedType(rt.Elem(), path)
|
||||
if err != nil {
|
||||
return cty.NilType, err
|
||||
}
|
||||
return cty.Map(ety), nil
|
||||
|
||||
// Structural types
|
||||
case reflect.Struct:
|
||||
return impliedStructType(rt, path)
|
||||
|
||||
default:
|
||||
return cty.NilType, path.NewErrorf("no cty.Type for %s", rt)
|
||||
}
|
||||
}
|
||||
|
||||
func impliedStructType(rt reflect.Type, path cty.Path) (cty.Type, error) {
|
||||
if valueType.AssignableTo(rt) {
|
||||
// Special case: cty.Value represents cty.DynamicPseudoType, for
|
||||
// type conformance checking.
|
||||
return cty.DynamicPseudoType, nil
|
||||
}
|
||||
|
||||
fieldIdxs := structTagIndices(rt)
|
||||
if len(fieldIdxs) == 0 {
|
||||
return cty.NilType, path.NewErrorf("no cty.Type for %s (no cty field tags)", rt)
|
||||
}
|
||||
|
||||
atys := make(map[string]cty.Type, len(fieldIdxs))
|
||||
|
||||
{
|
||||
// Temporary extension of path for attributes
|
||||
path := append(path, nil)
|
||||
|
||||
for k, fi := range fieldIdxs {
|
||||
path[len(path)-1] = cty.GetAttrStep{Name: k}
|
||||
|
||||
ft := rt.Field(fi).Type
|
||||
aty, err := impliedType(ft, path)
|
||||
if err != nil {
|
||||
return cty.NilType, err
|
||||
}
|
||||
|
||||
atys[k] = aty
|
||||
}
|
||||
}
|
||||
|
||||
return cty.Object(atys), nil
|
||||
}
|
Reference in New Issue
Block a user