func visitImpl()

in pkg/cloud/api/visit.go [86:153]


func visitImpl(p Path, v reflect.Value, a acceptor) error {
	switch {
	case isBasicV(v):
		if _, err := a.onBasic(p, v); err != nil {
			return err
		}
	case v.Type().Kind() == reflect.Pointer:
		descend, err := a.onPointer(p, v)
		if err != nil {
			return err
		}
		if !v.IsZero() && descend {
			err := visitImpl(p.Pointer(), v.Elem(), a)
			if err != nil {
				return err
			}
		}
	case v.Type().Kind() == reflect.Struct:
		descend, err := a.onStruct(p, v)
		if err != nil {
			return err
		}
		if descend {
			for i := 0; i < v.NumField(); i++ {
				fv := v.Field(i)
				ft := v.Type().Field(i)
				if err := visitImpl(p.Field(ft.Name), fv, a); err != nil {
					return err
				}
			}
		}
	case v.Type().Kind() == reflect.Slice:
		descend, err := a.onSlice(p, v)
		if err != nil {
			return err
		}
		if descend {
			for i := 0; i < v.Len(); i++ {
				sv := v.Index(i)
				if err := visitImpl(p.Index(i), sv, a); err != nil {
					return err
				}
			}
		}
	case v.Type().Kind() == reflect.Map:
		descend, err := a.onMap(p, v)
		if err != nil {
			return err
		}
		if descend {
			for _, mk := range v.MapKeys() {
				mv := v.MapIndex(mk)
				// Create a temporary setable map
				// value for cases where visitImpl
				// wants to mutate the value in the
				// map. This slightly inefficient for
				// read-only operations.
				setableMV := reflect.New(mv.Type()).Elem()
				setableMV.Set(mv)
				if err := visitImpl(p.MapIndex(mk), setableMV, a); err != nil {
					return err
				}
				v.SetMapIndex(mk, setableMV)
			}
		}
	}
	return nil
}