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

     1  package param
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	shimjson "github.com/anthropics/anthropic-sdk-go/internal/encoding/json"
     7  	"time"
     8  )
     9  
    10  func NewOpt[T comparable](v T) Opt[T] {
    11  	return Opt[T]{Value: v, status: included}
    12  }
    13  
    14  // Null creates optional field with the JSON value "null".
    15  //
    16  // To set a struct to null, use [NullStruct].
    17  func Null[T comparable]() Opt[T] { return Opt[T]{status: null} }
    18  
    19  type status int8
    20  
    21  const (
    22  	omitted status = iota
    23  	null
    24  	included
    25  )
    26  
    27  // Opt represents an optional parameter of type T. Use
    28  // the [Opt.Valid] method to confirm.
    29  type Opt[T comparable] struct {
    30  	Value T
    31  	// indicates whether the field should be omitted, null, or valid
    32  	status status
    33  	opt
    34  }
    35  
    36  // Valid returns true if the value is not "null" or omitted.
    37  //
    38  // To check if explicitly null, use [Opt.Null].
    39  func (o Opt[T]) Valid() bool {
    40  	var empty Opt[T]
    41  	return o.status == included || o != empty && o.status != null
    42  }
    43  
    44  func (o Opt[T]) Or(v T) T {
    45  	if o.Valid() {
    46  		return o.Value
    47  	}
    48  	return v
    49  }
    50  
    51  func (o Opt[T]) String() string {
    52  	if o.null() {
    53  		return "null"
    54  	}
    55  	if s, ok := any(o.Value).(fmt.Stringer); ok {
    56  		return s.String()
    57  	}
    58  	return fmt.Sprintf("%v", o.Value)
    59  }
    60  
    61  func (o Opt[T]) MarshalJSON() ([]byte, error) {
    62  	if !o.Valid() {
    63  		return []byte("null"), nil
    64  	}
    65  	return shimjson.Marshal(o.Value)
    66  }
    67  
    68  func (o *Opt[T]) UnmarshalJSON(data []byte) error {
    69  	if string(data) == "null" {
    70  		o.status = null
    71  		return nil
    72  	}
    73  
    74  	var value *T
    75  	if err := json.Unmarshal(data, &value); err != nil {
    76  		return err
    77  	}
    78  
    79  	if value == nil {
    80  		o.status = omitted
    81  		return nil
    82  	}
    83  
    84  	o.status = included
    85  	o.Value = *value
    86  	return nil
    87  }
    88  
    89  // MarshalJSONWithTimeLayout is necessary to bypass the internal caching performed
    90  // by [json.Marshal]. Prefer to use [Opt.MarshalJSON] instead.
    91  //
    92  // This function requires that the generic type parameter of [Opt] is not [time.Time].
    93  func (o Opt[T]) MarshalJSONWithTimeLayout(format string) []byte {
    94  	t, ok := any(o.Value).(time.Time)
    95  	if !ok || o.null() {
    96  		return nil
    97  	}
    98  
    99  	b, err := shimjson.Marshal(t.Format(shimjson.TimeLayout(format)))
   100  	if err != nil {
   101  		return nil
   102  	}
   103  	return b
   104  }
   105  
   106  func (o Opt[T]) null() bool   { return o.status == null }
   107  func (o Opt[T]) isZero() bool { return o == Opt[T]{} }
   108  
   109  // opt helps limit the [Optional] interface to only types in this package
   110  type opt struct{}
   111  
   112  func (opt) implOpt() {}
   113  
   114  // This interface is useful for internal purposes.
   115  type Optional interface {
   116  	Valid() bool
   117  	null() bool
   118  
   119  	isZero() bool
   120  	implOpt()
   121  }