mirror of
https://github.com/openai/openai-go.git
synced 2026-04-01 17:17:14 +09:00
123 lines
2.4 KiB
Go
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()
|
|
}
|