blob: 592980a7012d0033e9fbe75cd1e9812ee3409637 [file] [log] [blame]
package convert
import (
"github.com/zclconf/go-cty/cty"
)
// conversionTupleToTuple returns a conversion that will make the input
// tuple type conform to the output tuple type, if possible.
//
// Conversion is possible only if the two tuple types have the same number
// of elements and the corresponding elements by index can be converted.
//
// Shallow tuple conversions work the same for both safe and unsafe modes,
// but the safety flag is passed on to recursive conversions and may thus
// limit which element type conversions are possible.
func conversionTupleToTuple(in, out cty.Type, unsafe bool) conversion {
inEtys := in.TupleElementTypes()
outEtys := out.TupleElementTypes()
if len(inEtys) != len(outEtys) {
return nil // no conversion is possible
}
elemConvs := make([]conversion, len(inEtys))
for i, outEty := range outEtys {
inEty := inEtys[i]
if inEty.Equals(outEty) {
// No conversion needed, so we can leave this one nil.
continue
}
elemConvs[i] = getConversion(inEty, outEty, unsafe)
if elemConvs[i] == nil {
// If a recursive conversion isn't available, then our top-level
// configuration is impossible too.
return nil
}
}
// If we get here then a conversion is possible, using the element
// conversions given in elemConvs.
return func(val cty.Value, path cty.Path) (cty.Value, error) {
elemVals := make([]cty.Value, len(elemConvs))
path = append(path, nil)
pathStep := &path[len(path)-1]
i := 0
for it := val.ElementIterator(); it.Next(); i++ {
_, val := it.Element()
var err error
*pathStep = cty.IndexStep{
Key: cty.NumberIntVal(int64(i)),
}
conv := elemConvs[i]
if conv != nil {
val, err = conv(val, path)
if err != nil {
return cty.NilVal, err
}
}
elemVals[i] = val
}
return cty.TupleVal(elemVals), nil
}
}