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