govendor fetch github.com/zclconf/go-cty/...
This update includes a new conversion from tuple types to set types and improvements to the error messages returned when conversions fail.
This commit is contained in:
parent
f77dd12e5c
commit
aa6b55bb17
|
@ -19,7 +19,7 @@ func (t *capsuleType) Equals(other Type) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *capsuleType) FriendlyName() string {
|
func (t *capsuleType) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
return t.Name
|
return t.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,10 @@ func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
|
||||||
outEty := out.ElementType()
|
outEty := out.ElementType()
|
||||||
return conversionTupleToList(in, outEty, unsafe)
|
return conversionTupleToList(in, outEty, unsafe)
|
||||||
|
|
||||||
|
case out.IsSetType() && in.IsTupleType():
|
||||||
|
outEty := out.ElementType()
|
||||||
|
return conversionTupleToSet(in, outEty, unsafe)
|
||||||
|
|
||||||
case out.IsMapType() && in.IsObjectType():
|
case out.IsMapType() && in.IsObjectType():
|
||||||
outEty := out.ElementType()
|
outEty := out.ElementType()
|
||||||
return conversionObjectToMap(in, outEty, unsafe)
|
return conversionObjectToMap(in, outEty, unsafe)
|
||||||
|
|
|
@ -128,6 +128,76 @@ func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// conversionTupleToSet returns a conversion that will take a value of the
|
||||||
|
// given tuple type and return a set of the given element type.
|
||||||
|
//
|
||||||
|
// Will panic if the given tupleType isn't actually a tuple type.
|
||||||
|
func conversionTupleToSet(tupleType cty.Type, listEty cty.Type, unsafe bool) conversion {
|
||||||
|
tupleEtys := tupleType.TupleElementTypes()
|
||||||
|
|
||||||
|
if len(tupleEtys) == 0 {
|
||||||
|
// Empty tuple short-circuit
|
||||||
|
return func(val cty.Value, path cty.Path) (cty.Value, error) {
|
||||||
|
return cty.ListValEmpty(listEty), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if listEty == cty.DynamicPseudoType {
|
||||||
|
// This is a special case where the caller wants us to find
|
||||||
|
// a suitable single type that all elements can convert to, if
|
||||||
|
// possible.
|
||||||
|
listEty, _ = unify(tupleEtys, unsafe)
|
||||||
|
if listEty == cty.NilType {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elemConvs := make([]conversion, len(tupleEtys))
|
||||||
|
for i, tupleEty := range tupleEtys {
|
||||||
|
if tupleEty.Equals(listEty) {
|
||||||
|
// no conversion required
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
elemConvs[i] = getConversion(tupleEty, listEty, unsafe)
|
||||||
|
if elemConvs[i] == nil {
|
||||||
|
// If any of our element conversions are impossible, then the our
|
||||||
|
// whole conversion is impossible.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we fall out here then a conversion is possible, using the
|
||||||
|
// element conversions in elemConvs
|
||||||
|
return func(val cty.Value, path cty.Path) (cty.Value, error) {
|
||||||
|
elems := make([]cty.Value, 0, len(elemConvs))
|
||||||
|
path = append(path, nil)
|
||||||
|
i := int64(0)
|
||||||
|
it := val.ElementIterator()
|
||||||
|
for it.Next() {
|
||||||
|
_, val := it.Element()
|
||||||
|
var err error
|
||||||
|
|
||||||
|
path[len(path)-1] = cty.IndexStep{
|
||||||
|
Key: cty.NumberIntVal(i),
|
||||||
|
}
|
||||||
|
|
||||||
|
conv := elemConvs[i]
|
||||||
|
if conv != nil {
|
||||||
|
val, err = conv(val, path)
|
||||||
|
if err != nil {
|
||||||
|
return cty.NilVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elems = append(elems, val)
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return cty.SetVal(elems), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// conversionTupleToList returns a conversion that will take a value of the
|
// conversionTupleToList returns a conversion that will take a value of the
|
||||||
// given tuple type and return a list of the given element type.
|
// given tuple type and return a list of the given element type.
|
||||||
//
|
//
|
||||||
|
|
|
@ -32,9 +32,24 @@ func MismatchMessage(got, want cty.Type) string {
|
||||||
// about their respective attributes.
|
// about their respective attributes.
|
||||||
return mismatchMessageObjects(got, want)
|
return mismatchMessageObjects(got, want)
|
||||||
|
|
||||||
|
case got.IsTupleType() && want.IsListType() && want.ElementType() == cty.DynamicPseudoType:
|
||||||
|
// If conversion from tuple to list failed then it's because we couldn't
|
||||||
|
// find a common type to convert all of the tuple elements to.
|
||||||
|
return "all list elements must have the same type"
|
||||||
|
|
||||||
|
case got.IsTupleType() && want.IsSetType() && want.ElementType() == cty.DynamicPseudoType:
|
||||||
|
// If conversion from tuple to set failed then it's because we couldn't
|
||||||
|
// find a common type to convert all of the tuple elements to.
|
||||||
|
return "all set elements must have the same type"
|
||||||
|
|
||||||
|
case got.IsObjectType() && want.IsMapType() && want.ElementType() == cty.DynamicPseudoType:
|
||||||
|
// If conversion from object to map failed then it's because we couldn't
|
||||||
|
// find a common type to convert all of the object attributes to.
|
||||||
|
return "all map elements must have the same type"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// If we have nothing better to say, we'll just state what was required.
|
// If we have nothing better to say, we'll just state what was required.
|
||||||
return want.FriendlyName() + " required"
|
return want.FriendlyNameForConstraint() + " required"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,11 +103,11 @@ func (t *Type) GobDecode(buf []byte) error {
|
||||||
// Capsule types cannot currently be gob-encoded, because they rely on pointer
|
// Capsule types cannot currently be gob-encoded, because they rely on pointer
|
||||||
// equality and we have no way to recover the original pointer on decode.
|
// equality and we have no way to recover the original pointer on decode.
|
||||||
func (t *capsuleType) GobEncode() ([]byte, error) {
|
func (t *capsuleType) GobEncode() ([]byte, error) {
|
||||||
return nil, fmt.Errorf("cannot gob-encode capsule type %q", t.FriendlyName())
|
return nil, fmt.Errorf("cannot gob-encode capsule type %q", t.FriendlyName(friendlyTypeName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *capsuleType) GobDecode() ([]byte, error) {
|
func (t *capsuleType) GobDecode() ([]byte, error) {
|
||||||
return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName())
|
return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName(friendlyTypeName))
|
||||||
}
|
}
|
||||||
|
|
||||||
type gobValue struct {
|
type gobValue struct {
|
||||||
|
|
|
@ -33,8 +33,14 @@ func (t typeList) Equals(other Type) bool {
|
||||||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeList) FriendlyName() string {
|
func (t typeList) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
return "list of " + t.ElementTypeT.FriendlyName()
|
elemName := t.ElementTypeT.friendlyNameMode(mode)
|
||||||
|
if mode == friendlyTypeConstraintName {
|
||||||
|
if t.ElementTypeT == DynamicPseudoType {
|
||||||
|
elemName = "any single type"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "list of " + elemName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeList) ElementType() Type {
|
func (t typeList) ElementType() Type {
|
||||||
|
|
|
@ -33,8 +33,14 @@ func (t typeMap) Equals(other Type) bool {
|
||||||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeMap) FriendlyName() string {
|
func (t typeMap) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
return "map of " + t.ElementTypeT.FriendlyName()
|
elemName := t.ElementTypeT.friendlyNameMode(mode)
|
||||||
|
if mode == friendlyTypeConstraintName {
|
||||||
|
if t.ElementTypeT == DynamicPseudoType {
|
||||||
|
elemName = "any single type"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "map of " + elemName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeMap) ElementType() Type {
|
func (t typeMap) ElementType() Type {
|
||||||
|
|
|
@ -51,7 +51,7 @@ func (t typeObject) Equals(other Type) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeObject) FriendlyName() string {
|
func (t typeObject) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
// There isn't really a friendly way to write an object type due to its
|
// There isn't really a friendly way to write an object type due to its
|
||||||
// complexity, so we'll just do something English-ish. Callers will
|
// complexity, so we'll just do something English-ish. Callers will
|
||||||
// probably want to make some extra effort to avoid ever printing out
|
// probably want to make some extra effort to avoid ever printing out
|
||||||
|
|
|
@ -24,7 +24,7 @@ func (t primitiveType) Equals(other Type) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t primitiveType) FriendlyName() string {
|
func (t primitiveType) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
switch t.Kind {
|
switch t.Kind {
|
||||||
case primitiveTypeBool:
|
case primitiveTypeBool:
|
||||||
return "bool"
|
return "bool"
|
||||||
|
|
|
@ -31,8 +31,14 @@ func (t typeSet) Equals(other Type) bool {
|
||||||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeSet) FriendlyName() string {
|
func (t typeSet) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
return "set of " + t.ElementTypeT.FriendlyName()
|
elemName := t.ElementTypeT.friendlyNameMode(mode)
|
||||||
|
if mode == friendlyTypeConstraintName {
|
||||||
|
if t.ElementTypeT == DynamicPseudoType {
|
||||||
|
elemName = "any single type"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "set of " + elemName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeSet) ElementType() Type {
|
func (t typeSet) ElementType() Type {
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (t typeTuple) Equals(other Type) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t typeTuple) FriendlyName() string {
|
func (t typeTuple) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
// There isn't really a friendly way to write a tuple type due to its
|
// There isn't really a friendly way to write a tuple type due to its
|
||||||
// complexity, so we'll just do something English-ish. Callers will
|
// complexity, so we'll just do something English-ish. Callers will
|
||||||
// probably want to make some extra effort to avoid ever printing out
|
// probably want to make some extra effort to avoid ever printing out
|
||||||
|
|
|
@ -19,7 +19,7 @@ type typeImpl interface {
|
||||||
|
|
||||||
// FriendlyName returns a human-friendly *English* name for the given
|
// FriendlyName returns a human-friendly *English* name for the given
|
||||||
// type.
|
// type.
|
||||||
FriendlyName() string
|
FriendlyName(mode friendlyTypeNameMode) string
|
||||||
|
|
||||||
// GoString implements the GoStringer interface from package fmt.
|
// GoString implements the GoStringer interface from package fmt.
|
||||||
GoString() string
|
GoString() string
|
||||||
|
@ -41,7 +41,25 @@ func (t Type) Equals(other Type) bool {
|
||||||
|
|
||||||
// FriendlyName returns a human-friendly *English* name for the given type.
|
// FriendlyName returns a human-friendly *English* name for the given type.
|
||||||
func (t Type) FriendlyName() string {
|
func (t Type) FriendlyName() string {
|
||||||
return t.typeImpl.FriendlyName()
|
return t.typeImpl.FriendlyName(friendlyTypeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FriendlyNameForConstraint is similar to FriendlyName except that the
|
||||||
|
// result is specialized for describing type _constraints_ rather than types
|
||||||
|
// themselves. This is more appropriate when reporting that a particular value
|
||||||
|
// does not conform to an expected type constraint.
|
||||||
|
//
|
||||||
|
// In particular, this function uses the term "any type" to refer to
|
||||||
|
// cty.DynamicPseudoType, rather than "dynamic" as returned by FriendlyName.
|
||||||
|
func (t Type) FriendlyNameForConstraint() string {
|
||||||
|
return t.typeImpl.FriendlyName(friendlyTypeConstraintName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// friendlyNameMode is an internal combination of the various FriendlyName*
|
||||||
|
// variants that just directly takes a mode, for easy passthrough for
|
||||||
|
// recursive name construction.
|
||||||
|
func (t Type) friendlyNameMode(mode friendlyTypeNameMode) string {
|
||||||
|
return t.typeImpl.FriendlyName(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoString returns a string approximating how the receiver type would be
|
// GoString returns a string approximating how the receiver type would be
|
||||||
|
@ -93,3 +111,10 @@ func (t Type) HasDynamicTypes() bool {
|
||||||
panic("HasDynamicTypes does not support the given type")
|
panic("HasDynamicTypes does not support the given type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type friendlyTypeNameMode rune
|
||||||
|
|
||||||
|
const (
|
||||||
|
friendlyTypeName friendlyTypeNameMode = 'N'
|
||||||
|
friendlyTypeConstraintName friendlyTypeNameMode = 'C'
|
||||||
|
)
|
||||||
|
|
|
@ -54,8 +54,13 @@ func (t pseudoTypeDynamic) Equals(other Type) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t pseudoTypeDynamic) FriendlyName() string {
|
func (t pseudoTypeDynamic) FriendlyName(mode friendlyTypeNameMode) string {
|
||||||
return "dynamic"
|
switch mode {
|
||||||
|
case friendlyTypeConstraintName:
|
||||||
|
return "any type"
|
||||||
|
default:
|
||||||
|
return "dynamic"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t pseudoTypeDynamic) GoString() string {
|
func (t pseudoTypeDynamic) GoString() string {
|
||||||
|
|
|
@ -2464,52 +2464,52 @@
|
||||||
"revisionTime": "2016-10-29T10:40:18Z"
|
"revisionTime": "2016-10-29T10:40:18Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "4REWNRi5Dg7Kxj1US72+/oVii3Q=",
|
"checksumSHA1": "Ej+3WWvyjn0xg3aujsyT+yvvmdc=",
|
||||||
"path": "github.com/zclconf/go-cty/cty",
|
"path": "github.com/zclconf/go-cty/cty",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "3bFMqSB6IxIwhzIw8hyLfd7ayrY=",
|
"checksumSHA1": "1WGUPe776lvMMbaRerAbqOx19nQ=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/convert",
|
"path": "github.com/zclconf/go-cty/cty/convert",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "MyyLCGg3RREMllTJyK6ehZl/dHk=",
|
"checksumSHA1": "MyyLCGg3RREMllTJyK6ehZl/dHk=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/function",
|
"path": "github.com/zclconf/go-cty/cty/function",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "kcTJOuL131/stXJ4U9tC3SASQLs=",
|
"checksumSHA1": "kcTJOuL131/stXJ4U9tC3SASQLs=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/function/stdlib",
|
"path": "github.com/zclconf/go-cty/cty/function/stdlib",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "tmCzwfNXOEB1sSO7TKVzilb2vjA=",
|
"checksumSHA1": "tmCzwfNXOEB1sSO7TKVzilb2vjA=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/gocty",
|
"path": "github.com/zclconf/go-cty/cty/gocty",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "1ApmO+Q33+Oem/3f6BU6sztJWNc=",
|
"checksumSHA1": "1ApmO+Q33+Oem/3f6BU6sztJWNc=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/json",
|
"path": "github.com/zclconf/go-cty/cty/json",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "8H+2pufGi2Eo3d8cXFfJs31wk+I=",
|
"checksumSHA1": "8H+2pufGi2Eo3d8cXFfJs31wk+I=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/msgpack",
|
"path": "github.com/zclconf/go-cty/cty/msgpack",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "y5Sk+n6SOspFj8mlyb8swr4DMIs=",
|
"checksumSHA1": "y5Sk+n6SOspFj8mlyb8swr4DMIs=",
|
||||||
"path": "github.com/zclconf/go-cty/cty/set",
|
"path": "github.com/zclconf/go-cty/cty/set",
|
||||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||||
"revisionTime": "2018-07-07T01:23:34Z"
|
"revisionTime": "2018-07-18T22:05:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "vE43s37+4CJ2CDU6TlOUOYE0K9c=",
|
"checksumSHA1": "vE43s37+4CJ2CDU6TlOUOYE0K9c=",
|
||||||
|
|
Loading…
Reference in New Issue