in codegen/type_converter.go [440:641]
func (c *TypeConverter) genConverterForMap(
toField toFieldParam,
fromField fromFieldParam,
overriddenField overriddenFieldParam,
indent string,
) error {
toFieldType := toField.Type.(*compile.MapSpec)
typeName, err := c.getGoTypeName(toFieldType.ValueSpec)
if err != nil {
return err
}
valueStruct, isStruct := compile.RootTypeSpec(toFieldType.ValueSpec).(*compile.StructSpec)
valueList, isList := compile.RootTypeSpec(toFieldType.ValueSpec).(*compile.ListSpec)
valueMap, isMap := compile.RootTypeSpec(toFieldType.ValueSpec).(*compile.MapSpec)
sourceIdentifier := fromField.ValueIdentifier
_, isStringKey := toFieldType.KeySpec.(*compile.StringSpec)
keyType := "string"
if !isStringKey {
realType := compile.RootTypeSpec(toFieldType.KeySpec)
switch realType.(type) {
case *compile.StringSpec:
keyType, _ = c.getGoTypeName(toFieldType.KeySpec)
default:
return errors.Errorf(
"could not convert key (%s), map is not string-keyed.", toField.Name)
}
}
checkOverride := false
sourceListID := ""
isOverriddenID := ""
if overriddenField.Identifier != "" {
sourceListID = c.makeUniqIdentifier("sourceList")
isOverriddenID = c.makeUniqIdentifier("isOverridden")
// Determine which map (from or overrride) to use
c.appendf("%s := %s", sourceListID, overriddenField.Identifier)
if isStruct {
c.appendf("%s := false", isOverriddenID)
}
// TODO(sindelar): Verify how optional thrift map are defined.
c.appendf("if %s != nil {", fromField.Identifier)
c.appendf("\t%s = %s", sourceListID, fromField.Identifier)
if isStruct {
c.appendf("\t%s = true", isOverriddenID)
}
c.append("}")
sourceIdentifier = sourceListID
checkOverride = true
}
if isStruct {
c.appendf(
"%s = make(map[%s]*%s, len(%s))",
toField.Identifier, keyType, typeName, sourceIdentifier,
)
} else {
c.appendf(
"%s = make(map[%s]%s, len(%s))",
toField.Identifier, keyType, typeName, sourceIdentifier,
)
}
keyID := c.makeUniqIdentifier("key")
valID := c.makeUniqIdentifier("value")
c.appendf(
"for %s, %s := range %s {",
keyID, valID, sourceIdentifier,
)
if isStruct || isList || isMap {
nestedIndent := "\t" + indent
fromFieldMapType, ok := compile.RootTypeSpec(fromField.Type).(*compile.MapSpec)
if !ok {
return errors.Errorf(
"Could not convert field (%s): type is not map",
fromField.Name,
)
}
toFieldKeyID := keyID
toTypeKeyName := keyType
fromTypeKeyName, _ := c.getGoTypeName(fromFieldMapType.KeySpec)
if fromTypeKeyName != toTypeKeyName {
toFieldKeyID = toTypeKeyName + "(" + keyID + ")"
}
if isStruct {
if checkOverride {
nestedIndent = "\t" + nestedIndent
c.appendf("\tif %s {", isOverriddenID)
}
err = c.genConverterForStruct(
toField.Name,
valueStruct,
toField.Required,
fromFieldMapType.ValueSpec,
valID,
trimAnyPrefix(toField.Identifier, "out.", "outOriginal.")+"["+toFieldKeyID+"]",
trimAnyPrefix(fromField.Identifier, "in.", "inOriginal.")+"["+keyID+"]",
nestedIndent,
nil,
nil,
)
if err != nil {
return err
}
if checkOverride {
c.append("\t", "} else {")
overriddenFieldMapType, ok := overriddenField.Type.(*compile.MapSpec)
if !ok {
return errors.Errorf(
"Could not convert field (%s): type is not map",
overriddenField.Name,
)
}
err = c.genConverterForStruct(
toField.Name,
valueStruct,
toField.Required,
overriddenFieldMapType.ValueSpec,
valID,
trimAnyPrefix(toField.Identifier, "out.", "outOriginal.")+"["+toFieldKeyID+"]",
trimAnyPrefix(overriddenField.Identifier, "in.", "inOriginal.")+"["+keyID+"]",
nestedIndent,
nil,
nil,
)
if err != nil {
return err
}
c.append("\t", "}")
}
} else if isList {
err = c.genConverterForList(
toFieldParam{
valueList,
toField.Name,
toField.Required,
toField.Identifier + "[" + toFieldKeyID + "]",
},
fromFieldParam{
fromFieldMapType.ValueSpec,
fromField.Name,
fromField.Identifier + "[" + keyID + "]",
valID,
},
overriddenField,
nestedIndent)
if err != nil {
return err
}
} else if isMap {
err = c.genConverterForMap(
toFieldParam{
valueMap,
toField.Name,
toField.Required,
toField.Identifier + "[" + toFieldKeyID + "]",
},
fromFieldParam{
fromFieldMapType.ValueSpec,
fromField.Name,
fromField.Identifier + "[" + keyID + "]",
valID,
},
overriddenField,
nestedIndent)
if err != nil {
return err
}
}
} else {
if keyType == "string" {
c.appendf(
"\t%s[%s] = %s(%s)",
toField.Identifier, keyID, typeName, valID,
)
} else {
c.appendf(
"\t %s[%s(%s)] = %s(%s)",
toField.Identifier, keyType, keyID, typeName, valID,
)
}
}
c.append("}")
return nil
}