func()

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
}