github.com/anthropics/anthropic-sdk-go@v1.70.1/packages/param/param.go (about)

     1  package param
     2  
     3  import (
     4  	"encoding/json"
     5  	"github.com/anthropics/anthropic-sdk-go/internal/encoding/json/sentinel"
     6  	"reflect"
     7  )
     8  
     9  // NullStruct is used to set a struct to the JSON value null.
    10  // Check for null structs with [IsNull].
    11  //
    12  // Only the first type parameter should be provided,
    13  // the type PtrT will be inferred.
    14  //
    15  //	json.Marshal(param.NullStruct[MyStruct]()) -> 'null'
    16  //
    17  // To send null to an [Opt] field use [Null].
    18  func NullStruct[T ParamStruct, PtrT InferPtr[T]]() T {
    19  	var t T
    20  	pt := PtrT(&t)
    21  	pt.setMetadata(nil)
    22  	return *pt
    23  }
    24  
    25  // Override replaces the value of a struct with any type.
    26  //
    27  // Only the first type parameter should be provided,
    28  // the type PtrT will be inferred.
    29  //
    30  // It's often useful for providing raw JSON
    31  //
    32  //	param.Override[MyStruct](json.RawMessage(`{"foo": "bar"}`))
    33  //
    34  // The public fields of the returned struct T will be unset.
    35  //
    36  // To override a specific field in a struct, use its [SetExtraFields] method.
    37  func Override[T ParamStruct, PtrT InferPtr[T]](v any) T {
    38  	var t T
    39  	pt := PtrT(&t)
    40  	pt.setMetadata(v)
    41  	return *pt
    42  }
    43  
    44  // SetJSON configures a param struct to serialize with the provided raw JSON data.
    45  // Use this when you have existing JSON that you want to send as request parameters.
    46  //
    47  //	var req example.NewUserParams
    48  //	var rawJSON = []byte(`{"name": "...", "age": 40}`)
    49  //	param.SetJSON(rawJSON, &req)
    50  //	res, err := client.Users.New(ctx, req)
    51  //
    52  // Note: The struct's existing fields will be ignored; only the provided JSON is serialized.
    53  func SetJSON(rawJSON []byte, ptr anyParamStruct) {
    54  	ptr.setMetadata(json.RawMessage(rawJSON))
    55  }
    56  
    57  // IsOmitted returns true if v is the zero value of its type.
    58  //
    59  // If IsOmitted is true, and the field uses a `json:"...,omitzero"` tag,
    60  // the field will be omitted from the request.
    61  //
    62  // If v is set explicitly to the JSON value "null", IsOmitted returns false.
    63  func IsOmitted(v any) bool {
    64  	if v == nil {
    65  		return false
    66  	}
    67  	if o, ok := v.(Optional); ok {
    68  		return o.isZero()
    69  	}
    70  	return reflect.ValueOf(v).IsZero()
    71  }
    72  
    73  // IsNull returns true if v was set to the JSON value null.
    74  //
    75  // To set a param to null use [NullStruct], [Null], [NullMap], or [NullSlice]
    76  // depending on the type of v.
    77  //
    78  // IsNull returns false if the value is omitted.
    79  func IsNull[T any](v T) bool {
    80  	if nullable, ok := any(v).(ParamNullable); ok {
    81  		return nullable.null()
    82  	}
    83  
    84  	switch reflect.TypeOf(v).Kind() {
    85  	case reflect.Slice, reflect.Map:
    86  		return sentinel.IsNull(v)
    87  	}
    88  
    89  	return false
    90  }
    91  
    92  // ParamNullable encapsulates all structs in parameters,
    93  // and all [Opt] types in parameters.
    94  type ParamNullable interface {
    95  	null() bool
    96  }
    97  
    98  // ParamStruct represents the set of all structs that are
    99  // used in API parameters, by convention these usually end in
   100  // "Params" or "Param".
   101  type ParamStruct interface {
   102  	Overrides() (any, bool)
   103  	null() bool
   104  	extraFields() map[string]any
   105  }
   106  
   107  // A pointer to ParamStruct
   108  type anyParamStruct interface {
   109  	setMetadata(any)
   110  }
   111  
   112  // This is an implementation detail and should never be explicitly set.
   113  type InferPtr[T ParamStruct] interface {
   114  	setMetadata(any)
   115  	*T
   116  }
   117  
   118  // APIObject should be embedded in api object fields, preferably using an alias to make private
   119  type APIObject struct{ metadata }
   120  
   121  // APIUnion should be embedded in all api unions fields, preferably using an alias to make private
   122  type APIUnion struct{ metadata }
   123  
   124  // Overrides returns the value of the struct when it is created with
   125  // [Override], the second argument helps differentiate an explicit null.
   126  func (m metadata) Overrides() (any, bool) {
   127  	if _, ok := m.any.(metadataExtraFields); ok {
   128  		return nil, false
   129  	}
   130  	return m.any, m.any != nil
   131  }
   132  
   133  // ExtraFields returns the extra fields added to the JSON object.
   134  func (m metadata) ExtraFields() map[string]any {
   135  	if extras, ok := m.any.(metadataExtraFields); ok {
   136  		return extras
   137  	}
   138  	return nil
   139  }
   140  
   141  // Omit can be used with [metadata.SetExtraFields] to ensure that a
   142  // required field is omitted. This is useful as an escape hatch for
   143  // when a required is unwanted for some unexpected reason.
   144  const Omit forceOmit = -1
   145  
   146  // SetExtraFields adds extra fields to the JSON object.
   147  //
   148  // SetExtraFields will override any existing fields with the same key.
   149  // For security reasons, ensure this is only used with trusted input data.
   150  //
   151  // To intentionally omit a required field, use [Omit].
   152  //
   153  //	foo.SetExtraFields(map[string]any{"bar": Omit})
   154  //
   155  // If the struct already contains the field ExtraFields, then this
   156  // method will have no effect.
   157  func (m *metadata) SetExtraFields(extraFields map[string]any) {
   158  	m.any = metadataExtraFields(extraFields)
   159  }
   160  
   161  // extraFields aliases [metadata.ExtraFields] to avoid name collisions.
   162  func (m metadata) extraFields() map[string]any { return m.ExtraFields() }
   163  
   164  func (m metadata) null() bool {
   165  	if _, ok := m.any.(metadataNull); ok {
   166  		return true
   167  	}
   168  
   169  	if msg, ok := m.any.(json.RawMessage); ok {
   170  		return string(msg) == "null"
   171  	}
   172  
   173  	return false
   174  }
   175  
   176  type metadata struct{ any }
   177  type metadataNull struct{}
   178  type metadataExtraFields map[string]any
   179  
   180  func (m *metadata) setMetadata(override any) {
   181  	if override == nil {
   182  		m.any = metadataNull{}
   183  		return
   184  	}
   185  	m.any = override
   186  }