| 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 |
| } |
| } |