descend walks the given key path into v, and assigns the value at the end. It returns the value to store back at this level. An invalid value means nothing should be stored (e.g. unknown field).
(v reflect.Value, path []pathPart, idx int, expr *unstable.Node, value *unstable.Node)
| 1382 | // end. It returns the value to store back at this level. An invalid value |
| 1383 | // means nothing should be stored (e.g. unknown field). |
| 1384 | func (d *decoder) descend(v reflect.Value, path []pathPart, idx int, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) { |
| 1385 | if idx == len(path) { |
| 1386 | return d.assignValue(v, expr, value) |
| 1387 | } |
| 1388 | |
| 1389 | if v.Kind() == reflect.Ptr { |
| 1390 | if v.IsNil() { |
| 1391 | v.Set(reflect.New(v.Type().Elem())) |
| 1392 | } |
| 1393 | nv, err := d.descend(v.Elem(), path, idx, expr, value) |
| 1394 | if err != nil || !nv.IsValid() { |
| 1395 | return reflect.Value{}, err |
| 1396 | } |
| 1397 | v.Elem().Set(nv) |
| 1398 | return v, nil |
| 1399 | } |
| 1400 | |
| 1401 | // A target implementing the unmarshaler interface consumes the value, |
| 1402 | // whatever the remaining parts of the key are. |
| 1403 | if d.unmarshalerInterface { |
| 1404 | if u, ok := unmarshalerOf(v); ok { |
| 1405 | return v, u.UnmarshalTOML(d.rawValue(expr, value)) |
| 1406 | } |
| 1407 | } |
| 1408 | |
| 1409 | part := path[idx] |
| 1410 | |
| 1411 | switch v.Kind() { |
| 1412 | case reflect.Map: |
| 1413 | // Native fast path for the most common generic target: walk the |
| 1414 | // remaining dotted-key path with plain Go map operations and decode |
| 1415 | // the value directly, skipping the reflect.Value round-trips |
| 1416 | // (stringMapKey, MapIndex, New, SetMapIndex) entirely. |
| 1417 | if !d.unmarshalerInterface && v.Type() == mapStringInterfaceType { |
| 1418 | return d.descendStrMap(v, path, idx, value) |
| 1419 | } |
| 1420 | var name string |
| 1421 | var key reflect.Value |
| 1422 | var err error |
| 1423 | fastKey := v.Type().Key() == stringType |
| 1424 | if fastKey { |
| 1425 | name = d.partString(&part) |
| 1426 | key = d.stringMapKey(name) |
| 1427 | } else { |
| 1428 | key, err = makeMapKey(v.Type().Key(), d.partString(&part)) |
| 1429 | if err != nil { |
| 1430 | return reflect.Value{}, err |
| 1431 | } |
| 1432 | } |
| 1433 | if v.IsNil() { |
| 1434 | v = reflect.MakeMap(v.Type()) |
| 1435 | } |
| 1436 | elemType := v.Type().Elem() |
| 1437 | existing := v.MapIndex(key) |
| 1438 | var elem reflect.Value |
| 1439 | switch { |
| 1440 | case existing.IsValid(): |
| 1441 | elem = reflect.New(elemType).Elem() |
no test coverage detected