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
|
||||
}
|
||||
|
||||
func (t *capsuleType) FriendlyName() string {
|
||||
func (t *capsuleType) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
return t.Name
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,10 @@ func getConversionKnown(in cty.Type, out cty.Type, unsafe bool) conversion {
|
|||
outEty := out.ElementType()
|
||||
return conversionTupleToList(in, outEty, unsafe)
|
||||
|
||||
case out.IsSetType() && in.IsTupleType():
|
||||
outEty := out.ElementType()
|
||||
return conversionTupleToSet(in, outEty, unsafe)
|
||||
|
||||
case out.IsMapType() && in.IsObjectType():
|
||||
outEty := out.ElementType()
|
||||
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
|
||||
// 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.
|
||||
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:
|
||||
// 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
|
||||
// equality and we have no way to recover the original pointer on decode.
|
||||
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) {
|
||||
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 {
|
||||
|
|
|
@ -33,8 +33,14 @@ func (t typeList) Equals(other Type) bool {
|
|||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||
}
|
||||
|
||||
func (t typeList) FriendlyName() string {
|
||||
return "list of " + t.ElementTypeT.FriendlyName()
|
||||
func (t typeList) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
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 {
|
||||
|
|
|
@ -33,8 +33,14 @@ func (t typeMap) Equals(other Type) bool {
|
|||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||
}
|
||||
|
||||
func (t typeMap) FriendlyName() string {
|
||||
return "map of " + t.ElementTypeT.FriendlyName()
|
||||
func (t typeMap) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
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 {
|
||||
|
|
|
@ -51,7 +51,7 @@ func (t typeObject) Equals(other Type) bool {
|
|||
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
|
||||
// complexity, so we'll just do something English-ish. Callers will
|
||||
// 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
|
||||
}
|
||||
|
||||
func (t primitiveType) FriendlyName() string {
|
||||
func (t primitiveType) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
switch t.Kind {
|
||||
case primitiveTypeBool:
|
||||
return "bool"
|
||||
|
|
|
@ -31,8 +31,14 @@ func (t typeSet) Equals(other Type) bool {
|
|||
return t.ElementTypeT.Equals(ot.ElementTypeT)
|
||||
}
|
||||
|
||||
func (t typeSet) FriendlyName() string {
|
||||
return "set of " + t.ElementTypeT.FriendlyName()
|
||||
func (t typeSet) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
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 {
|
||||
|
|
|
@ -44,7 +44,7 @@ func (t typeTuple) Equals(other Type) bool {
|
|||
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
|
||||
// complexity, so we'll just do something English-ish. Callers will
|
||||
// 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
|
||||
// type.
|
||||
FriendlyName() string
|
||||
FriendlyName(mode friendlyTypeNameMode) string
|
||||
|
||||
// GoString implements the GoStringer interface from package fmt.
|
||||
GoString() string
|
||||
|
@ -41,7 +41,25 @@ func (t Type) Equals(other Type) bool {
|
|||
|
||||
// FriendlyName returns a human-friendly *English* name for the given type.
|
||||
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
|
||||
|
@ -93,3 +111,10 @@ func (t Type) HasDynamicTypes() bool {
|
|||
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
|
||||
}
|
||||
|
||||
func (t pseudoTypeDynamic) FriendlyName() string {
|
||||
return "dynamic"
|
||||
func (t pseudoTypeDynamic) FriendlyName(mode friendlyTypeNameMode) string {
|
||||
switch mode {
|
||||
case friendlyTypeConstraintName:
|
||||
return "any type"
|
||||
default:
|
||||
return "dynamic"
|
||||
}
|
||||
}
|
||||
|
||||
func (t pseudoTypeDynamic) GoString() string {
|
||||
|
|
|
@ -2464,52 +2464,52 @@
|
|||
"revisionTime": "2016-10-29T10:40:18Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "4REWNRi5Dg7Kxj1US72+/oVii3Q=",
|
||||
"checksumSHA1": "Ej+3WWvyjn0xg3aujsyT+yvvmdc=",
|
||||
"path": "github.com/zclconf/go-cty/cty",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "3bFMqSB6IxIwhzIw8hyLfd7ayrY=",
|
||||
"checksumSHA1": "1WGUPe776lvMMbaRerAbqOx19nQ=",
|
||||
"path": "github.com/zclconf/go-cty/cty/convert",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "MyyLCGg3RREMllTJyK6ehZl/dHk=",
|
||||
"path": "github.com/zclconf/go-cty/cty/function",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "kcTJOuL131/stXJ4U9tC3SASQLs=",
|
||||
"path": "github.com/zclconf/go-cty/cty/function/stdlib",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "tmCzwfNXOEB1sSO7TKVzilb2vjA=",
|
||||
"path": "github.com/zclconf/go-cty/cty/gocty",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "1ApmO+Q33+Oem/3f6BU6sztJWNc=",
|
||||
"path": "github.com/zclconf/go-cty/cty/json",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "8H+2pufGi2Eo3d8cXFfJs31wk+I=",
|
||||
"path": "github.com/zclconf/go-cty/cty/msgpack",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "y5Sk+n6SOspFj8mlyb8swr4DMIs=",
|
||||
"path": "github.com/zclconf/go-cty/cty/set",
|
||||
"revision": "3ccef1ae92b0ac73b92d86f274f0ff781e2d9b3b",
|
||||
"revisionTime": "2018-07-07T01:23:34Z"
|
||||
"revision": "02bd58e97b5759d478019c5a6333edbfdfed16a0",
|
||||
"revisionTime": "2018-07-18T22:05:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "vE43s37+4CJ2CDU6TlOUOYE0K9c=",
|
||||
|
|
Loading…
Reference in New Issue