// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT. package reflect import ( "context" "fmt" "reflect" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/attr/xattr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-go/tftypes" ) // Pointer builds a new zero value of the concrete type that `target` // references, populates it with BuildValue, and takes a pointer to it. // // It is meant to be called through Into, not directly. func Pointer(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.Value, opts Options, path path.Path) (reflect.Value, diag.Diagnostics) { var diags diag.Diagnostics if target.Kind() != reflect.Ptr { diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{ Val: val, TargetType: target.Type(), Err: fmt.Errorf("cannot dereference pointer, not a pointer, is a %s (%s)", target.Type(), target.Kind()), })) return target, diags } // we may have gotten a nil pointer, so we need to create our own that // we can set // FORK START pointer := target if target.IsNil() { pointer = reflect.New(target.Type().Elem()) } // FORK END // build out whatever the pointer is pointing to pointed, pointedDiags := BuildValue(ctx, typ, val, pointer.Elem(), opts, path) diags.Append(pointedDiags...) if diags.HasError() { return target, diags } // to be able to set the pointer to our new pointer, we need to create // a pointer to the pointer pointerPointer := reflect.New(pointer.Type()) // we set the pointer we created on the pointer to the pointer pointerPointer.Elem().Set(pointer) // then it's settable, so we can now set the concrete value we created // on the pointer pointerPointer.Elem().Elem().Set(pointed) // return the pointer we created return pointerPointer.Elem(), diags } // create a zero value of concrete type underlying any number of pointers, then // wrap it in that number of pointers again. The end result is to wind up with // the same exact type, except now you can be sure it's pointing to actual data // and will not give you a nil pointer dereference panic unexpectedly. func pointerSafeZeroValue(_ context.Context, target reflect.Value) reflect.Value { pointer := target.Type() var pointers int for pointer.Kind() == reflect.Ptr { pointer = pointer.Elem() pointers++ } receiver := reflect.Zero(pointer) for i := 0; i < pointers; i++ { newReceiver := reflect.New(receiver.Type()) newReceiver.Elem().Set(receiver) receiver = newReceiver } return receiver } // FromPointer turns a pointer into an attr.Value using `typ`. If the pointer // is nil, the attr.Value will use its null representation. If it is not nil, // it will recurse into FromValue to find the attr.Value of the type the value // the pointer is referencing. // // It is meant to be called through FromValue, not directly. func FromPointer(ctx context.Context, typ attr.Type, value reflect.Value, path path.Path) (attr.Value, diag.Diagnostics) { var diags diag.Diagnostics if value.Kind() != reflect.Ptr { err := fmt.Errorf("cannot use type %s as a pointer", value.Type()) diags.AddAttributeError( path, "Value Conversion Error", "An unexpected error was encountered trying to convert from pointer value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), ) return nil, diags } if value.IsNil() { tfVal := tftypes.NewValue(typ.TerraformType(ctx), nil) if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok { diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags } } attrVal, err := typ.ValueFromTerraform(ctx, tfVal) if err != nil { diags.AddAttributeError( path, "Value Conversion Error", "An unexpected error was encountered trying to convert from pointer value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), ) return nil, diags } return attrVal, diags } attrVal, attrValDiags := FromValue(ctx, typ, value.Elem().Interface(), path) diags.Append(attrValDiags...) return attrVal, diags }