blob: 100078fdc43063e7e80ad687c1651c976ba3e3aa [file] [log] [blame]
package stdlib
import (
"fmt"
"github.com/zclconf/go-cty/cty/convert"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
)
var SetHasElementFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "set",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
{
Name: "elem",
Type: cty.DynamicPseudoType,
AllowDynamicType: true,
},
},
Type: function.StaticReturnType(cty.Bool),
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
return args[0].HasElement(args[1]), nil
},
})
var SetUnionFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "first_set",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
},
VarParam: &function.Parameter{
Name: "other_sets",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Union(s2)
}),
})
var SetIntersectionFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "first_set",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
},
VarParam: &function.Parameter{
Name: "other_sets",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Intersection(s2)
}),
})
var SetSubtractFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "a",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
{
Name: "b",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
},
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Subtract(s2)
}),
})
var SetSymmetricDifferenceFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "first_set",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
},
VarParam: &function.Parameter{
Name: "other_sets",
Type: cty.Set(cty.DynamicPseudoType),
AllowDynamicType: true,
},
Type: setOperationReturnType,
Impl: setOperationImpl(func(s1, s2 cty.ValueSet) cty.ValueSet {
return s1.Subtract(s2)
}),
})
// SetHasElement determines whether the given set contains the given value as an
// element.
func SetHasElement(set cty.Value, elem cty.Value) (cty.Value, error) {
return SetHasElementFunc.Call([]cty.Value{set, elem})
}
// SetUnion returns a new set containing all of the elements from the given
// sets, which must have element types that can all be converted to some
// common type using the standard type unification rules. If conversion
// is not possible, an error is returned.
//
// The union operation is performed after type conversion, which may result
// in some previously-distinct values being conflated.
//
// At least one set must be provided.
func SetUnion(sets ...cty.Value) (cty.Value, error) {
return SetUnionFunc.Call(sets)
}
// Intersection returns a new set containing the elements that exist
// in all of the given sets, which must have element types that can all be
// converted to some common type using the standard type unification rules.
// If conversion is not possible, an error is returned.
//
// The intersection operation is performed after type conversion, which may
// result in some previously-distinct values being conflated.
//
// At least one set must be provided.
func SetIntersection(sets ...cty.Value) (cty.Value, error) {
return SetIntersectionFunc.Call(sets)
}
// SetSubtract returns a new set containing the elements from the
// first set that are not present in the second set. The sets must have
// element types that can both be converted to some common type using the
// standard type unification rules. If conversion is not possible, an error
// is returned.
//
// The subtract operation is performed after type conversion, which may
// result in some previously-distinct values being conflated.
func SetSubtract(a, b cty.Value) (cty.Value, error) {
return SetSubtractFunc.Call([]cty.Value{a, b})
}
// SetSymmetricDifference returns a new set containing elements that appear
// in any of the given sets but not multiple. The sets must have
// element types that can all be converted to some common type using the
// standard type unification rules. If conversion is not possible, an error
// is returned.
//
// The difference operation is performed after type conversion, which may
// result in some previously-distinct values being conflated.
func SetSymmetricDifference(sets ...cty.Value) (cty.Value, error) {
return SetSymmetricDifferenceFunc.Call(sets)
}
func setOperationReturnType(args []cty.Value) (ret cty.Type, err error) {
var etys []cty.Type
for _, arg := range args {
etys = append(etys, arg.Type().ElementType())
}
newEty, _ := convert.UnifyUnsafe(etys)
if newEty == cty.NilType {
return cty.NilType, fmt.Errorf("given sets must all have compatible element types")
}
return cty.Set(newEty), nil
}
func setOperationImpl(f func(s1, s2 cty.ValueSet) cty.ValueSet) function.ImplFunc {
return func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
first := args[0]
first, err = convert.Convert(first, retType)
if err != nil {
return cty.NilVal, function.NewArgError(0, err)
}
set := first.AsValueSet()
for i, arg := range args[1:] {
arg, err := convert.Convert(arg, retType)
if err != nil {
return cty.NilVal, function.NewArgError(i+1, err)
}
argSet := arg.AsValueSet()
set = f(set, argSet)
}
return cty.SetValFromValueSet(set), nil
}
}