Files
stainless-app[bot] 13778d44fe release: 3.0.0
2025-09-30 16:35:20 +00:00

123 lines
2.4 KiB
Go

package param
import (
"encoding/json"
"fmt"
"time"
shimjson "github.com/openai/openai-go/v3/internal/encoding/json"
)
func NewOpt[T comparable](v T) Opt[T] {
return Opt[T]{Value: v, status: included}
}
// Null creates optional field with the JSON value "null".
//
// To set a struct to null, use [NullStruct].
func Null[T comparable]() Opt[T] { return Opt[T]{status: null} }
type status int8
const (
omitted status = iota
null
included
)
// Opt represents an optional parameter of type T. Use
// the [Opt.Valid] method to confirm.
type Opt[T comparable] struct {
Value T
// indicates whether the field should be omitted, null, or valid
status status
opt
}
// Valid returns true if the value is not "null" or omitted.
//
// To check if explicitly null, use [Opt.Null].
func (o Opt[T]) Valid() bool {
var empty Opt[T]
return o.status == included || o != empty && o.status != null
}
func (o Opt[T]) Or(v T) T {
if o.Valid() {
return o.Value
}
return v
}
func (o Opt[T]) String() string {
if o.null() {
return "null"
}
if s, ok := any(o.Value).(fmt.Stringer); ok {
return s.String()
}
return fmt.Sprintf("%v", o.Value)
}
func (o Opt[T]) MarshalJSON() ([]byte, error) {
if !o.Valid() {
return []byte("null"), nil
}
return shimjson.Marshal(o.Value)
}
func (o *Opt[T]) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
o.status = null
return nil
}
var value *T
if err := json.Unmarshal(data, &value); err != nil {
return err
}
if value == nil {
o.status = omitted
return nil
}
o.status = included
o.Value = *value
return nil
}
// MarshalJSONWithTimeLayout is necessary to bypass the internal caching performed
// by [json.Marshal]. Prefer to use [Opt.MarshalJSON] instead.
//
// This function requires that the generic type parameter of [Opt] is not [time.Time].
func (o Opt[T]) MarshalJSONWithTimeLayout(format string) []byte {
t, ok := any(o.Value).(time.Time)
if !ok || o.null() {
return nil
}
b, err := shimjson.Marshal(t.Format(shimjson.TimeLayout(format)))
if err != nil {
return nil
}
return b
}
func (o Opt[T]) null() bool { return o.status == null }
func (o Opt[T]) isZero() bool { return o == Opt[T]{} }
// opt helps limit the [Optional] interface to only types in this package
type opt struct{}
func (opt) implOpt() {}
// This interface is useful for internal purposes.
type Optional interface {
Valid() bool
null() bool
isZero() bool
implOpt()
}