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 {
			return nil
		}
		if inAty.Equals(outAty) {
			attrConvs[name] = nil
			continue
		}
		attrConvs[name] = getConversion(inAty, outAty, unsafe)
		if attrConvs[name] == nil {
			return nil
		}
	}
	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
	}
}
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".
package convert
import (
	"github.com/zclconf/go-cty/cty"
)