func()

in packages/@jsii/go-runtime/jsii-runtime-go/internal/kernel/conversions.go [28:131]


func (c *Client) castAndSetToPtr(ptr reflect.Value, data reflect.Value) {
	if !data.IsValid() {
		// data will not be valid if was made from a nil value, as there would
		// not have been enough type information available to build a valid
		// reflect.Value. In such cases, we must craft the correctly-typed zero
		// value ourselves.
		data = reflect.Zero(ptr.Type())
	} else if ptr.Kind() == reflect.Ptr && ptr.IsNil() {
		// if ptr is a Pointer type and data is valid, initialize a non-nil pointer
		// type. Otherwise inner value is not-settable upon recursion. See third
		// law of reflection.
		// https://blog.golang.org/laws-of-reflection
		ptr.Set(reflect.New(ptr.Type().Elem()))
		c.castAndSetToPtr(ptr.Elem(), data)
		return
	} else if data.Kind() == reflect.Interface && !data.IsNil() {
		// If data is a non-nil interface, unwrap it to get it's dynamic value
		// type sorted out, so that further calls in this method don't have to
		// worry about this edge-case when reasoning on kinds.
		data = reflect.ValueOf(data.Interface())
	}

	if ref, isRef := castValToRef(data); isRef {
		// If return data is a jsii struct passed by reference, de-reference it all.
		if fields, _, isStruct := c.Types().StructFields(ptr.Type()); isStruct {
			for _, field := range fields {
				got, err := c.Get(GetProps{
					Property: field.Tag.Get("json"),
					ObjRef:   ref,
				})
				if err != nil {
					panic(err)
				}
				fieldVal := ptr.FieldByIndex(field.Index)
				c.castAndSetToPtr(fieldVal, reflect.ValueOf(got.Value))
			}
			return
		}

		targetType := ptr.Type()
		if typ, ok := c.Types().FindType(ref.TypeFQN()); ok && typ.AssignableTo(ptr.Type()) {
			// Specialize the return type to be the dynamic value type
			targetType = typ
		}

		// If it's currently tracked, return the current instance
		if object, ok := c.objects.GetObjectAs(ref.InstanceID, targetType); ok {
			ptr.Set(object)
			return
		}

		// If return data is jsii object references, add to objects table.
		if err := c.Types().InitJsiiProxy(ptr, targetType); err == nil {
			if err = c.RegisterInstance(ptr, ref); err != nil {
				panic(err)
			}
		} else {
			panic(err)
		}
		return
	}

	if enumref, isEnum := castValToEnumRef(data); isEnum {
		member, err := c.Types().EnumMemberForEnumRef(enumref)
		if err != nil {
			panic(err)
		}

		ptr.Set(reflect.ValueOf(member))
		return
	}

	if date, isDate := castValToDate(data); isDate {
		ptr.Set(reflect.ValueOf(date))
		return
	}

	// maps
	if m, isMap := c.castValToMap(data, ptr.Type()); isMap {
		ptr.Set(m)
		return
	}

	// arrays
	if data.Kind() == reflect.Slice {
		len := data.Len()
		var slice reflect.Value
		if ptr.Kind() == reflect.Slice {
			slice = reflect.MakeSlice(ptr.Type(), len, len)
		} else {
			slice = reflect.MakeSlice(reflect.SliceOf(anyType), len, len)
		}

		// If return type is a slice, recursively cast elements
		for i := 0; i < len; i++ {
			c.castAndSetToPtr(slice.Index(i), data.Index(i))
		}

		ptr.Set(slice)
		return
	}

	ptr.Set(data)
}