(name string, dataVal, val reflect.Value)
| 1263 | } |
| 1264 | |
| 1265 | func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { |
| 1266 | dataValType := dataVal.Type() |
| 1267 | if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { |
| 1268 | return fmt.Errorf( |
| 1269 | "'%s' needs a map with string keys, has '%s' keys", |
| 1270 | name, dataValType.Key().Kind()) |
| 1271 | } |
| 1272 | |
| 1273 | dataValKeys := make(map[reflect.Value]struct{}) |
| 1274 | dataValKeysUnused := make(map[interface{}]struct{}) |
| 1275 | for _, dataValKey := range dataVal.MapKeys() { |
| 1276 | dataValKeys[dataValKey] = struct{}{} |
| 1277 | dataValKeysUnused[dataValKey.Interface()] = struct{}{} |
| 1278 | } |
| 1279 | |
| 1280 | targetValKeysUnused := make(map[interface{}]struct{}) |
| 1281 | errors := make([]string, 0) |
| 1282 | |
| 1283 | // This slice will keep track of all the structs we'll be decoding. |
| 1284 | // There can be more than one struct if there are embedded structs |
| 1285 | // that are squashed. |
| 1286 | structs := make([]reflect.Value, 1, 5) |
| 1287 | structs[0] = val |
| 1288 | |
| 1289 | // Compile the list of all the fields that we're going to be decoding |
| 1290 | // from all the structs. |
| 1291 | type field struct { |
| 1292 | field reflect.StructField |
| 1293 | val reflect.Value |
| 1294 | } |
| 1295 | |
| 1296 | // remainField is set to a valid field set with the "remain" tag if |
| 1297 | // we are keeping track of remaining values. |
| 1298 | var remainField *field |
| 1299 | |
| 1300 | fields := []field{} |
| 1301 | for len(structs) > 0 { |
| 1302 | structVal := structs[0] |
| 1303 | structs = structs[1:] |
| 1304 | |
| 1305 | structType := structVal.Type() |
| 1306 | |
| 1307 | for i := 0; i < structType.NumField(); i++ { |
| 1308 | fieldType := structType.Field(i) |
| 1309 | fieldVal := structVal.Field(i) |
| 1310 | if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { |
| 1311 | // Handle embedded struct pointers as embedded structs. |
| 1312 | fieldVal = fieldVal.Elem() |
| 1313 | } |
| 1314 | |
| 1315 | // If "squash" is specified in the tag, we squash the field down. |
| 1316 | squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous |
| 1317 | remain := false |
| 1318 | |
| 1319 | // We always parse the tags cause we're looking for other tags too |
| 1320 | tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") |
| 1321 | for _, tag := range tagParts[1:] { |
| 1322 | if tag == "squash" { |
no test coverage detected