mirror of
https://github.com/LukeHagar/plexterraform.git
synced 2025-12-10 04:21:03 +00:00
217 lines
8.6 KiB
Go
217 lines
8.6 KiB
Go
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
|
|
|
package reflect
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/big"
|
|
"reflect"
|
|
|
|
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
|
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
|
)
|
|
|
|
// Into uses the data in `val` to populate `target`, using the reflection
|
|
// package to recursively reflect into structs and slices. If `target` is an
|
|
// attr.Value, its assignment method will be used instead of reflecting. If
|
|
// `target` is a tftypes.ValueConverter, the FromTerraformValue method will be
|
|
// used instead of using reflection. Primitives are set using the val.As
|
|
// method. Structs use reflection: each exported struct field must have a
|
|
// "tfsdk" tag with the name of the field in the tftypes.Value, and all fields
|
|
// in the tftypes.Value must have a corresponding property in the struct. Into
|
|
// will be called for each struct field. Slices will have Into called for each
|
|
// element.
|
|
func Into(ctx context.Context, typ attr.Type, val tftypes.Value, target interface{}, opts Options, path path.Path) diag.Diagnostics {
|
|
var diags diag.Diagnostics
|
|
|
|
v := reflect.ValueOf(target)
|
|
if v.Kind() != reflect.Ptr {
|
|
err := fmt.Errorf("target must be a pointer, got %T, which is a %s", target, v.Kind())
|
|
diags.AddAttributeError(
|
|
path,
|
|
"Value Conversion Error",
|
|
fmt.Sprintf("An unexpected error was encountered trying to convert the value. This is always an error in the provider. Please report the following to the provider developer:\n\nPath: %s\nError: %s", path.String(), err.Error()),
|
|
)
|
|
return diags
|
|
}
|
|
result, diags := BuildValue(ctx, typ, val, v.Elem(), opts, path)
|
|
if diags.HasError() {
|
|
return diags
|
|
}
|
|
v.Elem().Set(result)
|
|
return diags
|
|
}
|
|
|
|
// BuildValue constructs a reflect.Value of the same type as `target`,
|
|
// populated with the data in `val`. It will defensively instantiate new values
|
|
// to set, making it safe for use with pointer types which may be nil. It tries
|
|
// to give consumers the ability to override its default behaviors wherever
|
|
// possible.
|
|
func BuildValue(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 this isn't a valid reflect.Value, bail before we accidentally
|
|
// panic
|
|
if !target.IsValid() {
|
|
err := fmt.Errorf("invalid target")
|
|
diags.AddAttributeError(
|
|
path,
|
|
"Value Conversion Error",
|
|
"An unexpected error was encountered trying to build a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
|
|
)
|
|
return target, diags
|
|
}
|
|
|
|
// -------------------------
|
|
// -- Fork Start -----------
|
|
// -------------------------
|
|
|
|
if !val.IsKnown() {
|
|
return target, diags
|
|
}
|
|
|
|
// -------------------------
|
|
// -- Fork End - -----------
|
|
// -------------------------
|
|
|
|
// if this is an attr.Value, build the type from that
|
|
if target.Type().Implements(reflect.TypeOf((*attr.Value)(nil)).Elem()) {
|
|
return NewAttributeValue(ctx, typ, val, target, opts, path)
|
|
}
|
|
// if this tells tftypes how to build an instance of it out of a
|
|
// tftypes.Value, well, that's what we want, so do that instead of our
|
|
// default logic.
|
|
if target.Type().Implements(reflect.TypeOf((*tftypes.ValueConverter)(nil)).Elem()) {
|
|
return NewValueConverter(ctx, typ, val, target, opts, path)
|
|
}
|
|
// if this can explicitly be set to unknown, do that
|
|
if target.Type().Implements(reflect.TypeOf((*Unknownable)(nil)).Elem()) {
|
|
res, unknownableDiags := NewUnknownable(ctx, typ, val, target, opts, path)
|
|
diags.Append(unknownableDiags...)
|
|
if diags.HasError() {
|
|
return target, diags
|
|
}
|
|
target = res
|
|
// only return if it's unknown; we want to call SetUnknown
|
|
// either way, but if the value is unknown, there's nothing
|
|
// else to do, so bail
|
|
if !val.IsKnown() {
|
|
return target, nil
|
|
}
|
|
}
|
|
// if this can explicitly be set to null, do that
|
|
if target.Type().Implements(reflect.TypeOf((*Nullable)(nil)).Elem()) {
|
|
res, nullableDiags := NewNullable(ctx, typ, val, target, opts, path)
|
|
diags.Append(nullableDiags...)
|
|
if diags.HasError() {
|
|
return target, diags
|
|
}
|
|
target = res
|
|
// only return if it's null; we want to call SetNull either
|
|
// way, but if the value is null, there's nothing else to do,
|
|
// so bail
|
|
if val.IsNull() {
|
|
return target, nil
|
|
}
|
|
}
|
|
// -------------------------
|
|
// -- Fork Start -----------
|
|
// -------------------------
|
|
//if !val.IsKnown() {
|
|
// // we already handled unknown the only ways we can
|
|
// // we checked that target doesn't have a SetUnknown method we
|
|
// // can call
|
|
// // we checked that target isn't an attr.Value
|
|
// // all that's left to us now is to set it as an empty value or
|
|
// // throw an error, depending on what's in opts
|
|
// if !opts.UnhandledUnknownAsEmpty {
|
|
// diags.AddAttributeError(
|
|
// path,
|
|
// "Value Conversion Error",
|
|
// "An unexpected error was encountered trying to build a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+
|
|
// "Received unknown value, however the target type cannot handle unknown values. Use the corresponding `types` package type or a custom type that handles unknown values.\n\n"+
|
|
// fmt.Sprintf("Path: %s\nTarget Type: %s\nSuggested Type: %s", path.String(), target.Type(), reflect.TypeOf(typ.ValueType(ctx))),
|
|
// )
|
|
// return target, diags
|
|
// }
|
|
// // we want to set unhandled unknowns to the empty value
|
|
// return reflect.Zero(target.Type()), diags
|
|
//}
|
|
// -------------------------
|
|
// -- Fork End - -----------
|
|
// -------------------------
|
|
|
|
if val.IsNull() {
|
|
// we already handled null the only ways we can
|
|
// we checked that target doesn't have a SetNull method we can
|
|
// call
|
|
// we checked that target isn't an attr.Value
|
|
// all that's left to us now is to set it as an empty value or
|
|
// throw an error, depending on what's in opts
|
|
if canBeNil(target) || opts.UnhandledNullAsEmpty {
|
|
return reflect.Zero(target.Type()), nil
|
|
}
|
|
|
|
diags.AddAttributeError(
|
|
path,
|
|
"Value Conversion Error",
|
|
"An unexpected error was encountered trying to build a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+
|
|
"Received null value, however the target type cannot handle null values. Use the corresponding `types` package type, a pointer type or a custom type that handles null values.\n\n"+
|
|
fmt.Sprintf("Path: %s\nTarget Type: %s\nSuggested `types` Type: %s\nSuggested Pointer Type: *%s", path.String(), target.Type(), reflect.TypeOf(typ.ValueType(ctx)), target.Type()),
|
|
)
|
|
|
|
return target, diags
|
|
}
|
|
// *big.Float and *big.Int are technically pointers, but we want them
|
|
// handled as numbers
|
|
if target.Type() == reflect.TypeOf(big.NewFloat(0)) || target.Type() == reflect.TypeOf(big.NewInt(0)) {
|
|
return Number(ctx, typ, val, target, opts, path)
|
|
}
|
|
switch target.Kind() {
|
|
case reflect.Struct:
|
|
val, valDiags := Struct(ctx, typ, val, target, opts, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
case reflect.Bool, reflect.String:
|
|
val, valDiags := Primitive(ctx, typ, val, target, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16,
|
|
reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
|
// numbers are the wooooorst and need their own special handling
|
|
// because we can't just hand them off to tftypes and also
|
|
// because we can't just make people use *big.Floats, because a
|
|
// nil *big.Float will crash everything if we don't handle it
|
|
// as a special case, so let's just special case numbers and
|
|
// let people use the types they want
|
|
val, valDiags := Number(ctx, typ, val, target, opts, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
case reflect.Slice:
|
|
val, valDiags := reflectSlice(ctx, typ, val, target, opts, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
case reflect.Map:
|
|
val, valDiags := Map(ctx, typ, val, target, opts, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
case reflect.Ptr:
|
|
val, valDiags := Pointer(ctx, typ, val, target, opts, path)
|
|
diags.Append(valDiags...)
|
|
return val, diags
|
|
default:
|
|
err := fmt.Errorf("don't know how to reflect %s into %s", val.Type(), target.Type())
|
|
diags.AddAttributeError(
|
|
path,
|
|
"Value Conversion Error",
|
|
"An unexpected error was encountered trying to build a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
|
|
)
|
|
return target, diags
|
|
}
|
|
}
|