in pkg/cloud/api/copy.go [189:250]
func (c *copier) doMap(p Path, dest, src reflect.Value) error {
if dest.Type().Kind() != reflect.Map || src.Type().Kind() != reflect.Map {
return fmt.Errorf("copyMap: invalid type (dest: %T, src: %T)", dest.Interface(), src.Interface())
}
if src.IsZero() {
if !dest.CanSet() {
return fmt.Errorf("cannot set dest (%s)", p)
}
dest.Set(reflect.Zero(dest.Type()))
c.logS("copyMap zero", "path", p)
return nil
}
dkt := dest.Type().Key()
dvt := dest.Type().Elem()
skt := src.Type().Key()
svt := src.Type().Elem()
if !basicT(dkt) || !basicT(skt) {
return fmt.Errorf("copyMap: keys are not basic types (dest: %T, src: %T)", dest.Interface(), src.Interface())
}
if dkt.Kind() != skt.Kind() {
return fmt.Errorf("copyMap: keys do not match (dest: %T, src: %T)", dest.Interface(), src.Interface())
}
if dvt.Kind() != svt.Kind() {
return fmt.Errorf("copyMap: values type must match (dest: %T, src: %T)", dest.Interface(), src.Interface())
}
newMap := reflect.MakeMapWithSize(dest.Type(), src.Len())
for _, sk := range src.MapKeys() {
sv := src.MapIndex(sk)
switch {
case basicT(dvt) && basicT(svt):
c.logS("copyMap basic", "path", p.MapIndex(sk.Interface()), "value", sv.Interface())
newMap.SetMapIndex(sk, sv)
case svt.Kind() == reflect.Struct:
pdv := reflect.New(dvt)
if err := c.doValues(p.MapIndex(sk.Interface()), pdv.Elem(), sv); err != nil {
return err
}
newMap.SetMapIndex(sk, pdv.Elem())
case svt.Kind() == reflect.Slice:
dv := reflect.New(dvt).Elem()
dv.Grow(sv.Len())
if err := c.doValues(p.MapIndex(sk.Interface()), dv, sv); err != nil {
return err
}
newMap.SetMapIndex(sk, dv)
default:
return fmt.Errorf("unsupported map types (dest: %T, src: %T)", dest.Interface(), src.Interface())
}
}
if !dest.CanSet() {
return fmt.Errorf("cannot set dest (%s)", p)
}
dest.Set(newMap)
return nil
}