package convert import ( "github.com/zclconf/go-cty/cty" ) // conversionObjectToObject returns a conversion that will make the input // object type conform to the output object type, if possible. // // Conversion is possible only if the output type is a subset of the input // type, meaning that each attribute of the output type has a corresponding // attribute in the input type where a recursive conversion is available. // // Shallow object conversions work the same for both safe and unsafe modes, // but the safety flag is passed on to recursive conversions and may thus // limit the above definition of "subset". func conversionObjectToObject(in, out cty.Type, unsafe bool) conversion { inAtys := in.AttributeTypes() outAtys := out.AttributeTypes() attrConvs := make(map[string]conversion) for name, outAty := range outAtys { inAty, exists := inAtys[name] if !exists { // No conversion is available, then. return nil } if inAty.Equals(outAty) { // No conversion needed, but we'll still record the attribute // in our map for later reference. attrConvs[name] = nil continue } attrConvs[name] = getConversion(inAty, outAty, unsafe) if attrConvs[name] == 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 attribute // conversions given in attrConvs. return func(val cty.Value, path cty.Path) (cty.Value, error) { attrVals := make(map[string]cty.Value, len(attrConvs)) path = append(path, nil) pathStep := &path[len(path)-1] for it := val.ElementIterator(); it.Next(); { nameVal, val := it.Element() var err error name := nameVal.AsString() *pathStep = cty.GetAttrStep{ Name: name, } conv, exists := attrConvs[name] if !exists { continue } if conv != nil { val, err = conv(val, path) if err != nil { return cty.NilVal, err } } attrVals[name] = val } return cty.ObjectVal(attrVals), nil } }