github.com/go-playground/pkg/v5@v5.29.1/values/option/option_common.go (about)

     1  //go:build go1.18
     2  // +build go1.18
     3  
     4  package optionext
     5  
     6  import (
     7  	"encoding/json"
     8  )
     9  
    10  // Option represents a values that represents a values existence.
    11  //
    12  // nil is usually used on Go however this has two problems:
    13  // 1. Checking if the return values is nil is NOT enforced and can lead to panics.
    14  // 2. Using nil is not good enough when nil itself is a valid value.
    15  //
    16  // This implements the sql.Scanner interface and can be used as a sql value for reading and writing. It supports:
    17  // - String
    18  // - Bool
    19  // - Uint8
    20  // - Float64
    21  // - Int16
    22  // - Int32
    23  // - Int64
    24  // - interface{}/any
    25  // - time.Time
    26  // - Struct - when type is convertable to []byte and assumes JSON.
    27  // - Slice - when type is convertable to []byte and assumes JSON.
    28  // - Map types - when type is convertable to []byte and assumes JSON.
    29  //
    30  // This also implements the `json.Marshaler` and `json.Unmarshaler` interfaces. The only caveat is a None value will result
    31  // in a JSON `null` value. there is no way to hook into the std library to make `omitempty` not produce any value at
    32  // this time.
    33  type Option[T any] struct {
    34  	value  T
    35  	isSome bool
    36  }
    37  
    38  // IsSome returns true if the option is not empty.
    39  func (o Option[T]) IsSome() bool {
    40  	return o.isSome
    41  }
    42  
    43  // IsNone returns true if the option is empty.
    44  func (o Option[T]) IsNone() bool {
    45  	return !o.isSome
    46  }
    47  
    48  // Unwrap returns the values if the option is not empty or panics.
    49  func (o Option[T]) Unwrap() T {
    50  	if o.isSome {
    51  		return o.value
    52  	}
    53  	panic("Option.Unwrap: option is None")
    54  }
    55  
    56  // UnwrapOr returns the contained `Some` value or provided default value.
    57  //
    58  // Arguments passed to `UnwrapOr` are eagerly evaluated; if you are passing the result of a function call,
    59  // look to use `UnwrapOrElse`, which can be lazily evaluated.
    60  func (o Option[T]) UnwrapOr(value T) T {
    61  	if o.isSome {
    62  		return o.value
    63  	}
    64  	return value
    65  }
    66  
    67  // UnwrapOrElse returns the contained `Some` value or computes it from a provided function.
    68  func (o Option[T]) UnwrapOrElse(fn func() T) T {
    69  	if o.isSome {
    70  		return o.value
    71  	}
    72  	return fn()
    73  }
    74  
    75  // UnwrapOrDefault returns the contained `Some` value or the default value of the type T.
    76  func (o Option[T]) UnwrapOrDefault() T {
    77  	return o.value
    78  }
    79  
    80  // And calls the provided function with the contained value if the option is Some, returns the None value otherwise.
    81  func (o Option[T]) And(fn func(T) T) Option[T] {
    82  	if o.isSome {
    83  		o.value = fn(o.value)
    84  	}
    85  	return o
    86  }
    87  
    88  // AndThen calls the provided function with the contained value if the option is Some, returns the None value otherwise.
    89  //
    90  // This differs from `And` in that the provided function returns an Option[T] allowing changing of the Option value
    91  // itself.
    92  func (o Option[T]) AndThen(fn func(T) Option[T]) Option[T] {
    93  	if o.isSome {
    94  		return fn(o.value)
    95  	}
    96  	return o
    97  }
    98  
    99  // Some creates a new Option with the given values.
   100  func Some[T any](value T) Option[T] {
   101  	return Option[T]{value, true}
   102  }
   103  
   104  // None creates an empty Option that represents no values.
   105  func None[T any]() Option[T] {
   106  	return Option[T]{}
   107  }
   108  
   109  // MarshalJSON implements the `json.Marshaler` interface.
   110  func (o Option[T]) MarshalJSON() ([]byte, error) {
   111  	if o.isSome {
   112  		return json.Marshal(o.value)
   113  	}
   114  	return []byte("null"), nil
   115  }
   116  
   117  // UnmarshalJSON implements the `json.Unmarshaler` interface.
   118  func (o *Option[T]) UnmarshalJSON(data []byte) error {
   119  	if len(data) == 4 && string(data[:4]) == "null" {
   120  		*o = None[T]()
   121  		return nil
   122  	}
   123  	var v T
   124  	err := json.Unmarshal(data, &v)
   125  	if err != nil {
   126  		return err
   127  	}
   128  	*o = Some(v)
   129  	return nil
   130  }