mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
bump github.com/zclconf/go-cty from 1.7.1 to 1.10.0
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
27
vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
generated
vendored
27
vendor/github.com/zclconf/go-cty/cty/convert/conversion.go
generated
vendored
@ -33,14 +33,25 @@ func getConversion(in cty.Type, out cty.Type, unsafe bool) conversion {
|
||||
// Conversion to DynamicPseudoType always just passes through verbatim.
|
||||
return in, nil
|
||||
}
|
||||
if !in.IsKnown() {
|
||||
return cty.UnknownVal(out), nil
|
||||
}
|
||||
if in.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
|
||||
if isKnown, isNull := in.IsKnown(), in.IsNull(); !isKnown || isNull {
|
||||
// Avoid constructing unknown or null values with types which
|
||||
// include optional attributes. Known or non-null object values
|
||||
// will be passed to a conversion function which drops the optional
|
||||
// attributes from the type. Unknown and null pass through values
|
||||
// must do the same to ensure that homogeneous collections have a
|
||||
// single element type.
|
||||
out = out.WithoutOptionalAttributesDeep()
|
||||
|
||||
if !isKnown {
|
||||
return cty.UnknownVal(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 conv(in, path)
|
||||
|
57
vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
generated
vendored
57
vendor/github.com/zclconf/go-cty/cty/convert/conversion_collection.go
generated
vendored
@ -45,12 +45,18 @@ func conversionCollectionToList(ety cty.Type, conv conversion) conversion {
|
||||
}
|
||||
|
||||
if len(elems) == 0 {
|
||||
// Prefer a concrete type over a dynamic type when returning an
|
||||
// empty list
|
||||
if ety == cty.DynamicPseudoType {
|
||||
ety = val.Type().ElementType()
|
||||
return cty.ListValEmpty(val.Type().ElementType()), nil
|
||||
}
|
||||
return cty.ListValEmpty(ety), nil
|
||||
}
|
||||
|
||||
if !cty.CanListVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("element types must all match for conversion to list")
|
||||
}
|
||||
|
||||
return cty.ListVal(elems), nil
|
||||
}
|
||||
}
|
||||
@ -91,11 +97,15 @@ func conversionCollectionToSet(ety cty.Type, conv conversion) conversion {
|
||||
// Prefer a concrete type over a dynamic type when returning an
|
||||
// empty set
|
||||
if ety == cty.DynamicPseudoType {
|
||||
ety = val.Type().ElementType()
|
||||
return cty.SetValEmpty(val.Type().ElementType()), nil
|
||||
}
|
||||
return cty.SetValEmpty(ety), nil
|
||||
}
|
||||
|
||||
if !cty.CanSetVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("element types must all match for conversion to set")
|
||||
}
|
||||
|
||||
return cty.SetVal(elems), nil
|
||||
}
|
||||
}
|
||||
@ -140,7 +150,7 @@ func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
|
||||
// Prefer a concrete type over a dynamic type when returning an
|
||||
// empty map
|
||||
if ety == cty.DynamicPseudoType {
|
||||
ety = val.Type().ElementType()
|
||||
return cty.MapValEmpty(val.Type().ElementType()), nil
|
||||
}
|
||||
return cty.MapValEmpty(ety), nil
|
||||
}
|
||||
@ -152,8 +162,8 @@ func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
|
||||
}
|
||||
}
|
||||
|
||||
if err := conversionCheckMapElementTypes(elems, path); err != nil {
|
||||
return cty.NilVal, err
|
||||
if !cty.CanMapVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("element types must all match for conversion to map")
|
||||
}
|
||||
|
||||
return cty.MapVal(elems), nil
|
||||
@ -237,6 +247,10 @@ func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conv
|
||||
i++
|
||||
}
|
||||
|
||||
if !cty.CanSetVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("element types must all match for conversion to set")
|
||||
}
|
||||
|
||||
return cty.SetVal(elems), nil
|
||||
}
|
||||
}
|
||||
@ -324,6 +338,11 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
|
||||
if !cty.CanListVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("element types must all match for conversion to list")
|
||||
}
|
||||
|
||||
return cty.ListVal(elems), nil
|
||||
}
|
||||
}
|
||||
@ -402,8 +421,8 @@ func conversionObjectToMap(objectType cty.Type, mapEty cty.Type, unsafe bool) co
|
||||
}
|
||||
}
|
||||
|
||||
if err := conversionCheckMapElementTypes(elems, path); err != nil {
|
||||
return cty.NilVal, err
|
||||
if !cty.CanMapVal(elems) {
|
||||
return cty.NilVal, path.NewErrorf("attribute types must all match for conversion to map")
|
||||
}
|
||||
|
||||
return cty.MapVal(elems), nil
|
||||
@ -487,7 +506,7 @@ func conversionUnifyCollectionElements(elems map[string]cty.Value, path cty.Path
|
||||
}
|
||||
unifiedType, _ := unify(elemTypes, unsafe)
|
||||
if unifiedType == cty.NilType {
|
||||
return nil, path.NewErrorf("collection elements cannot be unified")
|
||||
return nil, path.NewErrorf("cannot find a common base type for all elements")
|
||||
}
|
||||
|
||||
unifiedElems := make(map[string]cty.Value)
|
||||
@ -514,26 +533,6 @@ func conversionUnifyCollectionElements(elems map[string]cty.Value, path cty.Path
|
||||
return unifiedElems, nil
|
||||
}
|
||||
|
||||
func conversionCheckMapElementTypes(elems map[string]cty.Value, path cty.Path) error {
|
||||
elementType := cty.NilType
|
||||
elemPath := append(path.Copy(), nil)
|
||||
|
||||
for name, elem := range elems {
|
||||
if elementType == cty.NilType {
|
||||
elementType = elem.Type()
|
||||
continue
|
||||
}
|
||||
if !elementType.Equals(elem.Type()) {
|
||||
elemPath[len(elemPath)-1] = cty.IndexStep{
|
||||
Key: cty.StringVal(name),
|
||||
}
|
||||
return elemPath.NewErrorf("%s is required", elementType.FriendlyName())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func conversionUnifyListElements(elems []cty.Value, path cty.Path, unsafe bool) ([]cty.Value, error) {
|
||||
elemTypes := make([]cty.Type, len(elems))
|
||||
for i, elem := range elems {
|
||||
@ -541,7 +540,7 @@ func conversionUnifyListElements(elems []cty.Value, path cty.Path, unsafe bool)
|
||||
}
|
||||
unifiedType, _ := unify(elemTypes, unsafe)
|
||||
if unifiedType == cty.NilType {
|
||||
return nil, path.NewErrorf("collection elements cannot be unified")
|
||||
return nil, path.NewErrorf("cannot find a common base type for all elements")
|
||||
}
|
||||
|
||||
ret := make([]cty.Value, len(elems))
|
||||
|
150
vendor/github.com/zclconf/go-cty/cty/convert/unify.go
generated
vendored
150
vendor/github.com/zclconf/go-cty/cty/convert/unify.go
generated
vendored
@ -29,6 +29,8 @@ func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
|
||||
// unification purposes.
|
||||
{
|
||||
mapCt := 0
|
||||
listCt := 0
|
||||
setCt := 0
|
||||
objectCt := 0
|
||||
tupleCt := 0
|
||||
dynamicCt := 0
|
||||
@ -36,6 +38,10 @@ func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
|
||||
switch {
|
||||
case ty.IsMapType():
|
||||
mapCt++
|
||||
case ty.IsListType():
|
||||
listCt++
|
||||
case ty.IsSetType():
|
||||
setCt++
|
||||
case ty.IsObjectType():
|
||||
objectCt++
|
||||
case ty.IsTupleType():
|
||||
@ -48,7 +54,31 @@ func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
|
||||
}
|
||||
switch {
|
||||
case mapCt > 0 && (mapCt+dynamicCt) == len(types):
|
||||
return unifyMapTypes(types, unsafe, dynamicCt > 0)
|
||||
return unifyCollectionTypes(cty.Map, types, unsafe, dynamicCt > 0)
|
||||
|
||||
case mapCt > 0 && (mapCt+objectCt+dynamicCt) == len(types):
|
||||
// Objects often contain map data, but are not directly typed as
|
||||
// such due to language constructs or function types. Try to unify
|
||||
// them as maps first before falling back to heterogeneous type
|
||||
// conversion.
|
||||
ty, convs := unifyObjectsAsMaps(types, unsafe)
|
||||
// If we got a map back, we know the unification was successful.
|
||||
if ty.IsMapType() {
|
||||
return ty, convs
|
||||
}
|
||||
case listCt > 0 && (listCt+dynamicCt) == len(types):
|
||||
return unifyCollectionTypes(cty.List, types, unsafe, dynamicCt > 0)
|
||||
case listCt > 0 && (listCt+tupleCt+dynamicCt) == len(types):
|
||||
// Tuples are often lists in disguise, and we may be able to
|
||||
// unify them as such.
|
||||
ty, convs := unifyTuplesAsList(types, unsafe)
|
||||
// if we got a list back, we know the unification was successful.
|
||||
// Otherwise we will fall back to the heterogeneous type codepath.
|
||||
if ty.IsListType() {
|
||||
return ty, convs
|
||||
}
|
||||
case setCt > 0 && (setCt+dynamicCt) == len(types):
|
||||
return unifyCollectionTypes(cty.Set, types, unsafe, dynamicCt > 0)
|
||||
case objectCt > 0 && (objectCt+dynamicCt) == len(types):
|
||||
return unifyObjectTypes(types, unsafe, dynamicCt > 0)
|
||||
case tupleCt > 0 && (tupleCt+dynamicCt) == len(types):
|
||||
@ -100,7 +130,121 @@ Preferences:
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
func unifyMapTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
|
||||
// unifyTuplesAsList attempts to first see if the tuples unify as lists, then
|
||||
// re-unifies the given types with the list in place of the tuples.
|
||||
func unifyTuplesAsList(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
|
||||
var tuples []cty.Type
|
||||
var tupleIdxs []int
|
||||
for i, t := range types {
|
||||
if t.IsTupleType() {
|
||||
tuples = append(tuples, t)
|
||||
tupleIdxs = append(tupleIdxs, i)
|
||||
}
|
||||
}
|
||||
|
||||
ty, tupleConvs := unifyTupleTypesToList(tuples, unsafe)
|
||||
if !ty.IsListType() {
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
// the tuples themselves unified as a list, get the overall
|
||||
// unification with this list type instead of the tuple.
|
||||
// make a copy of the types, so we can fallback to the standard
|
||||
// codepath if something went wrong
|
||||
listed := make([]cty.Type, len(types))
|
||||
copy(listed, types)
|
||||
for _, idx := range tupleIdxs {
|
||||
listed[idx] = ty
|
||||
}
|
||||
|
||||
newTy, convs := unify(listed, unsafe)
|
||||
if !newTy.IsListType() {
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
// we have a good conversion, wrap the nested tuple conversions.
|
||||
// We know the tuple conversion is not nil, because we went from tuple to
|
||||
// list
|
||||
for i, idx := range tupleIdxs {
|
||||
listConv := convs[idx]
|
||||
tupleConv := tupleConvs[i]
|
||||
|
||||
if listConv == nil {
|
||||
convs[idx] = tupleConv
|
||||
continue
|
||||
}
|
||||
|
||||
convs[idx] = func(in cty.Value) (out cty.Value, err error) {
|
||||
out, err = tupleConv(in)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
return listConv(in)
|
||||
}
|
||||
}
|
||||
|
||||
return newTy, convs
|
||||
}
|
||||
|
||||
// unifyObjectsAsMaps attempts to first see if the objects unify as maps, then
|
||||
// re-unifies the given types with the map in place of the objects.
|
||||
func unifyObjectsAsMaps(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
|
||||
var objs []cty.Type
|
||||
var objIdxs []int
|
||||
for i, t := range types {
|
||||
if t.IsObjectType() {
|
||||
objs = append(objs, t)
|
||||
objIdxs = append(objIdxs, i)
|
||||
}
|
||||
}
|
||||
|
||||
ty, objConvs := unifyObjectTypesToMap(objs, unsafe)
|
||||
if !ty.IsMapType() {
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
// the objects themselves unified as a map, get the overall
|
||||
// unification with this map type instead of the object.
|
||||
// Make a copy of the types, so we can fallback to the standard codepath if
|
||||
// something went wrong without changing the original types.
|
||||
mapped := make([]cty.Type, len(types))
|
||||
copy(mapped, types)
|
||||
for _, idx := range objIdxs {
|
||||
mapped[idx] = ty
|
||||
}
|
||||
|
||||
newTy, convs := unify(mapped, unsafe)
|
||||
if !newTy.IsMapType() {
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
// we have a good conversion, so wrap the nested object conversions.
|
||||
// We know the object conversion is not nil, because we went from object to
|
||||
// map.
|
||||
for i, idx := range objIdxs {
|
||||
mapConv := convs[idx]
|
||||
objConv := objConvs[i]
|
||||
|
||||
if mapConv == nil {
|
||||
convs[idx] = objConv
|
||||
continue
|
||||
}
|
||||
|
||||
convs[idx] = func(in cty.Value) (out cty.Value, err error) {
|
||||
out, err = objConv(in)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
return mapConv(in)
|
||||
}
|
||||
}
|
||||
|
||||
return newTy, convs
|
||||
}
|
||||
|
||||
func unifyCollectionTypes(collectionType func(cty.Type) cty.Type, types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []Conversion) {
|
||||
// If we had any dynamic types in the input here then we can't predict
|
||||
// what path we'll take through here once these become known types, so
|
||||
// we'll conservatively produce DynamicVal for these.
|
||||
@ -117,7 +261,7 @@ func unifyMapTypes(types []cty.Type, unsafe bool, hasDynamic bool) (cty.Type, []
|
||||
return cty.NilType, nil
|
||||
}
|
||||
|
||||
retTy := cty.Map(retElemType)
|
||||
retTy := collectionType(retElemType)
|
||||
|
||||
conversions := make([]Conversion, len(types))
|
||||
for i, ty := range types {
|
||||
|
8
vendor/github.com/zclconf/go-cty/cty/function/function.go
generated
vendored
8
vendor/github.com/zclconf/go-cty/cty/function/function.go
generated
vendored
@ -142,7 +142,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error)
|
||||
for i, spec := range f.spec.Params {
|
||||
val := posArgs[i]
|
||||
|
||||
if val.IsMarked() && !spec.AllowMarked {
|
||||
if val.ContainsMarked() && !spec.AllowMarked {
|
||||
// During type checking we just unmark values and discard their
|
||||
// marks, under the assumption that during actual execution of
|
||||
// the function we'll do similarly and then re-apply the marks
|
||||
@ -150,7 +150,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error)
|
||||
// inspects values (rather than just types) in its Type
|
||||
// implementation can potentially fail to take into account marks,
|
||||
// unless it specifically opts in to seeing them.
|
||||
unmarked, _ := val.Unmark()
|
||||
unmarked, _ := val.UnmarkDeep()
|
||||
newArgs := make([]cty.Value, len(args))
|
||||
copy(newArgs, args)
|
||||
newArgs[i] = unmarked
|
||||
@ -183,9 +183,9 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error)
|
||||
for i, val := range varArgs {
|
||||
realI := i + len(posArgs)
|
||||
|
||||
if val.IsMarked() && !spec.AllowMarked {
|
||||
if val.ContainsMarked() && !spec.AllowMarked {
|
||||
// See the similar block in the loop above for what's going on here.
|
||||
unmarked, _ := val.Unmark()
|
||||
unmarked, _ := val.UnmarkDeep()
|
||||
newArgs := make([]cty.Value, len(args))
|
||||
copy(newArgs, args)
|
||||
newArgs[realI] = unmarked
|
||||
|
310
vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
generated
vendored
310
vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go
generated
vendored
@ -111,6 +111,7 @@ var LengthFunc = function.New(&function.Spec{
|
||||
Name: "collection",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowDynamicType: true,
|
||||
AllowMarked: true,
|
||||
},
|
||||
},
|
||||
Type: func(args []cty.Value) (ret cty.Type, err error) {
|
||||
@ -128,8 +129,9 @@ var LengthFunc = function.New(&function.Spec{
|
||||
var ElementFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "list",
|
||||
Type: cty.DynamicPseudoType,
|
||||
Name: "list",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowMarked: true,
|
||||
},
|
||||
{
|
||||
Name: "index",
|
||||
@ -184,11 +186,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,7 +199,7 @@ 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
|
||||
},
|
||||
})
|
||||
|
||||
@ -398,12 +401,14 @@ var DistinctFunc = function.New(&function.Spec{
|
||||
var ChunklistFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "list",
|
||||
Type: cty.List(cty.DynamicPseudoType),
|
||||
Name: "list",
|
||||
Type: cty.List(cty.DynamicPseudoType),
|
||||
AllowMarked: true,
|
||||
},
|
||||
{
|
||||
Name: "size",
|
||||
Type: cty.Number,
|
||||
Name: "size",
|
||||
Type: cty.Number,
|
||||
AllowMarked: true,
|
||||
},
|
||||
},
|
||||
Type: func(args []cty.Value) (cty.Type, error) {
|
||||
@ -411,35 +416,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,7 +464,7 @@ var ChunklistFunc = function.New(&function.Spec{
|
||||
i++
|
||||
}
|
||||
|
||||
return cty.ListVal(output), nil
|
||||
return cty.ListVal(output).WithMarks(retMarks), nil
|
||||
},
|
||||
})
|
||||
|
||||
@ -463,8 +473,9 @@ var ChunklistFunc = function.New(&function.Spec{
|
||||
var FlattenFunc = function.New(&function.Spec{
|
||||
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 +488,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,46 +502,66 @@ 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()
|
||||
|
||||
// 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.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.
|
||||
@ -539,6 +571,7 @@ var KeysFunc = function.New(&function.Spec{
|
||||
Name: "inputMap",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowUnknown: true,
|
||||
AllowMarked: true,
|
||||
},
|
||||
},
|
||||
Type: func(args []cty.Value) (cty.Type, error) {
|
||||
@ -563,7 +596,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,28 +613,28 @@ 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
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -606,16 +643,19 @@ var KeysFunc = function.New(&function.Spec{
|
||||
var LookupFunc = function.New(&function.Spec{
|
||||
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 +667,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 +690,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
|
||||
},
|
||||
})
|
||||
|
||||
@ -687,6 +739,7 @@ var MergeFunc = function.New(&function.Spec{
|
||||
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 +765,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 +816,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 +835,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))
|
||||
}
|
||||
@ -791,8 +851,9 @@ var MergeFunc = function.New(&function.Spec{
|
||||
var ReverseListFunc = function.New(&function.Spec{
|
||||
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 +873,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
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -836,8 +899,9 @@ var ReverseListFunc = function.New(&function.Spec{
|
||||
var SetProductFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{},
|
||||
VarParam: &function.Parameter{
|
||||
Name: "sets",
|
||||
Type: cty.DynamicPseudoType,
|
||||
Name: "sets",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowMarked: true,
|
||||
},
|
||||
Type: func(args []cty.Value) (retType cty.Type, err error) {
|
||||
if len(args) < 2 {
|
||||
@ -881,11 +945,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 +966,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 +987,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,9 +1028,9 @@ 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
|
||||
},
|
||||
})
|
||||
|
||||
@ -961,8 +1039,9 @@ var SetProductFunc = function.New(&function.Spec{
|
||||
var SliceFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "list",
|
||||
Type: cty.DynamicPseudoType,
|
||||
Name: "list",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowMarked: true,
|
||||
},
|
||||
{
|
||||
Name: "start_index",
|
||||
@ -1001,10 +1080,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 +1095,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 +1114,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
|
||||
}
|
||||
|
||||
@ -1078,8 +1160,9 @@ func sliceIndexes(args []cty.Value) (int, int, bool, error) {
|
||||
var ValuesFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "values",
|
||||
Type: cty.DynamicPseudoType,
|
||||
Name: "values",
|
||||
Type: cty.DynamicPseudoType,
|
||||
AllowMarked: true,
|
||||
},
|
||||
},
|
||||
Type: func(args []cty.Value) (ret cty.Type, err error) {
|
||||
@ -1112,6 +1195,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,13 +1210,15 @@ 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
|
||||
},
|
||||
})
|
||||
|
||||
@ -1135,12 +1227,14 @@ var ValuesFunc = function.New(&function.Spec{
|
||||
var ZipmapFunc = function.New(&function.Spec{
|
||||
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 +1252,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 +1266,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 +1282,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 +1306,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.
|
||||
|
13
vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
generated
vendored
13
vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go
generated
vendored
@ -30,7 +30,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 +64,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 +91,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
|
||||
}
|
||||
}
|
||||
|
4
vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
generated
vendored
4
vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go
generated
vendored
@ -6,7 +6,7 @@ import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/apparentlymart/go-textseg/v12/textseg"
|
||||
"github.com/apparentlymart/go-textseg/v13/textseg"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
@ -114,6 +114,8 @@ var FormatListFunc = function.New(&function.Spec{
|
||||
continue
|
||||
}
|
||||
iterators[i] = arg.ElementIterator()
|
||||
case arg == cty.DynamicVal:
|
||||
unknowns[i] = true
|
||||
default:
|
||||
singleVals[i] = arg
|
||||
}
|
||||
|
38
vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
generated
vendored
38
vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go
generated
vendored
@ -371,14 +371,21 @@ 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
|
||||
},
|
||||
})
|
||||
|
||||
@ -393,14 +400,21 @@ 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
|
||||
},
|
||||
})
|
||||
|
||||
|
27
vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
generated
vendored
27
vendor/github.com/zclconf/go-cty/cty/function/stdlib/sequence.go
generated
vendored
@ -11,8 +11,9 @@ import (
|
||||
var ConcatFunc = function.New(&function.Spec{
|
||||
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 +43,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 +80,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 +89,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 +101,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 +112,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 +128,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")
|
||||
|
3
vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
generated
vendored
3
vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
generated
vendored
@ -6,7 +6,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/apparentlymart/go-textseg/v12/textseg"
|
||||
"github.com/apparentlymart/go-textseg/v13/textseg"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/function"
|
||||
@ -151,7 +151,6 @@ var SubstrFunc = function.New(&function.Spec{
|
||||
return cty.StringVal(""), nil
|
||||
}
|
||||
|
||||
|
||||
sub := in
|
||||
pos := 0
|
||||
var i int
|
||||
|
21
vendor/github.com/zclconf/go-cty/cty/marks.go
generated
vendored
21
vendor/github.com/zclconf/go-cty/cty/marks.go
generated
vendored
@ -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)
|
||||
|
2
vendor/github.com/zclconf/go-cty/cty/object_type.go
generated
vendored
2
vendor/github.com/zclconf/go-cty/cty/object_type.go
generated
vendored
@ -112,7 +112,7 @@ func (t typeObject) GoString() string {
|
||||
return "cty.EmptyObject"
|
||||
}
|
||||
if len(t.AttrOptional) > 0 {
|
||||
opt := make([]string, len(t.AttrOptional))
|
||||
var opt []string
|
||||
for k := range t.AttrOptional {
|
||||
opt = append(opt, k)
|
||||
}
|
||||
|
45
vendor/github.com/zclconf/go-cty/cty/primitive_type.go
generated
vendored
45
vendor/github.com/zclconf/go-cty/cty/primitive_type.go
generated
vendored
@ -52,6 +52,51 @@ 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
|
||||
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.
|
||||
|
38
vendor/github.com/zclconf/go-cty/cty/type.go
generated
vendored
38
vendor/github.com/zclconf/go-cty/cty/type.go
generated
vendored
@ -115,6 +115,44 @@ func (t Type) HasDynamicTypes() bool {
|
||||
}
|
||||
}
|
||||
|
||||
// WithoutOptionalAttributesDeep returns a type equivalent to the receiver but
|
||||
// with any objects with optional attributes converted into fully concrete
|
||||
// object types. This operation is applied recursively.
|
||||
func (t Type) WithoutOptionalAttributesDeep() Type {
|
||||
switch {
|
||||
case t == DynamicPseudoType, t.IsPrimitiveType(), t.IsCapsuleType():
|
||||
return t
|
||||
case t.IsMapType():
|
||||
return Map(t.ElementType().WithoutOptionalAttributesDeep())
|
||||
case t.IsListType():
|
||||
return List(t.ElementType().WithoutOptionalAttributesDeep())
|
||||
case t.IsSetType():
|
||||
return Set(t.ElementType().WithoutOptionalAttributesDeep())
|
||||
case t.IsTupleType():
|
||||
originalElemTypes := t.TupleElementTypes()
|
||||
elemTypes := make([]Type, len(originalElemTypes))
|
||||
for i, et := range originalElemTypes {
|
||||
elemTypes[i] = et.WithoutOptionalAttributesDeep()
|
||||
}
|
||||
return Tuple(elemTypes)
|
||||
case t.IsObjectType():
|
||||
originalAttrTypes := t.AttributeTypes()
|
||||
attrTypes := make(map[string]Type, len(originalAttrTypes))
|
||||
for k, t := range originalAttrTypes {
|
||||
attrTypes[k] = t.WithoutOptionalAttributesDeep()
|
||||
}
|
||||
|
||||
// This is the subtle line which does all the work of this function: by
|
||||
// constructing a new Object type with these attribute types, we drop
|
||||
// the list of optional attributes (if present). This results in a
|
||||
// concrete Object type which requires all of the original attributes.
|
||||
return Object(attrTypes)
|
||||
default:
|
||||
// Should never happen, since above should be exhaustive
|
||||
panic("WithoutOptionalAttributesDeep does not support the given type")
|
||||
}
|
||||
}
|
||||
|
||||
type friendlyTypeNameMode rune
|
||||
|
||||
const (
|
||||
|
48
vendor/github.com/zclconf/go-cty/cty/value_init.go
generated
vendored
48
vendor/github.com/zclconf/go-cty/cty/value_init.go
generated
vendored
@ -186,6 +186,20 @@ func ListValEmpty(element Type) Value {
|
||||
}
|
||||
}
|
||||
|
||||
// CanListVal returns false if the given Values can not be coalesced
|
||||
// into a single List due to inconsistent element types.
|
||||
func CanListVal(vals []Value) bool {
|
||||
elementType := DynamicPseudoType
|
||||
for _, val := range vals {
|
||||
if elementType == DynamicPseudoType {
|
||||
elementType = val.ty
|
||||
} else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MapVal returns a Value of a map type whose element type is defined by
|
||||
// the types of the given values, which must be homogenous.
|
||||
//
|
||||
@ -227,6 +241,20 @@ func MapValEmpty(element Type) Value {
|
||||
}
|
||||
}
|
||||
|
||||
// CanMapVal returns false if the given Values can not be coalesced into a
|
||||
// single Map due to inconsistent element types.
|
||||
func CanMapVal(vals map[string]Value) bool {
|
||||
elementType := DynamicPseudoType
|
||||
for _, val := range vals {
|
||||
if elementType == DynamicPseudoType {
|
||||
elementType = val.ty
|
||||
} else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SetVal returns a Value of set type whose element type is defined by
|
||||
// the types of the given values, which must be homogenous.
|
||||
//
|
||||
@ -267,6 +295,26 @@ func SetVal(vals []Value) Value {
|
||||
}.WithMarks(markSets...)
|
||||
}
|
||||
|
||||
// CanSetVal returns false if the given Values can not be coalesced
|
||||
// into a single Set due to inconsistent element types.
|
||||
func CanSetVal(vals []Value) bool {
|
||||
elementType := DynamicPseudoType
|
||||
var markSets []ValueMarks
|
||||
|
||||
for _, val := range vals {
|
||||
if unmarkedVal, marks := val.UnmarkDeep(); len(marks) > 0 {
|
||||
val = unmarkedVal
|
||||
markSets = append(markSets, marks)
|
||||
}
|
||||
if elementType == DynamicPseudoType {
|
||||
elementType = val.ty
|
||||
} else if val.ty != DynamicPseudoType && !elementType.Equals(val.ty) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SetValFromValueSet returns a Value of set type based on an already-constructed
|
||||
// ValueSet.
|
||||
//
|
||||
|
27
vendor/github.com/zclconf/go-cty/cty/value_ops.go
generated
vendored
27
vendor/github.com/zclconf/go-cty/cty/value_ops.go
generated
vendored
@ -116,9 +116,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 +191,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:
|
||||
@ -492,18 +492,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 {
|
||||
@ -1278,9 +1283,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
|
||||
|
35
vendor/github.com/zclconf/go-cty/cty/walk.go
generated
vendored
35
vendor/github.com/zclconf/go-cty/cty/walk.go
generated
vendored
@ -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:
|
||||
|
Reference in New Issue
Block a user