diff --git a/go.mod b/go.mod index 9d5ca8f..15604e2 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,6 @@ require ( github.com/hashicorp/hcl/v2 v2.10.0 github.com/hashicorp/terraform v0.14.10 github.com/stretchr/testify v1.7.0 - github.com/zclconf/go-cty v1.8.1 + github.com/zclconf/go-cty v1.12.1 github.com/zclconf/go-cty-yaml v1.0.2 ) diff --git a/go.sum b/go.sum index 672b2a0..6a22938 100644 --- a/go.sum +++ b/go.sum @@ -400,8 +400,8 @@ github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLE github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.8.1 h1:SI0LqNeNxAgv2WWqWJMlG2/Ad/6aYJ7IVYYMigmfkuI= -github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= +github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/zclconf/go-cty-yaml v1.0.2 h1:dNyg4QLTrv2IfJpm7Wtxi55ed5gLGOlPrZ6kMd51hY0= github.com/zclconf/go-cty-yaml v1.0.2/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0= @@ -555,8 +555,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go b/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go index 3ff6855..102d26f 100644 --- a/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go +++ b/vendor/github.com/zclconf/go-cty/cty/capsule_ops.go @@ -49,6 +49,18 @@ type CapsuleOps struct { // pointer identity of the encapsulated value. RawEquals func(a, b interface{}) bool + // HashKey provides a hashing function for values of the corresponding + // capsule type. If defined, cty will use the resulting hashes as part + // of the implementation of sets whose element type is or contains the + // corresponding capsule type. + // + // If a capsule type defines HashValue then the function _must_ return + // an equal hash value for any two values that would cause Equals or + // RawEquals to return true when given those values. If a given type + // does not uphold that assumption then sets including this type will + // not behave correctly. + HashKey func(v interface{}) string + // ConversionFrom can provide conversions from the corresponding type to // some other type when values of the corresponding type are used with // the "convert" package. (The main cty package does not use this operation.) diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go index ededc5f..541b9a4 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion.go @@ -43,14 +43,14 @@ func getConversion(in cty.Type, out cty.Type, unsafe bool) conversion { out = out.WithoutOptionalAttributesDeep() if !isKnown { - return cty.UnknownVal(out), nil + return cty.UnknownVal(dynamicReplace(in.Type(), out)), nil } if isNull { // We'll pass through nulls, albeit type converted, and let // the caller deal with whatever handling they want to do in // case null values are considered valid in some applications. - return cty.NullVal(out), nil + return cty.NullVal(dynamicReplace(in.Type(), out)), nil } } diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go index e70b018..05399c9 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go @@ -39,6 +39,11 @@ func conversionCollectionToList(ety cty.Type, conv conversion) conversion { return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ @@ -50,7 +55,7 @@ func conversionCollectionToList(ety cty.Type, conv conversion) conversion { if ety == cty.DynamicPseudoType { return cty.ListValEmpty(val.Type().ElementType()), nil } - return cty.ListValEmpty(ety), nil + return cty.ListValEmpty(ety.WithoutOptionalAttributesDeep()), nil } if !cty.CanListVal(elems) { @@ -88,6 +93,11 @@ func conversionCollectionToSet(ety cty.Type, conv conversion) conversion { return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ @@ -99,7 +109,7 @@ func conversionCollectionToSet(ety cty.Type, conv conversion) conversion { if ety == cty.DynamicPseudoType { return cty.SetValEmpty(val.Type().ElementType()), nil } - return cty.SetValEmpty(ety), nil + return cty.SetValEmpty(ety.WithoutOptionalAttributesDeep()), nil } if !cty.CanSetVal(elems) { @@ -180,7 +190,7 @@ func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conv if len(tupleEtys) == 0 { // Empty tuple short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.SetValEmpty(setEty), nil + return cty.SetValEmpty(setEty.WithoutOptionalAttributesDeep()), nil } } @@ -242,6 +252,11 @@ func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conv return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ @@ -265,7 +280,7 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co if len(tupleEtys) == 0 { // Empty tuple short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.ListValEmpty(listEty), nil + return cty.ListValEmpty(listEty.WithoutOptionalAttributesDeep()), nil } } @@ -357,7 +372,7 @@ func conversionObjectToMap(objectType cty.Type, mapEty cty.Type, unsafe bool) co if len(objectAtys) == 0 { // Empty object short-circuit return func(val cty.Value, path cty.Path) (cty.Value, error) { - return cty.MapValEmpty(mapEty), nil + return cty.MapValEmpty(mapEty.WithoutOptionalAttributesDeep()), nil } } @@ -448,13 +463,28 @@ func conversionMapToObject(mapType cty.Type, objType cty.Type, unsafe bool) conv elemConvs[name] = getConversion(mapEty, objectAty, unsafe) if elemConvs[name] == nil { - // If any of our element conversions are impossible, then the our - // whole conversion is impossible. + // This means that this conversion is impossible. Typically, we + // would give up at this point and declare the whole conversion + // impossible. But, if this attribute is optional then maybe we will + // be able to do this conversion anyway provided the actual concrete + // map doesn't have this value set. + // + // We only do this in "unsafe" mode, because we cannot guarantee + // that the returned conversion will actually succeed once applied. + if objType.AttributeOptional(name) && unsafe { + // This attribute is optional, so let's leave this conversion in + // as a nil, and we can error later if we actually have to + // convert this. + continue + } + + // Otherwise, give up. This conversion is impossible as we have a + // required attribute that doesn't match the map's inner type. return nil } } - // If we fall out here then a conversion is possible, using the + // If we fall out here then a conversion may be possible, using the // element conversions in elemConvs return func(val cty.Value, path cty.Path) (cty.Value, error) { elems := make(map[string]cty.Value, len(elemConvs)) @@ -474,12 +504,43 @@ func conversionMapToObject(mapType cty.Type, objType cty.Type, unsafe bool) conv Key: name, } - conv := elemConvs[name.AsString()] - if conv != nil { + // There are 3 cases here: + // 1. This attribute is not in elemConvs + // 2. This attribute is in elemConvs and is not nil + // 3. This attribute is in elemConvs and is nil. + + // In case 1, we do not enter any of the branches below. This case + // means the attribute type is the same between the map and the + // object, and we don't need to do any conversion. + + if conv, ok := elemConvs[name.AsString()]; conv != nil { + // This is case 2. The attribute type is different between the + // map and the object, and we know how to convert between them. + // So, we reset val to be the converted value and carry on. val, err = conv(val, elemPath) if err != nil { return cty.NilVal, err } + } else if ok { + // This is case 3 and it is an error. The attribute types are + // different between the map and the object, but we cannot + // convert between them. + // + // Now typically, this would be picked earlier on when we were + // building elemConvs. However, in the case of optional + // attributes there was a chance we could still convert the + // overall object even if this particular attribute was not + // convertable. This is because it could have not been set in + // the map, and we could skip over it here and set a null value. + // + // Since we reached this branch, we know that map did actually + // contain a non-convertable optional attribute. This means we + // error. + return cty.NilVal, path.NewErrorf("map element type is incompatible with attribute %q: %s", name.AsString(), MismatchMessage(val.Type(), objType.AttributeType(name.AsString()))) + } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) } elems[name.AsString()] = val diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go index 4d19cf6..3b554e0 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_dynamic.go @@ -31,3 +31,107 @@ func dynamicFixup(wantType cty.Type) conversion { func dynamicPassthrough(in cty.Value, path cty.Path) (cty.Value, error) { return in, nil } + +// dynamicReplace aims to return the out type unchanged, but if it finds a +// dynamic type either directly or in any descendent elements it replaces them +// with the equivalent type from in. +// +// This function assumes that in and out are compatible from a Convert +// perspective, and will panic if it finds that they are not. For example if +// in is an object and out is a map, this function will still attempt to iterate +// through both as if they were the same. +func dynamicReplace(in, out cty.Type) cty.Type { + if in == cty.DynamicPseudoType || in == cty.NilType { + // Short circuit this case, there's no point worrying about this if in + // is a dynamic type or a nil type. Out is the best we can do. + return out + } + + switch { + case out == cty.DynamicPseudoType: + // So replace out with in. + return in + case out.IsPrimitiveType(), out.IsCapsuleType(): + // out is not dynamic and it doesn't contain descendent elements so just + // return it unchanged. + return out + case out.IsMapType(): + var elemType cty.Type + + // Maps are compatible with other maps or objects. + if in.IsMapType() { + elemType = dynamicReplace(in.ElementType(), out.ElementType()) + } + + if in.IsObjectType() { + var types []cty.Type + for _, t := range in.AttributeTypes() { + types = append(types, t) + } + unifiedType, _ := unify(types, true) + elemType = dynamicReplace(unifiedType, out.ElementType()) + } + + return cty.Map(elemType) + case out.IsObjectType(): + // Objects are compatible with other objects and maps. + outTypes := map[string]cty.Type{} + if in.IsMapType() { + for attr, attrType := range out.AttributeTypes() { + outTypes[attr] = dynamicReplace(in.ElementType(), attrType) + } + } + + if in.IsObjectType() { + for attr, attrType := range out.AttributeTypes() { + if !in.HasAttribute(attr) { + // If in does not have this attribute, then it is an + // optional attribute and there is nothing we can do except + // to return the type from out even if it is dynamic. + outTypes[attr] = attrType + continue + } + outTypes[attr] = dynamicReplace(in.AttributeType(attr), attrType) + } + } + + return cty.Object(outTypes) + case out.IsSetType(): + var elemType cty.Type + + // Sets are compatible with other sets, lists, tuples. + if in.IsSetType() || in.IsListType() { + elemType = dynamicReplace(in.ElementType(), out.ElementType()) + } + + if in.IsTupleType() { + unifiedType, _ := unify(in.TupleElementTypes(), true) + elemType = dynamicReplace(unifiedType, out.ElementType()) + } + + return cty.Set(elemType) + case out.IsListType(): + var elemType cty.Type + + // Lists are compatible with other lists, sets, and tuples. + if in.IsSetType() || in.IsListType() { + elemType = dynamicReplace(in.ElementType(), out.ElementType()) + } + + if in.IsTupleType() { + unifiedType, _ := unify(in.TupleElementTypes(), true) + elemType = dynamicReplace(unifiedType, out.ElementType()) + } + + return cty.List(elemType) + case out.IsTupleType(): + // Tuples are only compatible with other tuples + var types []cty.Type + for ix := 0; ix < len(out.TupleElementTypes()); ix++ { + types = append(types, dynamicReplace(in.TupleElementType(ix), out.TupleElementType(ix))) + } + return cty.Tuple(types) + default: + panic("unrecognized type " + out.FriendlyName()) + } +} diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go index 098c109..51958ef 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/conversion_object.go @@ -80,13 +80,19 @@ func conversionObjectToObject(in, out cty.Type, unsafe bool) conversion { } } + if val.IsNull() { + // Strip optional attributes out of the embedded type for null + // values. + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + attrVals[name] = val } for name := range outOptionals { if _, exists := attrVals[name]; !exists { wantTy := outAtys[name] - attrVals[name] = cty.NullVal(wantTy) + attrVals[name] = cty.NullVal(wantTy.WithoutOptionalAttributesDeep()) } } diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/public.go b/vendor/github.com/zclconf/go-cty/cty/convert/public.go index af19bdc..aab0d0e 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/public.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/public.go @@ -40,7 +40,7 @@ func GetConversionUnsafe(in cty.Type, out cty.Type) Conversion { // This is a convenience wrapper around calling GetConversionUnsafe and then // immediately passing the given value to the resulting function. func Convert(in cty.Value, want cty.Type) (cty.Value, error) { - if in.Type().Equals(want) { + if in.Type().Equals(want.WithoutOptionalAttributesDeep()) { return in, nil } diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go index 144acd8..ac6b64d 100644 --- a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go +++ b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go @@ -447,7 +447,6 @@ func unifyTupleTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, conversions[i] = GetConversion(ty, retTy) } if conversions[i] == nil { - // Shouldn't be reachable, since we were able to unify return unifyTupleTypesToList(types, unsafe) } } @@ -483,8 +482,8 @@ func unifyTupleTypesToList(types []cty.Type, unsafe bool) (cty.Type, []Conversio conversions[i] = GetConversion(ty, retTy) } if conversions[i] == nil { - // Shouldn't be reachable, since we were able to unify - return unifyObjectTypesToMap(types, unsafe) + // no conversion was found + return cty.NilType, nil } } return retTy, conversions diff --git a/vendor/github.com/zclconf/go-cty/cty/element_iterator.go b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go index 9e4fff6..62c9ea5 100644 --- a/vendor/github.com/zclconf/go-cty/cty/element_iterator.go +++ b/vendor/github.com/zclconf/go-cty/cty/element_iterator.go @@ -66,7 +66,7 @@ func elementIterator(val Value) ElementIterator { idx: -1, } case val.ty.IsSetType(): - rawSet := val.v.(set.Set) + rawSet := val.v.(set.Set[interface{}]) return &setElementIterator{ ety: val.ty.ElementType(), setIt: rawSet.Iterator(), @@ -139,7 +139,7 @@ func (it *mapElementIterator) Next() bool { type setElementIterator struct { ety Type - setIt *set.Iterator + setIt *set.Iterator[interface{}] } func (it *setElementIterator) Element() (Value, Value) { diff --git a/vendor/github.com/zclconf/go-cty/cty/function/argument.go b/vendor/github.com/zclconf/go-cty/cty/function/argument.go index 5a26c27..61a1cf9 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/argument.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/argument.go @@ -10,6 +10,9 @@ type Parameter struct { // value, but callers may use it for documentation, etc. Name string + // Description is an optional description for the argument. + Description string + // A type that any argument for this parameter must conform to. // cty.DynamicPseudoType can be used, either at top-level or nested // in a parameterized type, to indicate that any type should be diff --git a/vendor/github.com/zclconf/go-cty/cty/function/function.go b/vendor/github.com/zclconf/go-cty/cty/function/function.go index c00a0e7..c4d99f6 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/function.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/function.go @@ -14,6 +14,9 @@ type Function struct { // Spec is the specification of a function, used to instantiate // a new Function. type Spec struct { + // Description is an optional description for the function specification. + Description string + // Params is a description of the positional parameters for the function. // The standard checking logic rejects any calls that do not provide // arguments conforming to this definition, freeing the function @@ -344,3 +347,62 @@ func (f Function) VarParam() *Parameter { ret := *f.spec.VarParam return &ret } + +// Description returns a human-readable description of the function. +func (f Function) Description() string { + return f.spec.Description +} + +// WithNewDescriptions returns a new function that has the same signature +// and implementation as the receiver but has the function description and +// the parameter descriptions replaced with those given in the arguments. +// +// All descriptions may be given as an empty string to specify that there +// should be no description at all. +// +// The paramDescs argument must match the number of parameters +// the reciever expects, or this function will panic. If the function has a +// VarParam then that counts as one parameter for the sake of this rule. The +// given descriptions will be assigned in order starting with the positional +// arguments in their declared order, followed by the variadic parameter if +// any. +// +// As a special case, WithNewDescriptions will accept a paramDescs which +// does not cover the reciever's variadic parameter (if any), so that it's +// possible to add a variadic parameter to a function which didn't previously +// have one without that being a breaking change for an existing caller using +// WithNewDescriptions against that function. In this case the base description +// of the variadic parameter will be preserved. +func (f Function) WithNewDescriptions(funcDesc string, paramDescs []string) Function { + retSpec := *f.spec // shallow copy of the reciever + retSpec.Description = funcDesc + + retSpec.Params = make([]Parameter, len(f.spec.Params)) + copy(retSpec.Params, f.spec.Params) // shallow copy of positional parameters + if f.spec.VarParam != nil { + retVarParam := *f.spec.VarParam // shallow copy of variadic parameter + retSpec.VarParam = &retVarParam + } + + if retSpec.VarParam != nil { + if with, without := len(retSpec.Params)+1, len(retSpec.Params); len(paramDescs) != with && len(paramDescs) != without { + panic(fmt.Sprintf("paramDescs must have length of either %d or %d", with, without)) + } + } else { + if want := len(retSpec.Params); len(paramDescs) != want { + panic(fmt.Sprintf("paramDescs must have length %d", want)) + } + } + + posParamDescs := paramDescs[:len(retSpec.Params)] + varParamDescs := paramDescs[len(retSpec.Params):] // guaranteed to be zero or one elements because of the rules above + + for i, desc := range posParamDescs { + retSpec.Params[i].Description = desc + } + for _, desc := range varParamDescs { + retSpec.VarParam.Description = desc + } + + return New(&retSpec) +} diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go index 4f1ecc8..8192d8c 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bool.go @@ -6,6 +6,7 @@ import ( ) var NotFunc = function.New(&function.Spec{ + Description: `Applies the logical NOT operation to the given boolean value.`, Params: []function.Parameter{ { Name: "val", @@ -21,6 +22,7 @@ var NotFunc = function.New(&function.Spec{ }) var AndFunc = function.New(&function.Spec{ + Description: `Applies the logical AND operation to the given boolean values.`, Params: []function.Parameter{ { Name: "a", @@ -42,6 +44,7 @@ var AndFunc = function.New(&function.Spec{ }) var OrFunc = function.New(&function.Spec{ + Description: `Applies the logical OR operation to the given boolean values.`, Params: []function.Parameter{ { Name: "a", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go index a132e0c..3fe600f 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/bytes.go @@ -30,6 +30,7 @@ func BytesVal(buf []byte) cty.Value { // BytesLen is a Function that returns the length of the buffer encapsulated // in a Bytes value. var BytesLenFunc = function.New(&function.Spec{ + Description: `Returns the total number of bytes in the given buffer.`, Params: []function.Parameter{ { Name: "buf", @@ -46,6 +47,7 @@ var BytesLenFunc = function.New(&function.Spec{ // BytesSlice is a Function that returns a slice of the given Bytes value. var BytesSliceFunc = function.New(&function.Spec{ + Description: `Extracts a subslice from the given buffer.`, Params: []function.Parameter{ { Name: "buf", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go index 230b03a..0573e74 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go @@ -12,6 +12,7 @@ import ( ) var HasIndexFunc = function.New(&function.Spec{ + Description: `Returns true if if the given collection can be indexed with the given key without producing an error, or false otherwise.`, Params: []function.Parameter{ { Name: "collection", @@ -37,6 +38,7 @@ var HasIndexFunc = function.New(&function.Spec{ }) var IndexFunc = function.New(&function.Spec{ + Description: `Returns the element with the given key from the given collection, or raises an error if there is no such element.`, Params: []function.Parameter{ { Name: "collection", @@ -106,11 +108,13 @@ var IndexFunc = function.New(&function.Spec{ }) var LengthFunc = function.New(&function.Spec{ + Description: `Returns the number of elements in the given collection.`, Params: []function.Parameter{ { Name: "collection", Type: cty.DynamicPseudoType, AllowDynamicType: true, + AllowMarked: true, }, }, Type: func(args []cty.Value) (ret cty.Type, err error) { @@ -126,10 +130,12 @@ var LengthFunc = function.New(&function.Spec{ }) var ElementFunc = function.New(&function.Spec{ + Description: `Returns the element with the given index from the given list or tuple, applying the modulo operation to the given index if it's greater than the number of elements.`, Params: []function.Parameter{ { - Name: "list", - Type: cty.DynamicPseudoType, + Name: "list", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, { Name: "index", @@ -184,11 +190,12 @@ var ElementFunc = function.New(&function.Spec{ return cty.DynamicVal, fmt.Errorf("cannot use element function with a negative index") } - if !args[0].IsKnown() { + input, marks := args[0].Unmark() + if !input.IsKnown() { return cty.UnknownVal(retType), nil } - l := args[0].LengthInt() + l := input.LengthInt() if l == 0 { return cty.DynamicVal, errors.New("cannot use element function with an empty list") } @@ -196,16 +203,18 @@ var ElementFunc = function.New(&function.Spec{ // We did all the necessary type checks in the type function above, // so this is guaranteed not to fail. - return args[0].Index(cty.NumberIntVal(int64(index))), nil + return input.Index(cty.NumberIntVal(int64(index))).WithMarks(marks), nil }, }) // CoalesceListFunc is a function that takes any number of list arguments // and returns the first one that isn't empty. var CoalesceListFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Returns the first of the given sequences that has a length greater than zero.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "vals", + Description: `List or tuple values to test in the given order.`, Type: cty.DynamicPseudoType, AllowUnknown: true, AllowDynamicType: true, @@ -267,6 +276,7 @@ var CoalesceListFunc = function.New(&function.Spec{ // CompactFunc is a function that takes a list of strings and returns a new list // with any empty string elements removed. var CompactFunc = function.New(&function.Spec{ + Description: `Removes all empty string elements from the given list of strings.`, Params: []function.Parameter{ { Name: "list", @@ -303,6 +313,7 @@ var CompactFunc = function.New(&function.Spec{ // ContainsFunc is a function that determines whether a given list or // set contains a given single value as one of its elements. var ContainsFunc = function.New(&function.Spec{ + Description: `Returns true if the given value is a value in the given list, tuple, or set, or false otherwise.`, Params: []function.Parameter{ { Name: "list", @@ -361,6 +372,7 @@ var ContainsFunc = function.New(&function.Spec{ // DistinctFunc is a function that takes a list and returns a new list // with any duplicate elements removed. var DistinctFunc = function.New(&function.Spec{ + Description: `Removes any duplicate values from the given list, preserving the order of remaining elements.`, Params: []function.Parameter{ { Name: "list", @@ -396,14 +408,19 @@ var DistinctFunc = function.New(&function.Spec{ // ChunklistFunc is a function that splits a single list into fixed-size chunks, // returning a list of lists. var ChunklistFunc = function.New(&function.Spec{ + Description: `Splits a single list into multiple lists where each has at most the given number of elements.`, Params: []function.Parameter{ { - Name: "list", - Type: cty.List(cty.DynamicPseudoType), + Name: "list", + Description: `The list to split into chunks.`, + Type: cty.List(cty.DynamicPseudoType), + AllowMarked: true, }, { - Name: "size", - Type: cty.Number, + Name: "size", + Description: `The maximum length of each chunk. All but the last element of the result is guaranteed to be of exactly this size.`, + Type: cty.Number, + AllowMarked: true, }, }, Type: func(args []cty.Value) (cty.Type, error) { @@ -411,35 +428,40 @@ var ChunklistFunc = function.New(&function.Spec{ }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { listVal := args[0] - if !listVal.IsKnown() { - return cty.UnknownVal(retType), nil - } - - if listVal.LengthInt() == 0 { - return cty.ListValEmpty(listVal.Type()), nil - } + sizeVal := args[1] + listVal, listMarks := listVal.Unmark() + sizeVal, sizeMarks := sizeVal.Unmark() + // All return paths below must include .WithMarks(retMarks) to propagate + // the top-level marks into the return value. Deep marks inside the + // list will just propagate naturally because we treat those values + // as opaque here. + retMarks := cty.NewValueMarks(listMarks, sizeMarks) var size int - err = gocty.FromCtyValue(args[1], &size) + err = gocty.FromCtyValue(sizeVal, &size) if err != nil { - return cty.NilVal, fmt.Errorf("invalid index: %s", err) + return cty.NilVal, fmt.Errorf("invalid size: %s", err) } if size < 0 { return cty.NilVal, errors.New("the size argument must be positive") } + if listVal.LengthInt() == 0 { + return cty.ListValEmpty(listVal.Type()).WithMarks(retMarks), nil + } + output := make([]cty.Value, 0) // if size is 0, returns a list made of the initial list if size == 0 { output = append(output, listVal) - return cty.ListVal(output), nil + return cty.ListVal(output).WithMarks(retMarks), nil } chunk := make([]cty.Value, 0) - l := args[0].LengthInt() + l := listVal.LengthInt() i := 0 for it := listVal.ElementIterator(); it.Next(); { @@ -454,17 +476,19 @@ var ChunklistFunc = function.New(&function.Spec{ i++ } - return cty.ListVal(output), nil + return cty.ListVal(output).WithMarks(retMarks), nil }, }) // FlattenFunc is a function that takes a list and replaces any elements // that are lists with a flattened sequence of the list contents. var FlattenFunc = function.New(&function.Spec{ + Description: `Transforms a list, set, or tuple value into a tuple by replacing any given elements that are themselves sequences with a flattened tuple of all of the nested elements concatenated together.`, Params: []function.Parameter{ { - Name: "list", - Type: cty.DynamicPseudoType, + Name: "list", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, }, Type: func(args []cty.Value) (cty.Type, error) { @@ -477,7 +501,8 @@ var FlattenFunc = function.New(&function.Spec{ return cty.NilType, errors.New("can only flatten lists, sets and tuples") } - retVal, known := flattener(args[0]) + // marks are attached to values, so ignore while determining type + retVal, _, known := flattener(args[0]) if !known { return cty.DynamicPseudoType, nil } @@ -490,55 +515,79 @@ var FlattenFunc = function.New(&function.Spec{ }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { inputList := args[0] - if inputList.LengthInt() == 0 { - return cty.EmptyTupleVal, nil + + if unmarked, marks := inputList.Unmark(); unmarked.LengthInt() == 0 { + return cty.EmptyTupleVal.WithMarks(marks), nil } - out, known := flattener(inputList) + out, markses, known := flattener(inputList) if !known { - return cty.UnknownVal(retType), nil + return cty.UnknownVal(retType).WithMarks(markses...), nil } - return cty.TupleVal(out), nil + return cty.TupleVal(out).WithMarks(markses...), nil }, }) // Flatten until it's not a cty.List, and return whether the value is known. // We can flatten lists with unknown values, as long as they are not // lists themselves. -func flattener(flattenList cty.Value) ([]cty.Value, bool) { +func flattener(flattenList cty.Value) ([]cty.Value, []cty.ValueMarks, bool) { + var markses []cty.ValueMarks + flattenList, flattenListMarks := flattenList.Unmark() + if len(flattenListMarks) > 0 { + markses = append(markses, flattenListMarks) + } + if !flattenList.Length().IsKnown() { // If we don't know the length of what we're flattening then we can't // predict the length of our result yet either. - return nil, false + return nil, markses, false } + out := make([]cty.Value, 0) + isKnown := true for it := flattenList.ElementIterator(); it.Next(); { _, val := it.Element() - if val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType() { + + // Any dynamic types could result in more collections that need to be + // flattened, so the type cannot be known. + if val == cty.DynamicVal { + isKnown = false + } + + if !val.IsNull() && (val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType()) { if !val.IsKnown() { - return out, false + isKnown = false + _, unknownMarks := val.Unmark() + markses = append(markses, unknownMarks) + continue } - res, known := flattener(val) - if !known { - return res, known + res, resMarks, known := flattener(val) + markses = append(markses, resMarks...) + if known { + out = append(out, res...) + } else { + isKnown = false } - out = append(out, res...) } else { out = append(out, val) } } - return out, true + return out, markses, isKnown } // KeysFunc is a function that takes a map and returns a sorted list of the map keys. var KeysFunc = function.New(&function.Spec{ + Description: `Returns a list of the keys of the given map in lexicographical order.`, Params: []function.Parameter{ { Name: "inputMap", + Description: `The map to extract keys from. May instead be an object-typed value, in which case the result is a tuple of the object attributes.`, Type: cty.DynamicPseudoType, AllowUnknown: true, + AllowMarked: true, }, }, Type: func(args []cty.Value) (cty.Type, error) { @@ -563,7 +612,11 @@ var KeysFunc = function.New(&function.Spec{ } }, Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { - m := args[0] + // We must unmark the value before we can use ElementIterator on it, and + // then re-apply the same marks (possibly none) when we return. Since we + // don't mark map keys, we can throw away any nested marks, which would + // only apply to values. + m, marks := args[0].Unmark() var keys []cty.Value switch { @@ -576,46 +629,50 @@ var KeysFunc = function.New(&function.Spec{ } sort.Strings(names) // same ordering guaranteed by cty's ElementIterator if len(names) == 0 { - return cty.EmptyTupleVal, nil + return cty.EmptyTupleVal.WithMarks(marks), nil } keys = make([]cty.Value, len(names)) for i, name := range names { keys[i] = cty.StringVal(name) } - return cty.TupleVal(keys), nil + return cty.TupleVal(keys).WithMarks(marks), nil default: if !m.IsKnown() { - return cty.UnknownVal(retType), nil + return cty.UnknownVal(retType).WithMarks(marks), nil } // cty guarantees that ElementIterator will iterate in lexicographical // order by key. - for it := args[0].ElementIterator(); it.Next(); { + for it := m.ElementIterator(); it.Next(); { k, _ := it.Element() keys = append(keys, k) } if len(keys) == 0 { - return cty.ListValEmpty(cty.String), nil + return cty.ListValEmpty(cty.String).WithMarks(marks), nil } - return cty.ListVal(keys), nil + return cty.ListVal(keys).WithMarks(marks), nil } }, }) // LookupFunc is a function that performs dynamic lookups of map types. var LookupFunc = function.New(&function.Spec{ + Description: `Returns the value of the element with the given key from the given map, or returns the default value if there is no such element.`, Params: []function.Parameter{ { - Name: "inputMap", - Type: cty.DynamicPseudoType, + Name: "inputMap", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, { - Name: "key", - Type: cty.String, + Name: "key", + Type: cty.String, + AllowMarked: true, }, { - Name: "default", - Type: cty.DynamicPseudoType, + Name: "default", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, }, Type: func(args []cty.Value) (ret cty.Type, err error) { @@ -627,7 +684,8 @@ var LookupFunc = function.New(&function.Spec{ return cty.DynamicPseudoType, nil } - key := args[1].AsString() + keyVal, _ := args[1].Unmark() + key := keyVal.AsString() if ty.HasAttribute(key) { return args[0].GetAttr(key).Type(), nil } else if len(args) == 3 { @@ -649,28 +707,39 @@ var LookupFunc = function.New(&function.Spec{ } }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { + // leave default value marked defaultVal := args[2] - mapVar := args[0] - lookupKey := args[1].AsString() + var markses []cty.ValueMarks + + // unmark collection, retain marks to reapply later + mapVar, mapMarks := args[0].Unmark() + markses = append(markses, mapMarks) + + // include marks on the key in the result + keyVal, keyMarks := args[1].Unmark() + if len(keyMarks) > 0 { + markses = append(markses, keyMarks) + } + lookupKey := keyVal.AsString() if !mapVar.IsWhollyKnown() { - return cty.UnknownVal(retType), nil + return cty.UnknownVal(retType).WithMarks(markses...), nil } if mapVar.Type().IsObjectType() { if mapVar.Type().HasAttribute(lookupKey) { - return mapVar.GetAttr(lookupKey), nil + return mapVar.GetAttr(lookupKey).WithMarks(markses...), nil } } else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True { - return mapVar.Index(cty.StringVal(lookupKey)), nil + return mapVar.Index(cty.StringVal(lookupKey)).WithMarks(markses...), nil } defaultVal, err = convert.Convert(defaultVal, retType) if err != nil { return cty.NilVal, err } - return defaultVal, nil + return defaultVal.WithMarks(markses...), nil }, }) @@ -681,12 +750,14 @@ var LookupFunc = function.New(&function.Spec{ // If more than one given map or object defines the same key then the one that // is later in the argument sequence takes precedence. var MergeFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Merges all of the elements from the given maps into a single map, or the attributes from given objects into a single object.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "maps", Type: cty.DynamicPseudoType, AllowDynamicType: true, AllowNull: true, + AllowMarked: true, }, Type: func(args []cty.Value) (cty.Type, error) { // empty args is accepted, so assume an empty object since we have no @@ -712,6 +783,8 @@ var MergeFunc = function.New(&function.Spec{ if !ty.IsMapType() && !ty.IsObjectType() { return cty.NilType, fmt.Errorf("arguments must be maps or objects, got %#v", ty.FriendlyName()) } + // marks are attached to values, so ignore while determining type + arg, _ = arg.Unmark() switch { case ty.IsObjectType() && !arg.IsNull(): @@ -761,11 +834,16 @@ var MergeFunc = function.New(&function.Spec{ }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { outputMap := make(map[string]cty.Value) + var markses []cty.ValueMarks // remember any marked maps/objects we find for _, arg := range args { if arg.IsNull() { continue } + arg, argMarks := arg.Unmark() + if len(argMarks) > 0 { + markses = append(markses, argMarks) + } for it := arg.ElementIterator(); it.Next(); { k, v := it.Element() outputMap[k.AsString()] = v @@ -775,11 +853,11 @@ var MergeFunc = function.New(&function.Spec{ switch { case retType.IsMapType(): if len(outputMap) == 0 { - return cty.MapValEmpty(retType.ElementType()), nil + return cty.MapValEmpty(retType.ElementType()).WithMarks(markses...), nil } - return cty.MapVal(outputMap), nil + return cty.MapVal(outputMap).WithMarks(markses...), nil case retType.IsObjectType(), retType.Equals(cty.DynamicPseudoType): - return cty.ObjectVal(outputMap), nil + return cty.ObjectVal(outputMap).WithMarks(markses...), nil default: panic(fmt.Sprintf("unexpected return type: %#v", retType)) } @@ -789,10 +867,12 @@ var MergeFunc = function.New(&function.Spec{ // ReverseListFunc takes a sequence and produces a new sequence of the same length // with all of the same elements as the given sequence but in reverse order. var ReverseListFunc = function.New(&function.Spec{ + Description: `Returns the given list with its elements in reverse order.`, Params: []function.Parameter{ { - Name: "list", - Type: cty.DynamicPseudoType, + Name: "list", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, }, Type: func(args []cty.Value) (cty.Type, error) { @@ -812,19 +892,21 @@ var ReverseListFunc = function.New(&function.Spec{ } }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - in := args[0].AsValueSlice() - outVals := make([]cty.Value, len(in)) - for i, v := range in { + in, marks := args[0].Unmark() + inVals := in.AsValueSlice() + outVals := make([]cty.Value, len(inVals)) + + for i, v := range inVals { outVals[len(outVals)-i-1] = v } switch { case retType.IsTupleType(): - return cty.TupleVal(outVals), nil + return cty.TupleVal(outVals).WithMarks(marks), nil default: if len(outVals) == 0 { - return cty.ListValEmpty(retType.ElementType()), nil + return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil } - return cty.ListVal(outVals), nil + return cty.ListVal(outVals).WithMarks(marks), nil } }, }) @@ -834,10 +916,13 @@ var ReverseListFunc = function.New(&function.Spec{ // preserving the ordering of all of the input lists. Otherwise the result is a // set of tuples. var SetProductFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Calculates the cartesian product of two or more sets.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ - Name: "sets", - Type: cty.DynamicPseudoType, + Name: "sets", + Description: "The sets to consider. Also accepts lists and tuples, and if all arguments are of list or tuple type then the result will preserve the input ordering", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, Type: func(args []cty.Value) (retType cty.Type, err error) { if len(args) < 2 { @@ -881,11 +966,19 @@ var SetProductFunc = function.New(&function.Spec{ }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { ety := retType.ElementType() + var retMarks cty.ValueMarks total := 1 + var hasUnknownLength bool for _, arg := range args { + arg, marks := arg.Unmark() + retMarks = cty.NewValueMarks(retMarks, marks) + + // Continue processing after we find an argument with unknown + // length to ensure that we cover all the marks if !arg.Length().IsKnown() { - return cty.UnknownVal(retType), nil + hasUnknownLength = true + continue } // Because of our type checking function, we are guaranteed that @@ -894,13 +987,17 @@ var SetProductFunc = function.New(&function.Spec{ total *= arg.LengthInt() } + if hasUnknownLength { + return cty.UnknownVal(retType).WithMarks(retMarks), nil + } + if total == 0 { // If any of the arguments was an empty collection then our result // is also an empty collection, which we'll short-circuit here. if retType.IsListType() { - return cty.ListValEmpty(ety), nil + return cty.ListValEmpty(ety).WithMarks(retMarks), nil } - return cty.SetValEmpty(ety), nil + return cty.SetValEmpty(ety).WithMarks(retMarks), nil } subEtys := ety.TupleElementTypes() @@ -911,6 +1008,8 @@ var SetProductFunc = function.New(&function.Spec{ s := 0 argVals := make([][]cty.Value, len(args)) for i, arg := range args { + // We've already stored the marks in retMarks + arg, _ := arg.Unmark() argVals[i] = arg.AsValueSlice() } @@ -950,19 +1049,21 @@ var SetProductFunc = function.New(&function.Spec{ } if retType.IsListType() { - return cty.ListVal(productVals), nil + return cty.ListVal(productVals).WithMarks(retMarks), nil } - return cty.SetVal(productVals), nil + return cty.SetVal(productVals).WithMarks(retMarks), nil }, }) // SliceFunc is a function that extracts some consecutive elements // from within a list. var SliceFunc = function.New(&function.Spec{ + Description: `Extracts a subslice of the given list or tuple value.`, Params: []function.Parameter{ { - Name: "list", - Type: cty.DynamicPseudoType, + Name: "list", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, { Name: "start_index", @@ -1001,10 +1102,10 @@ var SliceFunc = function.New(&function.Spec{ return cty.Tuple(argTy.TupleElementTypes()[startIndex:endIndex]), nil }, Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - inputList := args[0] + inputList, marks := args[0].Unmark() if retType == cty.DynamicPseudoType { - return cty.DynamicVal, nil + return cty.DynamicVal.WithMarks(marks), nil } // we ignore idxsKnown return value here because the indices are always @@ -1016,18 +1117,18 @@ var SliceFunc = function.New(&function.Spec{ if endIndex-startIndex == 0 { if retType.IsTupleType() { - return cty.EmptyTupleVal, nil + return cty.EmptyTupleVal.WithMarks(marks), nil } - return cty.ListValEmpty(retType.ElementType()), nil + return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil } outputList := inputList.AsValueSlice()[startIndex:endIndex] if retType.IsTupleType() { - return cty.TupleVal(outputList), nil + return cty.TupleVal(outputList).WithMarks(marks), nil } - return cty.ListVal(outputList), nil + return cty.ListVal(outputList).WithMarks(marks), nil }, }) @@ -1035,9 +1136,12 @@ func sliceIndexes(args []cty.Value) (int, int, bool, error) { var startIndex, endIndex, length int var startKnown, endKnown, lengthKnown bool + // remove marks from args[0] + list, _ := args[0].Unmark() + // If it's a tuple then we always know the length by the type, but collections might be unknown or have unknown length - if args[0].Type().IsTupleType() || args[0].Length().IsKnown() { - length = args[0].LengthInt() + if list.Type().IsTupleType() || list.Length().IsKnown() { + length = list.LengthInt() lengthKnown = true } @@ -1076,10 +1180,12 @@ func sliceIndexes(args []cty.Value) (int, int, bool, error) { // ValuesFunc is a function that returns a list of the map values, // in the order of the sorted keys. var ValuesFunc = function.New(&function.Spec{ + Description: `Returns the values of elements of a given map, or the values of attributes of a given object, in lexicographic order by key or attribute name.`, Params: []function.Parameter{ { - Name: "values", - Type: cty.DynamicPseudoType, + Name: "mapping", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, }, Type: func(args []cty.Value) (ret cty.Type, err error) { @@ -1112,6 +1218,13 @@ var ValuesFunc = function.New(&function.Spec{ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { mapVar := args[0] + // We must unmark the value before we can use ElementIterator on it, + // and then re-apply the same marks (possibly none) when we return. + // (We leave the inner values just as they are, because we won't be + // doing anything with them aside from copying them verbatim into the + // result, marks and all.) + mapVar, marks := mapVar.Unmark() + // We can just iterate the map/object value here because cty guarantees // that these types always iterate in key lexicographical order. var values []cty.Value @@ -1120,27 +1233,32 @@ var ValuesFunc = function.New(&function.Spec{ values = append(values, val) } + // All of the return paths must include .WithMarks(marks) so that we + // will preserve the markings of the overall map/object we were given. if retType.IsTupleType() { - return cty.TupleVal(values), nil + return cty.TupleVal(values).WithMarks(marks), nil } if len(values) == 0 { - return cty.ListValEmpty(retType.ElementType()), nil + return cty.ListValEmpty(retType.ElementType()).WithMarks(marks), nil } - return cty.ListVal(values), nil + return cty.ListVal(values).WithMarks(marks), nil }, }) // ZipmapFunc is a function that constructs a map from a list of keys // and a corresponding list of values. var ZipmapFunc = function.New(&function.Spec{ + Description: `Constructs a map from a list of keys and a corresponding list of values, which must both be of the same length.`, Params: []function.Parameter{ { - Name: "keys", - Type: cty.List(cty.String), + Name: "keys", + Type: cty.List(cty.String), + AllowMarked: true, }, { - Name: "values", - Type: cty.DynamicPseudoType, + Name: "values", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, }, Type: func(args []cty.Value) (ret cty.Type, err error) { @@ -1158,6 +1276,13 @@ var ZipmapFunc = function.New(&function.Spec{ return cty.DynamicPseudoType, nil } + // NOTE: Marking of the keys list can't be represented in the + // result type, so the tuple type here will disclose the keys. + // This is unfortunate but is a common compromise with dynamic + // return types; the result from Impl will still reflect the marks + // from the keys list, so a mark-using caller should look out for + // that if it's important for their use-case. + keys, _ := keys.Unmark() keysRaw := keys.AsValueSlice() valueTypesRaw := valuesTy.TupleElementTypes() if len(keysRaw) != len(valueTypesRaw) { @@ -1165,6 +1290,7 @@ var ZipmapFunc = function.New(&function.Spec{ } atys := make(map[string]cty.Type, len(valueTypesRaw)) for i, keyVal := range keysRaw { + keyVal, _ = keyVal.Unmark() if keyVal.IsNull() { return cty.NilType, fmt.Errorf("keys list has null value at index %d", i) } @@ -1180,11 +1306,17 @@ var ZipmapFunc = function.New(&function.Spec{ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { keys := args[0] values := args[1] + keys, keysMarks := keys.Unmark() + values, valuesMarks := values.Unmark() + + // All of our return paths must pass through the merged marks from + // both the keys and the values, if any, using .WithMarks(retMarks) + retMarks := cty.NewValueMarks(keysMarks, valuesMarks) if !keys.IsWhollyKnown() { // Unknown map keys and object attributes are not supported, so // our entire result must be unknown in this case. - return cty.UnknownVal(retType), nil + return cty.UnknownVal(retType).WithMarks(retMarks), nil } // both keys and values are guaranteed to be shallowly-known here, @@ -1198,19 +1330,25 @@ var ZipmapFunc = function.New(&function.Spec{ i := 0 for it := keys.ElementIterator(); it.Next(); { _, v := it.Element() + v, vMarks := v.Unmark() val := values.Index(cty.NumberIntVal(int64(i))) output[v.AsString()] = val + + // We also need to accumulate the individual key marks on the + // returned map, because keys can't carry marks on their own. + retMarks = cty.NewValueMarks(retMarks, vMarks) + i++ } switch { case retType.IsMapType(): if len(output) == 0 { - return cty.MapValEmpty(retType.ElementType()), nil + return cty.MapValEmpty(retType.ElementType()).WithMarks(retMarks), nil } - return cty.MapVal(output), nil + return cty.MapVal(output).WithMarks(retMarks), nil case retType.IsObjectType(): - return cty.ObjectVal(output), nil + return cty.ObjectVal(output).WithMarks(retMarks), nil default: // Should never happen because the type-check function should've // caught any other case. diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go index 66eb97e..f61b534 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/conversion.go @@ -1,6 +1,7 @@ package stdlib import ( + "fmt" "strconv" "github.com/zclconf/go-cty/cty" @@ -18,6 +19,7 @@ import ( // a tuple. func MakeToFunc(wantTy cty.Type) function.Function { return function.New(&function.Spec{ + Description: fmt.Sprintf("Converts the given value to %s, or raises an error if that conversion is impossible.", wantTy.FriendlyName()), Params: []function.Parameter{ { Name: "v", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go index 5070a5a..20d82bc 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go @@ -11,6 +11,7 @@ import ( ) var CSVDecodeFunc = function.New(&function.Spec{ + Description: `Parses the given string as Comma Separated Values (as defined by RFC 4180) and returns a map of objects representing the table of data, using the first row as a header row to define the object attributes.`, Params: []function.Parameter{ { Name: "str", @@ -30,7 +31,7 @@ var CSVDecodeFunc = function.New(&function.Spec{ return cty.DynamicPseudoType, fmt.Errorf("missing header line") } if err != nil { - return cty.DynamicPseudoType, err + return cty.DynamicPseudoType, csvError(err) } atys := make(map[string]cty.Type, len(headers)) @@ -64,7 +65,7 @@ var CSVDecodeFunc = function.New(&function.Spec{ break } if err != nil { - return cty.DynamicVal, err + return cty.DynamicVal, csvError(err) } vals := make(map[string]cty.Value, len(cols)) @@ -91,3 +92,12 @@ var CSVDecodeFunc = function.New(&function.Spec{ func CSVDecode(str cty.Value) (cty.Value, error) { return CSVDecodeFunc.Call([]cty.Value{str}) } + +func csvError(err error) error { + switch err := err.(type) { + case *csv.ParseError: + return fmt.Errorf("CSV parse error on line %d: %w", err.Line, err.Err) + default: + return err + } +} diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go index 1ceffcf..6c0ee05 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/datetime.go @@ -12,6 +12,7 @@ import ( ) var FormatDateFunc = function.New(&function.Spec{ + Description: `Formats a timestamp given in RFC 3339 syntax into another timestamp in some other machine-oriented time syntax, as described in the format string.`, Params: []function.Parameter{ { Name: "format", @@ -205,6 +206,7 @@ var FormatDateFunc = function.New(&function.Spec{ // TimeAddFunc is a function that adds a duration to a timestamp, returning a new timestamp. var TimeAddFunc = function.New(&function.Spec{ + Description: `Adds the duration represented by the given duration string to the given RFC 3339 timestamp string, returning another RFC 3339 timestamp.`, Params: []function.Parameter{ { Name: "timestamp", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go index 63881f5..ca163a8 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go @@ -18,6 +18,7 @@ import ( //go:generate gofmt -w format_fsm.go var FormatFunc = function.New(&function.Spec{ + Description: `Constructs a string by applying formatting verbs to a series of arguments, using a similar syntax to the C function \"printf\".`, Params: []function.Parameter{ { Name: "format", @@ -45,6 +46,7 @@ var FormatFunc = function.New(&function.Spec{ }) var FormatListFunc = function.New(&function.Spec{ + Description: `Constructs a list of strings by applying formatting verbs to a series of arguments, using a similar syntax to the C function \"printf\".`, Params: []function.Parameter{ { Name: "format", @@ -114,6 +116,8 @@ var FormatListFunc = function.New(&function.Spec{ continue } iterators[i] = arg.ElementIterator() + case arg == cty.DynamicVal: + unknowns[i] = true default: singleVals[i] = arg } diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go index 6b31f26..4f70fff 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/general.go @@ -9,6 +9,7 @@ import ( ) var EqualFunc = function.New(&function.Spec{ + Description: `Returns true if the two given values are equal, or false otherwise.`, Params: []function.Parameter{ { Name: "a", @@ -32,6 +33,7 @@ var EqualFunc = function.New(&function.Spec{ }) var NotEqualFunc = function.New(&function.Spec{ + Description: `Returns false if the two given values are equal, or true otherwise.`, Params: []function.Parameter{ { Name: "a", @@ -55,7 +57,8 @@ var NotEqualFunc = function.New(&function.Spec{ }) var CoalesceFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Returns the first of the given arguments that isn't null, or raises an error if there are no non-null arguments.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "vals", Type: cty.DynamicPseudoType, diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go index 02770a6..63dd320 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/json.go @@ -7,6 +7,7 @@ import ( ) var JSONEncodeFunc = function.New(&function.Spec{ + Description: `Returns a string containing a JSON representation of the given value.`, Params: []function.Parameter{ { Name: "val", @@ -39,6 +40,7 @@ var JSONEncodeFunc = function.New(&function.Spec{ }) var JSONDecodeFunc = function.New(&function.Spec{ + Description: `Parses the given string as JSON and returns a value corresponding to what the JSON document describes.`, Params: []function.Parameter{ { Name: "str", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go index 7bbe584..ce73751 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go @@ -11,6 +11,7 @@ import ( ) var AbsoluteFunc = function.New(&function.Spec{ + Description: `If the given number is negative then returns its positive equivalent, or otherwise returns the given number unchanged.`, Params: []function.Parameter{ { Name: "num", @@ -26,6 +27,7 @@ var AbsoluteFunc = function.New(&function.Spec{ }) var AddFunc = function.New(&function.Spec{ + Description: `Returns the sum of the two given numbers.`, Params: []function.Parameter{ { Name: "a", @@ -59,6 +61,7 @@ var AddFunc = function.New(&function.Spec{ }) var SubtractFunc = function.New(&function.Spec{ + Description: `Returns the difference between the two given numbers.`, Params: []function.Parameter{ { Name: "a", @@ -92,6 +95,7 @@ var SubtractFunc = function.New(&function.Spec{ }) var MultiplyFunc = function.New(&function.Spec{ + Description: `Returns the product of the two given numbers.`, Params: []function.Parameter{ { Name: "a", @@ -126,6 +130,7 @@ var MultiplyFunc = function.New(&function.Spec{ }) var DivideFunc = function.New(&function.Spec{ + Description: `Divides the first given number by the second.`, Params: []function.Parameter{ { Name: "a", @@ -160,6 +165,7 @@ var DivideFunc = function.New(&function.Spec{ }) var ModuloFunc = function.New(&function.Spec{ + Description: `Divides the first given number by the second and then returns the remainder.`, Params: []function.Parameter{ { Name: "a", @@ -194,6 +200,7 @@ var ModuloFunc = function.New(&function.Spec{ }) var GreaterThanFunc = function.New(&function.Spec{ + Description: `Returns true if and only if the second number is greater than the first.`, Params: []function.Parameter{ { Name: "a", @@ -215,6 +222,7 @@ var GreaterThanFunc = function.New(&function.Spec{ }) var GreaterThanOrEqualToFunc = function.New(&function.Spec{ + Description: `Returns true if and only if the second number is greater than or equal to the first.`, Params: []function.Parameter{ { Name: "a", @@ -236,6 +244,7 @@ var GreaterThanOrEqualToFunc = function.New(&function.Spec{ }) var LessThanFunc = function.New(&function.Spec{ + Description: `Returns true if and only if the second number is less than the first.`, Params: []function.Parameter{ { Name: "a", @@ -257,6 +266,7 @@ var LessThanFunc = function.New(&function.Spec{ }) var LessThanOrEqualToFunc = function.New(&function.Spec{ + Description: `Returns true if and only if the second number is less than or equal to the first.`, Params: []function.Parameter{ { Name: "a", @@ -278,6 +288,7 @@ var LessThanOrEqualToFunc = function.New(&function.Spec{ }) var NegateFunc = function.New(&function.Spec{ + Description: `Multiplies the given number by -1.`, Params: []function.Parameter{ { Name: "num", @@ -293,7 +304,8 @@ var NegateFunc = function.New(&function.Spec{ }) var MinFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Returns the numerically smallest of all of the given numbers.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "numbers", Type: cty.Number, @@ -317,7 +329,8 @@ var MinFunc = function.New(&function.Spec{ }) var MaxFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Returns the numerically greatest of all of the given numbers.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ Name: "numbers", Type: cty.Number, @@ -341,6 +354,7 @@ var MaxFunc = function.New(&function.Spec{ }) var IntFunc = function.New(&function.Spec{ + Description: `Discards any fractional portion of the given number.`, Params: []function.Parameter{ { Name: "num", @@ -363,6 +377,7 @@ var IntFunc = function.New(&function.Spec{ // CeilFunc is a function that returns the closest whole number greater // than or equal to the given value. var CeilFunc = function.New(&function.Spec{ + Description: `Returns the smallest whole number that is greater than or equal to the given value.`, Params: []function.Parameter{ { Name: "num", @@ -371,20 +386,28 @@ var CeilFunc = function.New(&function.Spec{ }, Type: function.StaticReturnType(cty.Number), Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - var val float64 - if err := gocty.FromCtyValue(args[0], &val); err != nil { - return cty.UnknownVal(cty.String), err + f := args[0].AsBigFloat() + + if f.IsInf() { + return cty.NumberVal(f), nil } - if math.IsInf(val, 0) { - return cty.NumberFloatVal(val), nil + + i, acc := f.Int(nil) + switch acc { + case big.Exact, big.Above: + // Done. + case big.Below: + i.Add(i, big.NewInt(1)) } - return cty.NumberIntVal(int64(math.Ceil(val))), nil + + return cty.NumberVal(f.SetInt(i)), nil }, }) // FloorFunc is a function that returns the closest whole number lesser // than or equal to the given value. var FloorFunc = function.New(&function.Spec{ + Description: `Returns the greatest whole number that is less than or equal to the given value.`, Params: []function.Parameter{ { Name: "num", @@ -393,19 +416,27 @@ var FloorFunc = function.New(&function.Spec{ }, Type: function.StaticReturnType(cty.Number), Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - var val float64 - if err := gocty.FromCtyValue(args[0], &val); err != nil { - return cty.UnknownVal(cty.String), err + f := args[0].AsBigFloat() + + if f.IsInf() { + return cty.NumberVal(f), nil } - if math.IsInf(val, 0) { - return cty.NumberFloatVal(val), nil + + i, acc := f.Int(nil) + switch acc { + case big.Exact, big.Below: + // Done. + case big.Above: + i.Sub(i, big.NewInt(1)) } - return cty.NumberIntVal(int64(math.Floor(val))), nil + + return cty.NumberVal(f.SetInt(i)), nil }, }) // LogFunc is a function that returns the logarithm of a given number in a given base. var LogFunc = function.New(&function.Spec{ + Description: `Returns the logarithm of the given number in the given base.`, Params: []function.Parameter{ { Name: "num", @@ -434,6 +465,7 @@ var LogFunc = function.New(&function.Spec{ // PowFunc is a function that returns the logarithm of a given number in a given base. var PowFunc = function.New(&function.Spec{ + Description: `Returns the given number raised to the given power (exponentiation).`, Params: []function.Parameter{ { Name: "num", @@ -463,6 +495,7 @@ var PowFunc = function.New(&function.Spec{ // SignumFunc is a function that determines the sign of a number, returning a // number between -1 and 1 to represent the sign.. var SignumFunc = function.New(&function.Spec{ + Description: `Returns 0 if the given number is zero, 1 if the given number is positive, or -1 if the given number is negative.`, Params: []function.Parameter{ { Name: "num", @@ -488,6 +521,7 @@ var SignumFunc = function.New(&function.Spec{ // ParseIntFunc is a function that parses a string argument and returns an integer of the specified base. var ParseIntFunc = function.New(&function.Spec{ + Description: `Parses the given string as a number of the given base, or raises an error if the string contains invalid characters.`, Params: []function.Parameter{ { Name: "number", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go index 2dd6348..ab4257b 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/regexp.go @@ -10,6 +10,7 @@ import ( ) var RegexFunc = function.New(&function.Spec{ + Description: `Applies the given regular expression pattern to the given string and returns information about a single match, or raises an error if there is no match.`, Params: []function.Parameter{ { Name: "pattern", @@ -54,6 +55,7 @@ var RegexFunc = function.New(&function.Spec{ }) var RegexAllFunc = function.New(&function.Spec{ + Description: `Applies the given regular expression pattern to the given string and returns a list of information about all non-overlapping matches, or an empty list if there are no matches.`, Params: []function.Parameter{ { Name: "pattern", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go index d3cc341..6b2d97b 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go @@ -9,10 +9,12 @@ import ( ) var ConcatFunc = function.New(&function.Spec{ - Params: []function.Parameter{}, + Description: `Concatenates together all of the given lists or tuples into a single sequence, preserving the input order.`, + Params: []function.Parameter{}, VarParam: &function.Parameter{ - Name: "seqs", - Type: cty.DynamicPseudoType, + Name: "seqs", + Type: cty.DynamicPseudoType, + AllowMarked: true, }, Type: func(args []cty.Value) (ret cty.Type, err error) { if len(args) == 0 { @@ -42,6 +44,10 @@ var ConcatFunc = function.New(&function.Spec{ etys := make([]cty.Type, 0, len(args)) for i, val := range args { + // Discard marks for nested values, as we only need to handle types + // and lengths. + val, _ := val.UnmarkDeep() + ety := val.Type() switch { case ety.IsTupleType(): @@ -75,6 +81,7 @@ var ConcatFunc = function.New(&function.Spec{ // given values will be lists and that they will either be of // retType or of something we can convert to retType. vals := make([]cty.Value, 0, len(args)) + var markses []cty.ValueMarks // remember any marked lists we find for i, list := range args { list, err = convert.Convert(list, retType) if err != nil { @@ -83,6 +90,11 @@ var ConcatFunc = function.New(&function.Spec{ return cty.NilVal, function.NewArgError(i, err) } + list, listMarks := list.Unmark() + if len(listMarks) > 0 { + markses = append(markses, listMarks) + } + it := list.ElementIterator() for it.Next() { _, v := it.Element() @@ -90,10 +102,10 @@ var ConcatFunc = function.New(&function.Spec{ } } if len(vals) == 0 { - return cty.ListValEmpty(retType.ElementType()), nil + return cty.ListValEmpty(retType.ElementType()).WithMarks(markses...), nil } - return cty.ListVal(vals), nil + return cty.ListVal(vals).WithMarks(markses...), nil case retType.IsTupleType(): // If retType is a tuple type then we could have a mixture of // lists and tuples but we know they all have known values @@ -101,8 +113,14 @@ var ConcatFunc = function.New(&function.Spec{ // concatenating them all together will produce a tuple of // retType because of the work we did in the Type function above. vals := make([]cty.Value, 0, len(args)) + var markses []cty.ValueMarks // remember any marked seqs we find for _, seq := range args { + seq, seqMarks := seq.Unmark() + if len(seqMarks) > 0 { + markses = append(markses, seqMarks) + } + // Both lists and tuples support ElementIterator, so this is easy. it := seq.ElementIterator() for it.Next() { @@ -111,7 +129,7 @@ var ConcatFunc = function.New(&function.Spec{ } } - return cty.TupleVal(vals), nil + return cty.TupleVal(vals).WithMarks(markses...), nil default: // should never happen if Type is working correctly above panic("unsupported return type") @@ -120,6 +138,7 @@ var ConcatFunc = function.New(&function.Spec{ }) var RangeFunc = function.New(&function.Spec{ + Description: `Returns a list of numbers spread evenly over a particular range.`, VarParam: &function.Parameter{ Name: "params", Type: cty.Number, diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go index 29c425e..15f4c05 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/set.go @@ -10,6 +10,7 @@ import ( ) var SetHasElementFunc = function.New(&function.Spec{ + Description: `Returns true if the given set contains the given element, or false otherwise.`, Params: []function.Parameter{ { Name: "set", @@ -29,6 +30,7 @@ var SetHasElementFunc = function.New(&function.Spec{ }) var SetUnionFunc = function.New(&function.Spec{ + Description: `Returns the union of all given sets.`, Params: []function.Parameter{ { Name: "first_set", @@ -48,6 +50,7 @@ var SetUnionFunc = function.New(&function.Spec{ }) var SetIntersectionFunc = function.New(&function.Spec{ + Description: `Returns the intersection of all given sets.`, Params: []function.Parameter{ { Name: "first_set", @@ -67,6 +70,7 @@ var SetIntersectionFunc = function.New(&function.Spec{ }) var SetSubtractFunc = function.New(&function.Spec{ + Description: `Returns the relative complement of the two given sets.`, Params: []function.Parameter{ { Name: "a", @@ -86,6 +90,7 @@ var SetSubtractFunc = function.New(&function.Spec{ }) var SetSymmetricDifferenceFunc = function.New(&function.Spec{ + Description: `Returns the symmetric difference of the two given sets.`, Params: []function.Parameter{ { Name: "first_set", diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go index 43182dd..f340ef7 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go @@ -14,6 +14,7 @@ import ( ) var UpperFunc = function.New(&function.Spec{ + Description: "Returns the given string with all Unicode letters translated to their uppercase equivalents.", Params: []function.Parameter{ { Name: "str", @@ -30,6 +31,7 @@ var UpperFunc = function.New(&function.Spec{ }) var LowerFunc = function.New(&function.Spec{ + Description: "Returns the given string with all Unicode letters translated to their lowercase equivalents.", Params: []function.Parameter{ { Name: "str", @@ -46,6 +48,7 @@ var LowerFunc = function.New(&function.Spec{ }) var ReverseFunc = function.New(&function.Spec{ + Description: "Returns the given string with all of its Unicode characters in reverse order.", Params: []function.Parameter{ { Name: "str", @@ -73,6 +76,7 @@ var ReverseFunc = function.New(&function.Spec{ }) var StrlenFunc = function.New(&function.Spec{ + Description: "Returns the number of Unicode characters (technically: grapheme clusters) in the given string.", Params: []function.Parameter{ { Name: "str", @@ -97,19 +101,23 @@ var StrlenFunc = function.New(&function.Spec{ }) var SubstrFunc = function.New(&function.Spec{ + Description: "Extracts a substring from the given string.", Params: []function.Parameter{ { Name: "str", + Description: "The input string.", Type: cty.String, AllowDynamicType: true, }, { Name: "offset", + Description: "The starting offset in Unicode characters.", Type: cty.Number, AllowDynamicType: true, }, { Name: "length", + Description: "The maximum length of the result in Unicode characters.", Type: cty.Number, AllowDynamicType: true, }, @@ -197,15 +205,18 @@ var SubstrFunc = function.New(&function.Spec{ }) var JoinFunc = function.New(&function.Spec{ + Description: "Concatenates together the elements of all given lists with a delimiter, producing a single string.", Params: []function.Parameter{ { - Name: "separator", - Type: cty.String, + Name: "separator", + Description: "Delimiter to insert between the given strings.", + Type: cty.String, }, }, VarParam: &function.Parameter{ - Name: "lists", - Type: cty.List(cty.String), + Name: "lists", + Description: "One or more lists of strings to join.", + Type: cty.List(cty.String), }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { @@ -244,6 +255,7 @@ var JoinFunc = function.New(&function.Spec{ }) var SortFunc = function.New(&function.Spec{ + Description: "Applies a lexicographic sort to the elements of the given list.", Params: []function.Parameter{ { Name: "list", @@ -282,14 +294,17 @@ var SortFunc = function.New(&function.Spec{ }) var SplitFunc = function.New(&function.Spec{ + Description: "Produces a list of one or more strings by splitting the given string at all instances of a given separator substring.", Params: []function.Parameter{ { - Name: "separator", - Type: cty.String, + Name: "separator", + Description: "The substring that delimits the result strings.", + Type: cty.String, }, { - Name: "str", - Type: cty.String, + Name: "str", + Description: "The string to split.", + Type: cty.String, }, }, Type: function.StaticReturnType(cty.List(cty.String)), @@ -311,6 +326,7 @@ var SplitFunc = function.New(&function.Spec{ // ChompFunc is a function that removes newline characters at the end of a // string. var ChompFunc = function.New(&function.Spec{ + Description: "Removes one or more newline characters from the end of the given string.", Params: []function.Parameter{ { Name: "str", @@ -327,14 +343,17 @@ var ChompFunc = function.New(&function.Spec{ // IndentFunc is a function that adds a given number of spaces to the // beginnings of all but the first line in a given multi-line string. var IndentFunc = function.New(&function.Spec{ + Description: "Adds a given number of spaces after each newline character in the given string.", Params: []function.Parameter{ { - Name: "spaces", - Type: cty.Number, + Name: "spaces", + Description: "Number of spaces to add after each newline character.", + Type: cty.Number, }, { - Name: "str", - Type: cty.String, + Name: "str", + Description: "The string to transform.", + Type: cty.String, }, }, Type: function.StaticReturnType(cty.String), @@ -352,6 +371,7 @@ var IndentFunc = function.New(&function.Spec{ // TitleFunc is a function that converts the first letter of each word in the // given string to uppercase. var TitleFunc = function.New(&function.Spec{ + Description: "Replaces one letter after each non-letter and non-digit character with its uppercase equivalent.", Params: []function.Parameter{ { Name: "str", @@ -367,6 +387,7 @@ var TitleFunc = function.New(&function.Spec{ // TrimSpaceFunc is a function that removes any space characters from the start // and end of the given string. var TrimSpaceFunc = function.New(&function.Spec{ + Description: "Removes any consecutive space characters (as defined by Unicode) from the start and end of the given string.", Params: []function.Parameter{ { Name: "str", @@ -382,20 +403,26 @@ var TrimSpaceFunc = function.New(&function.Spec{ // TrimFunc is a function that removes the specified characters from the start // and end of the given string. var TrimFunc = function.New(&function.Spec{ + Description: "Removes consecutive sequences of characters in \"cutset\" from the start and end of the given string.", Params: []function.Parameter{ { - Name: "str", - Type: cty.String, + Name: "str", + Description: "The string to trim.", + Type: cty.String, }, { - Name: "cutset", - Type: cty.String, + Name: "cutset", + Description: "A string containing all of the characters to trim. Each character is taken separately, so the order of characters is insignificant.", + Type: cty.String, }, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { str := args[0].AsString() cutset := args[1].AsString() + // NOTE: This doesn't properly handle any character that is encoded + // with multiple sequential code units, such as letters with + // combining diacritics and emoji modifier sequences. return cty.StringVal(strings.Trim(str, cutset)), nil }, }) @@ -403,14 +430,17 @@ var TrimFunc = function.New(&function.Spec{ // TrimPrefixFunc is a function that removes the specified characters from the // start the given string. var TrimPrefixFunc = function.New(&function.Spec{ + Description: "Removes the given prefix from the start of the given string, if present.", Params: []function.Parameter{ { - Name: "str", - Type: cty.String, + Name: "str", + Description: "The string to trim.", + Type: cty.String, }, { - Name: "prefix", - Type: cty.String, + Name: "prefix", + Description: "The prefix to remove, if present.", + Type: cty.String, }, }, Type: function.StaticReturnType(cty.String), @@ -424,14 +454,17 @@ var TrimPrefixFunc = function.New(&function.Spec{ // TrimSuffixFunc is a function that removes the specified characters from the // end of the given string. var TrimSuffixFunc = function.New(&function.Spec{ + Description: "Removes the given suffix from the start of the given string, if present.", Params: []function.Parameter{ { - Name: "str", - Type: cty.String, + Name: "str", + Description: "The string to trim.", + Type: cty.String, }, { - Name: "suffix", - Type: cty.String, + Name: "suffix", + Description: "The suffix to remove, if present.", + Type: cty.String, }, }, Type: function.StaticReturnType(cty.String), diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go index f777ce5..573083b 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string_replace.go @@ -12,18 +12,22 @@ import ( // substring, and replaces each occurence with a given replacement string. // The substr argument is a simple string. var ReplaceFunc = function.New(&function.Spec{ + Description: `Replaces all instances of the given substring in the given string with the given replacement string.`, Params: []function.Parameter{ { - Name: "str", - Type: cty.String, + Name: "str", + Description: `The string to search within.`, + Type: cty.String, }, { - Name: "substr", - Type: cty.String, + Name: "substr", + Description: `The substring to search for.`, + Type: cty.String, }, { - Name: "replace", - Type: cty.String, + Name: "replace", + Description: `The new substring to replace substr with.`, + Type: cty.String, }, }, Type: function.StaticReturnType(cty.String), @@ -40,13 +44,14 @@ var ReplaceFunc = function.New(&function.Spec{ // given substring, and replaces each occurence with a given replacement // string. The substr argument must be a valid regular expression. var RegexReplaceFunc = function.New(&function.Spec{ + Description: `Applies the given regular expression pattern to the given string and replaces all matches with the given replacement string.`, Params: []function.Parameter{ { Name: "str", Type: cty.String, }, { - Name: "substr", + Name: "pattern", Type: cty.String, }, { diff --git a/vendor/github.com/zclconf/go-cty/cty/gob.go b/vendor/github.com/zclconf/go-cty/cty/gob.go deleted file mode 100644 index a0961b8..0000000 --- a/vendor/github.com/zclconf/go-cty/cty/gob.go +++ /dev/null @@ -1,204 +0,0 @@ -package cty - -import ( - "bytes" - "encoding/gob" - "errors" - "fmt" - "math/big" - - "github.com/zclconf/go-cty/cty/set" -) - -// GobEncode is an implementation of the gob.GobEncoder interface, which -// allows Values to be included in structures encoded with encoding/gob. -// -// Currently it is not possible to represent values of capsule types in gob, -// because the types themselves cannot be represented. -func (val Value) GobEncode() ([]byte, error) { - if val.IsMarked() { - return nil, errors.New("value is marked") - } - - buf := &bytes.Buffer{} - enc := gob.NewEncoder(buf) - - gv := gobValue{ - Version: 0, - Ty: val.ty, - V: val.v, - } - - err := enc.Encode(gv) - if err != nil { - return nil, fmt.Errorf("error encoding cty.Value: %s", err) - } - - return buf.Bytes(), nil -} - -// GobDecode is an implementation of the gob.GobDecoder interface, which -// inverts the operation performed by GobEncode. See the documentation of -// GobEncode for considerations when using cty.Value instances with gob. -func (val *Value) GobDecode(buf []byte) error { - r := bytes.NewReader(buf) - dec := gob.NewDecoder(r) - - var gv gobValue - err := dec.Decode(&gv) - if err != nil { - return fmt.Errorf("error decoding cty.Value: %s", err) - } - if gv.Version != 0 { - return fmt.Errorf("unsupported cty.Value encoding version %d; only 0 is supported", gv.Version) - } - - // Because big.Float.GobEncode is implemented with a pointer reciever, - // gob encoding of an interface{} containing a *big.Float value does not - // round-trip correctly, emerging instead as a non-pointer big.Float. - // The rest of cty expects all number values to be represented by - // *big.Float, so we'll fix that up here. - gv.V = gobDecodeFixNumberPtr(gv.V, gv.Ty) - - val.ty = gv.Ty - val.v = gv.V - - return nil -} - -// GobEncode is an implementation of the gob.GobEncoder interface, which -// allows Types to be included in structures encoded with encoding/gob. -// -// Currently it is not possible to represent capsule types in gob. -func (t Type) GobEncode() ([]byte, error) { - buf := &bytes.Buffer{} - enc := gob.NewEncoder(buf) - - gt := gobType{ - Version: 0, - Impl: t.typeImpl, - } - - err := enc.Encode(gt) - if err != nil { - return nil, fmt.Errorf("error encoding cty.Type: %s", err) - } - - return buf.Bytes(), nil -} - -// GobDecode is an implementatino of the gob.GobDecoder interface, which -// reverses the encoding performed by GobEncode to allow types to be recovered -// from gob buffers. -func (t *Type) GobDecode(buf []byte) error { - r := bytes.NewReader(buf) - dec := gob.NewDecoder(r) - - var gt gobType - err := dec.Decode(>) - if err != nil { - return fmt.Errorf("error decoding cty.Type: %s", err) - } - if gt.Version != 0 { - return fmt.Errorf("unsupported cty.Type encoding version %d; only 0 is supported", gt.Version) - } - - t.typeImpl = gt.Impl - - return nil -} - -// 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(friendlyTypeName)) -} - -func (t *capsuleType) GobDecode() ([]byte, error) { - return nil, fmt.Errorf("cannot gob-decode capsule type %q", t.FriendlyName(friendlyTypeName)) -} - -type gobValue struct { - Version int - Ty Type - V interface{} -} - -type gobType struct { - Version int - Impl typeImpl -} - -type gobCapsuleTypeImpl struct { -} - -// goDecodeFixNumberPtr fixes an unfortunate quirk of round-tripping cty.Number -// values through gob: the big.Float.GobEncode method is implemented on a -// pointer receiver, and so it loses the "pointer-ness" of the value on -// encode, causing the values to emerge the other end as big.Float rather than -// *big.Float as we expect elsewhere in cty. -// -// The implementation of gobDecodeFixNumberPtr mutates the given raw value -// during its work, and may either return the same value mutated or a new -// value. Callers must no longer use whatever value they pass as "raw" after -// this function is called. -func gobDecodeFixNumberPtr(raw interface{}, ty Type) interface{} { - // Unfortunately we need to work recursively here because number values - // might be embedded in structural or collection type values. - - switch { - case ty.Equals(Number): - if bf, ok := raw.(big.Float); ok { - return &bf // wrap in pointer - } - case ty.IsMapType() && ty.ElementType().Equals(Number): - if m, ok := raw.(map[string]interface{}); ok { - for k, v := range m { - m[k] = gobDecodeFixNumberPtr(v, ty.ElementType()) - } - } - case ty.IsListType() && ty.ElementType().Equals(Number): - if s, ok := raw.([]interface{}); ok { - for i, v := range s { - s[i] = gobDecodeFixNumberPtr(v, ty.ElementType()) - } - } - case ty.IsSetType() && ty.ElementType().Equals(Number): - if s, ok := raw.(set.Set); ok { - newS := set.NewSet(s.Rules()) - for it := s.Iterator(); it.Next(); { - newV := gobDecodeFixNumberPtr(it.Value(), ty.ElementType()) - newS.Add(newV) - } - return newS - } - case ty.IsObjectType(): - if m, ok := raw.(map[string]interface{}); ok { - for k, v := range m { - aty := ty.AttributeType(k) - m[k] = gobDecodeFixNumberPtr(v, aty) - } - } - case ty.IsTupleType(): - if s, ok := raw.([]interface{}); ok { - for i, v := range s { - ety := ty.TupleElementType(i) - s[i] = gobDecodeFixNumberPtr(v, ety) - } - } - } - - return raw -} - -// gobDecodeFixNumberPtrVal is a helper wrapper around gobDecodeFixNumberPtr -// that works with already-constructed values. This is primarily for testing, -// to fix up intentionally-invalid number values for the parts of the test -// code that need them to be valid, such as calling GoString on them. -func gobDecodeFixNumberPtrVal(v Value) Value { - raw := gobDecodeFixNumberPtr(v.v, v.ty) - return Value{ - v: raw, - ty: v.ty, - } -} diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go index 94ffd2f..98e5ba1 100644 --- a/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/helpers.go @@ -11,7 +11,7 @@ import ( var valueType = reflect.TypeOf(cty.Value{}) var typeType = reflect.TypeOf(cty.Type{}) -var setType = reflect.TypeOf(set.Set{}) +var setType = reflect.TypeOf(set.Set[interface{}]{}) var bigFloatType = reflect.TypeOf(big.Float{}) var bigIntType = reflect.TypeOf(big.Int{}) diff --git a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go index ca9de21..6cb308b 100644 --- a/vendor/github.com/zclconf/go-cty/cty/gocty/in.go +++ b/vendor/github.com/zclconf/go-cty/cty/gocty/in.go @@ -268,7 +268,7 @@ func toCtySet(val reflect.Value, ety cty.Type, path cty.Path) (cty.Value, error) return cty.NilVal, path.NewErrorf("can't convert Go %s to %#v", val.Type(), cty.Set(ety)) } - rawSet := val.Interface().(set.Set) + rawSet := val.Interface().(set.Set[interface{}]) inVals := rawSet.Values() if len(inVals) == 0 { diff --git a/vendor/github.com/zclconf/go-cty/cty/map_type.go b/vendor/github.com/zclconf/go-cty/cty/map_type.go index 82d36c6..732c78a 100644 --- a/vendor/github.com/zclconf/go-cty/cty/map_type.go +++ b/vendor/github.com/zclconf/go-cty/cty/map_type.go @@ -51,7 +51,7 @@ func (t typeMap) GoString() string { return fmt.Sprintf("cty.Map(%#v)", t.ElementTypeT) } -// IsMapType returns true if the given type is a list type, regardless of its +// IsMapType returns true if the given type is a map type, regardless of its // element type. func (t Type) IsMapType() bool { _, ok := t.typeImpl.(typeMap) diff --git a/vendor/github.com/zclconf/go-cty/cty/marks.go b/vendor/github.com/zclconf/go-cty/cty/marks.go index 4e1d3b1..b889e73 100644 --- a/vendor/github.com/zclconf/go-cty/cty/marks.go +++ b/vendor/github.com/zclconf/go-cty/cty/marks.go @@ -27,14 +27,32 @@ type marker struct { type ValueMarks map[interface{}]struct{} // NewValueMarks constructs a new ValueMarks set with the given mark values. +// +// If any of the arguments are already ValueMarks values then they'll be merged +// into the result, rather than used directly as individual marks. func NewValueMarks(marks ...interface{}) ValueMarks { if len(marks) == 0 { return nil } ret := make(ValueMarks, len(marks)) for _, v := range marks { + if vm, ok := v.(ValueMarks); ok { + // Constructing a new ValueMarks with an existing ValueMarks + // implements a merge operation. (This can cause our result to + // have a larger size than we expected, but that's okay.) + for v := range vm { + ret[v] = struct{}{} + } + continue + } ret[v] = struct{}{} } + if len(ret) == 0 { + // If we were merging ValueMarks values together and they were all + // empty then we'll avoid returning a zero-length map and return a + // nil instead, as is conventional. + return nil + } return ret } @@ -180,6 +198,9 @@ func (val Value) Mark(mark interface{}) Value { for k, v := range mr.marks { newMarker.marks[k] = v } + // unwrap the inner marked value, so we don't get multiple layers + // of marking. + newMarker.realV = mr.realV } else { // It's not a marker yet, so we're creating the first mark. newMarker.marks = make(ValueMarks, 1) diff --git a/vendor/github.com/zclconf/go-cty/cty/path_set.go b/vendor/github.com/zclconf/go-cty/cty/path_set.go index 1960c01..3ebfdc3 100644 --- a/vendor/github.com/zclconf/go-cty/cty/path_set.go +++ b/vendor/github.com/zclconf/go-cty/cty/path_set.go @@ -11,14 +11,14 @@ import ( // to talk about a subset of paths within a value that meet some criteria, // without directly modifying the values at those paths. type PathSet struct { - set set.Set + set set.Set[Path] } // NewPathSet creates and returns a PathSet, with initial contents optionally // set by the given arguments. func NewPathSet(paths ...Path) PathSet { ret := PathSet{ - set: set.NewSet(pathSetRules{}), + set: set.NewSet(set.Rules[Path](pathSetRules{})), } for _, path := range paths { @@ -61,7 +61,7 @@ func (s PathSet) List() []Path { } ret := make([]Path, 0, s.set.Length()) for it := s.set.Iterator(); it.Next(); { - ret = append(ret, it.Value().(Path)) + ret = append(ret, it.Value()) } return ret } @@ -134,8 +134,7 @@ var indexStepPlaceholder = []byte("#") type pathSetRules struct { } -func (r pathSetRules) Hash(v interface{}) int { - path := v.(Path) +func (r pathSetRules) Hash(path Path) int { hash := crc64.New(crc64Table) for _, rawStep := range path { @@ -159,10 +158,7 @@ func (r pathSetRules) Hash(v interface{}) int { return int(hash.Sum64()) } -func (r pathSetRules) Equivalent(a, b interface{}) bool { - aPath := a.(Path) - bPath := b.(Path) - +func (r pathSetRules) Equivalent(aPath, bPath Path) bool { if len(aPath) != len(bPath) { return false } @@ -198,7 +194,7 @@ func (r pathSetRules) Equivalent(a, b interface{}) bool { } // SameRules is true if both Rules instances are pathSetRules structs. -func (r pathSetRules) SameRules(other set.Rules) bool { +func (r pathSetRules) SameRules(other set.Rules[Path]) bool { _, ok := other.(pathSetRules) return ok } diff --git a/vendor/github.com/zclconf/go-cty/cty/primitive_type.go b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go index 7b3d119..3ce2540 100644 --- a/vendor/github.com/zclconf/go-cty/cty/primitive_type.go +++ b/vendor/github.com/zclconf/go-cty/cty/primitive_type.go @@ -52,6 +52,53 @@ func (t primitiveType) GoString() string { } } +// rawNumberEqual is our cty-specific definition of whether two big floats +// underlying cty.Number are "equal" for the purposes of the Value.Equals and +// Value.RawEquals methods. +// +// The built-in equality for big.Float is a direct comparison of the mantissa +// bits and the exponent, but that's too precise a check for cty because we +// routinely send numbers through decimal approximations and back and so +// we only promise to accurately represent the subset of binary floating point +// numbers that can be derived from a decimal string representation. +// +// In respect of the fact that cty only tries to preserve numbers that can +// reasonably be written in JSON documents, we use the string representation of +// a decimal approximation of the number as our comparison, relying on the +// big.Float type's heuristic for discarding extraneous mantissa bits that seem +// likely to only be there as a result of an earlier decimal-to-binary +// approximation during parsing, e.g. in ParseNumberVal. +func rawNumberEqual(a, b *big.Float) bool { + switch { + case (a == nil) != (b == nil): + return false + case a == nil: // b == nil too then, due to previous case + return true + case a.Sign() != b.Sign(): + return false + default: + // This format and precision matches that used by cty/json.Marshal, + // and thus achieves our definition of "two numbers are equal if + // we'd use the same JSON serialization for both of them". + const format = 'f' + const prec = -1 + aStr := a.Text(format, prec) + bStr := b.Text(format, prec) + + // The one exception to our rule about equality-by-stringification is + // negative zero, because we want -0 to always be equal to +0. + const posZero = "0" + const negZero = "-0" + if aStr == negZero { + aStr = posZero + } + if bStr == negZero { + bStr = posZero + } + return aStr == bStr + } +} + // Number is the numeric type. Number values are arbitrary-precision // decimal numbers, which can then be converted into Go's various numeric // types only if they are in the appropriate range. diff --git a/vendor/github.com/zclconf/go-cty/cty/set/gob.go b/vendor/github.com/zclconf/go-cty/cty/set/gob.go deleted file mode 100644 index da2978f..0000000 --- a/vendor/github.com/zclconf/go-cty/cty/set/gob.go +++ /dev/null @@ -1,76 +0,0 @@ -package set - -import ( - "bytes" - "encoding/gob" - "fmt" -) - -// GobEncode is an implementation of the interface gob.GobEncoder, allowing -// sets to be included in structures encoded via gob. -// -// The set rules are included in the serialized value, so the caller must -// register its concrete rules type with gob.Register before using a -// set in a gob, and possibly also implement GobEncode/GobDecode to customize -// how any parameters are persisted. -// -// The set elements are also included, so if they are of non-primitive types -// they too must be registered with gob. -// -// If the produced gob values will persist for a long time, the caller must -// ensure compatibility of the rules implementation. In particular, if the -// definition of element equivalence changes between encoding and decoding -// then two distinct stored elements may be considered equivalent on decoding, -// causing the recovered set to have fewer elements than when it was stored. -func (s Set) GobEncode() ([]byte, error) { - gs := gobSet{ - Version: 0, - Rules: s.rules, - Values: s.Values(), - } - - buf := &bytes.Buffer{} - enc := gob.NewEncoder(buf) - err := enc.Encode(gs) - if err != nil { - return nil, fmt.Errorf("error encoding set.Set: %s", err) - } - - return buf.Bytes(), nil -} - -// GobDecode is the opposite of GobEncode. See GobEncode for information -// on the requirements for and caveats of including set values in gobs. -func (s *Set) GobDecode(buf []byte) error { - r := bytes.NewReader(buf) - dec := gob.NewDecoder(r) - - var gs gobSet - err := dec.Decode(&gs) - if err != nil { - return fmt.Errorf("error decoding set.Set: %s", err) - } - if gs.Version != 0 { - return fmt.Errorf("unsupported set.Set encoding version %d; need 0", gs.Version) - } - - victim := NewSetFromSlice(gs.Rules, gs.Values) - s.vals = victim.vals - s.rules = victim.rules - return nil -} - -type gobSet struct { - Version int - Rules Rules - - // The bucket-based representation is for efficient in-memory access, but - // for serialization it's enough to just retain the values themselves, - // which we can re-bucket using the rules (which may have changed!) when - // we re-inflate. - Values []interface{} -} - -func init() { - gob.Register([]interface{}(nil)) -} diff --git a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go index 4a60494..60825b0 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set/iterator.go +++ b/vendor/github.com/zclconf/go-cty/cty/set/iterator.go @@ -1,15 +1,15 @@ package set -type Iterator struct { - vals []interface{} +type Iterator[T any] struct { + vals []T idx int } -func (it *Iterator) Value() interface{} { +func (it *Iterator[T]) Value() T { return it.vals[it.idx] } -func (it *Iterator) Next() bool { +func (it *Iterator[T]) Next() bool { it.idx++ return it.idx < len(it.vals) } diff --git a/vendor/github.com/zclconf/go-cty/cty/set/ops.go b/vendor/github.com/zclconf/go-cty/cty/set/ops.go index fd1555f..ffd950a 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set/ops.go +++ b/vendor/github.com/zclconf/go-cty/cty/set/ops.go @@ -7,10 +7,10 @@ import ( // Add inserts the given value into the receiving Set. // // This mutates the set in-place. This operation is not thread-safe. -func (s Set) Add(val interface{}) { +func (s Set[T]) Add(val T) { hv := s.rules.Hash(val) if _, ok := s.vals[hv]; !ok { - s.vals[hv] = make([]interface{}, 0, 1) + s.vals[hv] = make([]T, 0, 1) } bucket := s.vals[hv] @@ -26,7 +26,7 @@ func (s Set) Add(val interface{}) { // Remove deletes the given value from the receiving set, if indeed it was // there in the first place. If the value is not present, this is a no-op. -func (s Set) Remove(val interface{}) { +func (s Set[T]) Remove(val T) { hv := s.rules.Hash(val) bucket, ok := s.vals[hv] if !ok { @@ -35,7 +35,7 @@ func (s Set) Remove(val interface{}) { for i, ev := range bucket { if s.rules.Equivalent(val, ev) { - newBucket := make([]interface{}, 0, len(bucket)-1) + newBucket := make([]T, 0, len(bucket)-1) newBucket = append(newBucket, bucket[:i]...) newBucket = append(newBucket, bucket[i+1:]...) if len(newBucket) > 0 { @@ -50,7 +50,7 @@ func (s Set) Remove(val interface{}) { // Has returns true if the given value is in the receiving set, or false if // it is not. -func (s Set) Has(val interface{}) bool { +func (s Set[T]) Has(val T) bool { hv := s.rules.Hash(val) bucket, ok := s.vals[hv] if !ok { @@ -67,7 +67,7 @@ func (s Set) Has(val interface{}) bool { // Copy performs a shallow copy of the receiving set, returning a new set // with the same rules and elements. -func (s Set) Copy() Set { +func (s Set[T]) Copy() Set[T] { ret := NewSet(s.rules) for k, v := range s.vals { ret.vals[k] = v @@ -92,10 +92,10 @@ func (s Set) Copy() Set { // // Once an iterator has been created for a set, the set *must not* be mutated // until the iterator is no longer in use. -func (s Set) Iterator() *Iterator { +func (s Set[T]) Iterator() *Iterator[T] { vals := s.Values() - return &Iterator{ + return &Iterator[T]{ vals: vals, idx: -1, } @@ -103,7 +103,7 @@ func (s Set) Iterator() *Iterator { // EachValue calls the given callback once for each value in the set, in an // undefined order that callers should not depend on. -func (s Set) EachValue(cb func(interface{})) { +func (s Set[T]) EachValue(cb func(T)) { it := s.Iterator() for it.Next() { cb(it.Value()) @@ -114,8 +114,8 @@ func (s Set) EachValue(cb func(interface{})) { // an order then the result is in that order. If no order is provided or if // it is not a total order then the result order is undefined, but consistent // for a particular set value within a specific release of cty. -func (s Set) Values() []interface{} { - var ret []interface{} +func (s Set[T]) Values() []T { + var ret []T // Sort the bucketIds to ensure that we always traverse in a // consistent order. bucketIDs := make([]int, 0, len(s.vals)) @@ -128,7 +128,7 @@ func (s Set) Values() []interface{} { ret = append(ret, s.vals[bucketID]...) } - if orderRules, ok := s.rules.(OrderedRules); ok { + if orderRules, ok := s.rules.(OrderedRules[T]); ok { sort.SliceStable(ret, func(i, j int) bool { return orderRules.Less(ret[i], ret[j]) }) @@ -138,7 +138,7 @@ func (s Set) Values() []interface{} { } // Length returns the number of values in the set. -func (s Set) Length() int { +func (s Set[T]) Length() int { var count int for _, bucket := range s.vals { count = count + len(bucket) @@ -149,13 +149,13 @@ func (s Set) Length() int { // Union returns a new set that contains all of the members of both the // receiving set and the given set. Both sets must have the same rules, or // else this function will panic. -func (s1 Set) Union(s2 Set) Set { +func (s1 Set[T]) Union(s2 Set[T]) Set[T] { mustHaveSameRules(s1, s2) rs := NewSet(s1.rules) - s1.EachValue(func(v interface{}) { + s1.EachValue(func(v T) { rs.Add(v) }) - s2.EachValue(func(v interface{}) { + s2.EachValue(func(v T) { rs.Add(v) }) return rs @@ -164,10 +164,10 @@ func (s1 Set) Union(s2 Set) Set { // Intersection returns a new set that contains the values that both the // receiver and given sets have in common. Both sets must have the same rules, // or else this function will panic. -func (s1 Set) Intersection(s2 Set) Set { +func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] { mustHaveSameRules(s1, s2) rs := NewSet(s1.rules) - s1.EachValue(func(v interface{}) { + s1.EachValue(func(v T) { if s2.Has(v) { rs.Add(v) } @@ -178,10 +178,10 @@ func (s1 Set) Intersection(s2 Set) Set { // Subtract returns a new set that contains all of the values from the receiver // that are not also in the given set. Both sets must have the same rules, // or else this function will panic. -func (s1 Set) Subtract(s2 Set) Set { +func (s1 Set[T]) Subtract(s2 Set[T]) Set[T] { mustHaveSameRules(s1, s2) rs := NewSet(s1.rules) - s1.EachValue(func(v interface{}) { + s1.EachValue(func(v T) { if !s2.Has(v) { rs.Add(v) } @@ -193,15 +193,15 @@ func (s1 Set) Subtract(s2 Set) Set { // both the receiver and given sets, except those that both sets have in // common. Both sets must have the same rules, or else this function will // panic. -func (s1 Set) SymmetricDifference(s2 Set) Set { +func (s1 Set[T]) SymmetricDifference(s2 Set[T]) Set[T] { mustHaveSameRules(s1, s2) rs := NewSet(s1.rules) - s1.EachValue(func(v interface{}) { + s1.EachValue(func(v T) { if !s2.Has(v) { rs.Add(v) } }) - s2.EachValue(func(v interface{}) { + s2.EachValue(func(v T) { if !s1.Has(v) { rs.Add(v) } diff --git a/vendor/github.com/zclconf/go-cty/cty/set/rules.go b/vendor/github.com/zclconf/go-cty/cty/set/rules.go index 03ecd25..da4c768 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set/rules.go +++ b/vendor/github.com/zclconf/go-cty/cty/set/rules.go @@ -4,13 +4,13 @@ package set // // Each Set has a Rules instance, whose methods must satisfy the interface // contracts given below for any value that will be added to the set. -type Rules interface { +type Rules[T any] interface { // Hash returns an int that somewhat-uniquely identifies the given value. // // A good hash function will minimize collisions for values that will be // added to the set, though collisions *are* permitted. Collisions will // simply reduce the efficiency of operations on the set. - Hash(interface{}) int + Hash(T) int // Equivalent returns true if and only if the two values are considered // equivalent for the sake of set membership. Two values that are @@ -21,11 +21,11 @@ type Rules interface { // Two values that are equivalent *must* result in the same hash value, // though it is *not* required that two values with the same hash value // be equivalent. - Equivalent(interface{}, interface{}) bool + Equivalent(T, T) bool // SameRules returns true if the instance is equivalent to another Rules - // instance. - SameRules(Rules) bool + // instance over the same element type. + SameRules(Rules[T]) bool } // OrderedRules is an extension of Rules that can apply a partial order to @@ -37,8 +37,8 @@ type Rules interface { // is undefined but consistent for a particular version of cty. The exact // order in that case is not part of the contract and is subject to change // between versions. -type OrderedRules interface { - Rules +type OrderedRules[T any] interface { + Rules[T] // Less returns true if and only if the first argument should sort before // the second argument. If the second argument should sort before the first diff --git a/vendor/github.com/zclconf/go-cty/cty/set/set.go b/vendor/github.com/zclconf/go-cty/cty/set/set.go index 15a7663..761b0ff 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set/set.go +++ b/vendor/github.com/zclconf/go-cty/cty/set/set.go @@ -19,20 +19,20 @@ import ( // Set operations are not optimized to minimize memory pressure. Mutating // a set will generally create garbage and so should perhaps be avoided in // tight loops where memory pressure is a concern. -type Set struct { - vals map[int][]interface{} - rules Rules +type Set[T any] struct { + vals map[int][]T + rules Rules[T] } // NewSet returns an empty set with the membership rules given. -func NewSet(rules Rules) Set { - return Set{ - vals: map[int][]interface{}{}, +func NewSet[T any](rules Rules[T]) Set[T] { + return Set[T]{ + vals: map[int][]T{}, rules: rules, } } -func NewSetFromSlice(rules Rules, vals []interface{}) Set { +func NewSetFromSlice[T any](rules Rules[T], vals []T) Set[T] { s := NewSet(rules) for _, v := range vals { s.Add(v) @@ -40,11 +40,11 @@ func NewSetFromSlice(rules Rules, vals []interface{}) Set { return s } -func sameRules(s1 Set, s2 Set) bool { +func sameRules[T any](s1 Set[T], s2 Set[T]) bool { return s1.rules.SameRules(s2.rules) } -func mustHaveSameRules(s1 Set, s2 Set) { +func mustHaveSameRules[T any](s1 Set[T], s2 Set[T]) { if !sameRules(s1, s2) { panic(fmt.Errorf("incompatible set rules: %#v, %#v", s1.rules, s2.rules)) } @@ -52,11 +52,11 @@ func mustHaveSameRules(s1 Set, s2 Set) { // HasRules returns true if and only if the receiving set has the given rules // instance as its rules. -func (s Set) HasRules(rules Rules) bool { +func (s Set[T]) HasRules(rules Rules[T]) bool { return s.rules.SameRules(rules) } // Rules returns the receiving set's rules instance. -func (s Set) Rules() Rules { +func (s Set[T]) Rules() Rules[T] { return s.rules } diff --git a/vendor/github.com/zclconf/go-cty/cty/set_helper.go b/vendor/github.com/zclconf/go-cty/cty/set_helper.go index 962bb52..5d39805 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set_helper.go +++ b/vendor/github.com/zclconf/go-cty/cty/set_helper.go @@ -21,15 +21,15 @@ type ValueSet struct { // ValueSet is just a thin wrapper around a set.Set with our value-oriented // "rules" applied. We do this so that the caller can work in terms of // cty.Value objects even though the set internals use the raw values. - s set.Set + s set.Set[interface{}] } // NewValueSet creates and returns a new ValueSet with the given element type. func NewValueSet(ety Type) ValueSet { - return newValueSet(set.NewSet(setRules{Type: ety})) + return newValueSet(set.NewSet(newSetRules(ety))) } -func newValueSet(s set.Set) ValueSet { +func newValueSet(s set.Set[interface{}]) ValueSet { return ValueSet{ s: s, } diff --git a/vendor/github.com/zclconf/go-cty/cty/set_internals.go b/vendor/github.com/zclconf/go-cty/cty/set_internals.go index 2b8af1e..7b3d425 100644 --- a/vendor/github.com/zclconf/go-cty/cty/set_internals.go +++ b/vendor/github.com/zclconf/go-cty/cty/set_internals.go @@ -21,7 +21,11 @@ type setRules struct { Type Type } -var _ set.OrderedRules = setRules{} +var _ set.OrderedRules[interface{}] = setRules{} + +func newSetRules(ety Type) set.Rules[interface{}] { + return setRules{ety} +} // Hash returns a hash value for the receiver that can be used for equality // checks where some inaccuracy is tolerable. @@ -67,7 +71,7 @@ func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool { // SameRules is only true if the other Rules instance is also a setRules struct, // and the types are considered equal. -func (r setRules) SameRules(other set.Rules) bool { +func (r setRules) SameRules(other set.Rules[interface{}]) bool { rules, ok := other.(setRules) if !ok { return false @@ -250,6 +254,25 @@ func appendSetHashBytes(val Value, buf *bytes.Buffer, marks ValueMarks) { return } + if val.ty.IsCapsuleType() { + buf.WriteRune('«') + ops := val.ty.CapsuleOps() + if ops != nil && ops.HashKey != nil { + key := ops.HashKey(val.EncapsulatedValue()) + buf.WriteString(fmt.Sprintf("%q", key)) + } else { + // If there isn't an explicit hash implementation then we'll + // just generate the same hash value for every value of this + // type, which is logically fine but less efficient for + // larger sets because we'll have to bucket all values + // together and scan over them with Equals to determine + // set membership. + buf.WriteRune('?') + } + buf.WriteRune('»') + return + } + // should never get down here - panic("unsupported type in set hash") + panic(fmt.Sprintf("unsupported type %#v in set hash", val.ty)) } diff --git a/vendor/github.com/zclconf/go-cty/cty/types_to_register.go b/vendor/github.com/zclconf/go-cty/cty/types_to_register.go deleted file mode 100644 index e1e220a..0000000 --- a/vendor/github.com/zclconf/go-cty/cty/types_to_register.go +++ /dev/null @@ -1,57 +0,0 @@ -package cty - -import ( - "encoding/gob" - "fmt" - "math/big" - "strings" - - "github.com/zclconf/go-cty/cty/set" -) - -// InternalTypesToRegister is a slice of values that covers all of the -// internal types used in the representation of cty.Type and cty.Value -// across all cty Types. -// -// This is intended to be used to register these types with encoding -// packages that require registration of types used in interfaces, such as -// encoding/gob, thus allowing cty types and values to be included in streams -// created from those packages. However, registering with gob is not necessary -// since that is done automatically as a side-effect of importing this package. -// -// Callers should not do anything with the values here except pass them on -// verbatim to a registration function. -// -// If the calling application uses Capsule types that wrap local structs either -// directly or indirectly, these structs may also need to be registered in -// order to support encoding and decoding of values of these types. That is the -// responsibility of the calling application. -var InternalTypesToRegister []interface{} - -func init() { - InternalTypesToRegister = []interface{}{ - primitiveType{}, - typeList{}, - typeMap{}, - typeObject{}, - typeSet{}, - setRules{}, - set.Set{}, - typeTuple{}, - big.Float{}, - capsuleType{}, - []interface{}(nil), - map[string]interface{}(nil), - } - - // Register these with gob here, rather than in gob.go, to ensure - // that this will always happen after we build the above. - for _, tv := range InternalTypesToRegister { - typeName := fmt.Sprintf("%T", tv) - if strings.HasPrefix(typeName, "cty.") { - gob.RegisterName(fmt.Sprintf("github.com/zclconf/go-cty/%s", typeName), tv) - } else { - gob.Register(tv) - } - } -} diff --git a/vendor/github.com/zclconf/go-cty/cty/value_init.go b/vendor/github.com/zclconf/go-cty/cty/value_init.go index 25ee0b6..6dcae27 100644 --- a/vendor/github.com/zclconf/go-cty/cty/value_init.go +++ b/vendor/github.com/zclconf/go-cty/cty/value_init.go @@ -287,7 +287,7 @@ func SetVal(vals []Value) Value { rawList[i] = val.v } - rawVal := set.NewSetFromSlice(setRules{elementType}, rawList) + rawVal := set.NewSetFromSlice(set.Rules[interface{}](setRules{elementType}), rawList) return Value{ ty: Set(elementType), @@ -334,7 +334,7 @@ func SetValFromValueSet(s ValueSet) Value { func SetValEmpty(element Type) Value { return Value{ ty: Set(element), - v: set.NewSet(setRules{element}), + v: set.NewSet(set.Rules[interface{}](setRules{element})), } } diff --git a/vendor/github.com/zclconf/go-cty/cty/value_ops.go b/vendor/github.com/zclconf/go-cty/cty/value_ops.go index b33cc4f..88b3637 100644 --- a/vendor/github.com/zclconf/go-cty/cty/value_ops.go +++ b/vendor/github.com/zclconf/go-cty/cty/value_ops.go @@ -47,6 +47,9 @@ func (val Value) GoString() string { } return "cty.False" case Number: + if f, ok := val.v.(big.Float); ok { + panic(fmt.Sprintf("number value contains big.Float value %s, rather than pointer to big.Float", f.Text('g', -1))) + } fv := val.v.(*big.Float) // We'll try to use NumberIntVal or NumberFloatVal if we can, since // the fully-general initializer call is pretty ugly-looking. @@ -116,9 +119,9 @@ func (val Value) GoString() string { // Use RawEquals to compare if two values are equal *ignoring* the // short-circuit rules and the exception for null values. func (val Value) Equals(other Value) Value { - if val.IsMarked() || other.IsMarked() { - val, valMarks := val.Unmark() - other, otherMarks := other.Unmark() + if val.ContainsMarked() || other.ContainsMarked() { + val, valMarks := val.UnmarkDeep() + other, otherMarks := other.UnmarkDeep() return val.Equals(other).WithMarks(valMarks, otherMarks) } @@ -191,7 +194,7 @@ func (val Value) Equals(other Value) Value { switch { case ty == Number: - result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0 + result = rawNumberEqual(val.v.(*big.Float), other.v.(*big.Float)) case ty == Bool: result = val.v.(bool) == other.v.(bool) case ty == String: @@ -265,8 +268,8 @@ func (val Value) Equals(other Value) Value { } } case ty.IsSetType(): - s1 := val.v.(set.Set) - s2 := other.v.(set.Set) + s1 := val.v.(set.Set[interface{}]) + s2 := other.v.(set.Set[interface{}]) equal := true // Two sets are equal if all of their values are known and all values @@ -492,18 +495,23 @@ func (val Value) RawEquals(other Value) bool { case ty.IsMapType(): ety := ty.typeImpl.(typeMap).ElementTypeT - if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) { - for k := range val.v.(map[string]interface{}) { - if _, ok := other.v.(map[string]interface{})[k]; !ok { + if !val.HasSameMarks(other) { + return false + } + valUn, _ := val.Unmark() + otherUn, _ := other.Unmark() + if len(valUn.v.(map[string]interface{})) == len(otherUn.v.(map[string]interface{})) { + for k := range valUn.v.(map[string]interface{}) { + if _, ok := otherUn.v.(map[string]interface{})[k]; !ok { return false } lhs := Value{ ty: ety, - v: val.v.(map[string]interface{})[k], + v: valUn.v.(map[string]interface{})[k], } rhs := Value{ ty: ety, - v: other.v.(map[string]interface{})[k], + v: otherUn.v.(map[string]interface{})[k], } eq := lhs.RawEquals(rhs) if !eq { @@ -978,7 +986,7 @@ func (val Value) HasElement(elem Value) Value { return False } - s := val.v.(set.Set) + s := val.v.(set.Set[interface{}]) return BoolVal(s.Has(elem.v)) } @@ -1012,7 +1020,7 @@ func (val Value) Length() Value { // may or may not be equal to other elements in the set, and thus they // may or may not coalesce with other elements and produce fewer // items in the resulting set. - storeLength := int64(val.v.(set.Set).Length()) + storeLength := int64(val.v.(set.Set[interface{}]).Length()) if storeLength == 1 || val.IsWhollyKnown() { // If our set is wholly known then we know its length. // @@ -1073,7 +1081,7 @@ func (val Value) LengthInt() int { // compatibility with callers that were relying on LengthInt rather // than calling Length. Instead of panicking when a set contains an // unknown value, LengthInt returns the largest possible length. - return val.v.(set.Set).Length() + return val.v.(set.Set[interface{}]).Length() case val.ty.IsMapType(): return len(val.v.(map[string]interface{})) @@ -1278,9 +1286,7 @@ func (val Value) AsBigFloat() *big.Float { } // Copy the float so that callers can't mutate our internal state - ret := *(val.v.(*big.Float)) - - return &ret + return new(big.Float).Copy(val.v.(*big.Float)) } // AsValueSlice returns a []cty.Value representation of a non-null, non-unknown diff --git a/vendor/github.com/zclconf/go-cty/cty/walk.go b/vendor/github.com/zclconf/go-cty/cty/walk.go index d17f48c..87ba32e 100644 --- a/vendor/github.com/zclconf/go-cty/cty/walk.go +++ b/vendor/github.com/zclconf/go-cty/cty/walk.go @@ -33,10 +33,15 @@ func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error { return nil } + // The callback already got a chance to see the mark in our + // call above, so can safely strip it off here in order to + // visit the child elements, which might still have their own marks. + rawVal, _ := val.Unmark() + ty := val.Type() switch { case ty.IsObjectType(): - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { nameVal, av := it.Element() path := append(path, GetAttrStep{ Name: nameVal.AsString(), @@ -46,8 +51,8 @@ func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error { return err } } - case val.CanIterateElements(): - for it := val.ElementIterator(); it.Next(); { + case rawVal.CanIterateElements(): + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -134,6 +139,12 @@ func transform(path Path, val Value, t Transformer) (Value, error) { ty := val.Type() var newVal Value + // We need to peel off any marks here so that we can dig around + // inside any collection values. We'll reapply these to any + // new collections we construct, but the transformer's Exit + // method gets the final say on what to do with those. + rawVal, marks := val.Unmark() + switch { case val.IsNull() || !val.IsKnown(): @@ -141,14 +152,14 @@ func transform(path Path, val Value, t Transformer) (Value, error) { newVal = val case ty.IsListType() || ty.IsSetType() || ty.IsTupleType(): - l := val.LengthInt() + l := rawVal.LengthInt() switch l { case 0: // No deep transform for an empty sequence newVal = val default: elems := make([]Value, 0, l) - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -161,25 +172,25 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } switch { case ty.IsListType(): - newVal = ListVal(elems) + newVal = ListVal(elems).WithMarks(marks) case ty.IsSetType(): - newVal = SetVal(elems) + newVal = SetVal(elems).WithMarks(marks) case ty.IsTupleType(): - newVal = TupleVal(elems) + newVal = TupleVal(elems).WithMarks(marks) default: panic("unknown sequence type") // should never happen because of the case we are in } } case ty.IsMapType(): - l := val.LengthInt() + l := rawVal.LengthInt() switch l { case 0: // No deep transform for an empty map newVal = val default: elems := make(map[string]Value) - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -190,7 +201,7 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } elems[kv.AsString()] = newEv } - newVal = MapVal(elems) + newVal = MapVal(elems).WithMarks(marks) } case ty.IsObjectType(): @@ -212,7 +223,7 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } newAVs[name] = newAV } - newVal = ObjectVal(newAVs) + newVal = ObjectVal(newAVs).WithMarks(marks) } default: diff --git a/vendor/golang.org/x/text/encoding/ianaindex/ascii.go b/vendor/golang.org/x/text/encoding/ianaindex/ascii.go index 9792f81..2b9824f 100644 --- a/vendor/golang.org/x/text/encoding/ianaindex/ascii.go +++ b/vendor/golang.org/x/text/encoding/ianaindex/ascii.go @@ -10,8 +10,8 @@ import ( "golang.org/x/text/encoding" "golang.org/x/text/encoding/internal" - "golang.org/x/text/transform" "golang.org/x/text/encoding/internal/identifier" + "golang.org/x/text/transform" ) type asciiDecoder struct { @@ -22,7 +22,7 @@ func (d asciiDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, er for _, c := range src { if c > unicode.MaxASCII { r := unicode.ReplacementChar - if nDst + utf8.RuneLen(r) > len(dst) { + if nDst+utf8.RuneLen(r) > len(dst) { err = transform.ErrShortDst break } diff --git a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go index 26fbd55..f5a0788 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.10 && !go1.13 // +build go1.10,!go1.13 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go index 2c58f09..cb7239c 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.13 && !go1.14 // +build go1.13,!go1.14 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go index 7e1ae09..11b2733 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.14 && !go1.16 // +build go1.14,!go1.16 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go index 9ea1b42..96a130d 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.16 // +build go1.16 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go index 9429069..0175eae 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build !go1.10 // +build !go1.10 package norm diff --git a/vendor/modules.txt b/vendor/modules.txt index 299f7f9..b0b9d95 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -36,7 +36,7 @@ github.com/pmezard/go-difflib/difflib ## explicit github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/zclconf/go-cty v1.8.1 +# github.com/zclconf/go-cty v1.12.1 ## explicit github.com/zclconf/go-cty/cty github.com/zclconf/go-cty/cty/convert @@ -61,7 +61,7 @@ golang.org/x/crypto/ssh golang.org/x/crypto/ssh/internal/bcrypt_pbkdf # golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f golang.org/x/sys/cpu -# golang.org/x/text v0.3.5 +# golang.org/x/text v0.3.7 golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/ianaindex