package opt
// Coalesce returns the first non-empty Opt.
// If all Opt values are empty, it returns empty Opt.
func Coalesce[T any](opts ...Opt[T]) (r Opt[T]) {
for _, o := range opts {
if o.IsPresent() {
return o
}
}
return
}
// Else returns the value from the first non-empty Opt.
// If all Opt values are empty, it returns the final value.
func Else[T any](final T, opts ...Opt[T]) T {
for _, o := range opts {
if val, ok := o.Get(); ok {
return val
}
}
return final
}
package opt
// Of creates a new Opt with the given value and ok set to true.
func Of[T any](val T) Opt[T] {
return Opt[T]{val: val, ok: true}
}
// FromOk creates a new Opt with the given value and ok status.
func FromOk[T any](val T, ok bool) Opt[T] {
return Opt[T]{val: val, ok: ok}
}
// FromErr creates a new Opt from a value and an error.
// - If the error is nil, it returns an Opt with the value and ok set to true.
// - If the error is not nil, it returns an empty Opt.
func FromErr[T any](val T, err error) (o Opt[T]) {
if err == nil {
return Opt[T]{val: val, ok: true}
}
return // zero opt is valid empty opt
}
// FromPtr creates a new Opt from a pointer.
// - If the pointer is not nil, it returns an Opt with the value pointed to and ok set to true.
// - If the pointer is nil, it returns an empty Opt.
func FromPtr[T any](ptr *T) (o Opt[T]) {
if ptr != nil {
return Opt[T]{val: *ptr, ok: true}
}
return // zero opt is valid empty opt
}
// FromZero creates a new Opt from a zeroable (emptiable) value.
// - If the value is not equal to its zero value, it returns an Opt with the value and ok set to true.
// - If the value is equal to its zero value, it returns an empty Opt.
func FromZero[T comparable](v T) (o Opt[T]) {
var zero T
if v != zero {
return Opt[T]{val: v, ok: true}
}
return // zero opt is valid empty opt
}
// Package opt provides a generic optional type Opt
// that can be used to represent a value that may or may not be present.
package opt
// Opt is a generic optional type that can hold a value of type T or be empty.
type Opt[T any] struct {
val T
ok bool
}
// IsPresent returns true if the Opt contains a value.
func (o Opt[T]) IsPresent() bool {
return o.ok
}
// IsMissing returns true if the Opt does not contain a value.
func (o Opt[T]) IsMissing() bool {
return !o.ok
}
// Get returns the value and a boolean indicating if the value is present.
func (o Opt[T]) Get() (T, bool) {
return o.val, o.ok
}
// Ptr returns a pointer to the value if it is present, or nil if it is not.
func (o Opt[T]) Ptr() *T {
if !o.ok {
return nil
}
return &o.val
}
// Or returns the value if it is present, otherwise it returns the provided fallback value.
func (o Opt[T]) Or(fallback T) T {
if o.ok {
return o.val
}
return fallback
}
// OrZero returns the value if it is present, otherwise it returns the zero value of T.
func (o Opt[T]) OrZero() T {
if o.ok {
return o.val
}
var zero T
return zero
}
package ptr
import "github.com/sr9000/go-ptr-tools/ref"
// Coalesce returns the first not nil pointer.
// If all pointers are nil, it returns nil.
func Coalesce[T any](pointers ...*T) *T {
for _, ptr := range pointers {
if ptr != nil {
return ptr
}
}
return nil
}
// Else returns the first not nil pointer as a ref.Ref.
// If all pointers are nil, it returns the final ref.Ref.
func Else[T any](final ref.Ref[T], pointers ...*T) ref.Ref[T] {
for _, ptr := range pointers {
if ptr != nil {
return ref.Guaranteed(ptr)
}
}
return final
}
// Package ptr provides several helper routines for working with pointers.
package ptr
// Of returns pointer onto a value, works with primitive types (int, string, etc.).
func Of[T any](v T) *T {
return &v
}
// FromOk creates a new pointer from a value and an ok flag.
// If ok equals true, it returns a pointer to val, else nil.
func FromOk[T any](val T, ok bool) *T {
if ok {
return &val
}
return nil
}
// FromErr creates a new pointer from a value and an error.
// - If the error is nil, it returns a pointer to val.
// - If the error is not nil, it returns nil.
func FromErr[T any](val T, err error) *T {
if err == nil {
return &val
}
return nil
}
// FromZero creates a new pointer from a zeroable (emptiable) value.
// - If the value is not equal to its zero value, it returns a pointer to val.
// - If the value is equal to its zero value, it returns nil.
func FromZero[T comparable](v T) *T {
var zero T
if v != zero {
return &v
}
return nil
}
// OrVal returns the value pointed to by ptr if it is not nil, otherwise it returns the provided value.
func OrVal[T any](value T, ptrs ...*T) T {
for _, p := range ptrs {
if p != nil {
return *p
}
}
return value
}
// OrZero returns the value pointed to by ptr if it is not nil, otherwise it returns the zero value of T.
func OrZero[T any](ptrs ...*T) T {
var zero T
return OrVal(zero, ptrs...)
}
package ref
// Of returns a new Ref based on the given value.
func Of[T any](v T) Ref[T] {
return Ref[T]{&v}
}
// Guaranteed returns a new Ref based on the given pointer that is guaranteed to be not nil.
// It is useful when you know that the pointer is not nil, but the compiler does not.
func Guaranteed[T any](notNilPtr *T) Ref[T] {
return Ref[T]{notNilPtr}
}
// FromPtr returns a new Ref based on the given pointer.
// It returns an error if the pointer is nil.
func FromPtr[T any](ptr *T) (Ref[T], error) {
if ptr == nil {
return Ref[T]{}, ErrPtrMustBeNotNil
}
return Ref[T]{ptr}, nil
}
// Package ref provides a reference type Ref that can be used to store an "always valid pointer".
package ref
// Ref must be used as mental anchor for "always valid pointer" guarantees.
type Ref[T any] struct {
ptr *T
}
// Ptr returns the pointer to the value.
// There is no need to check for nil, because the pointer is guaranteed to be not nil.
func (r Ref[T]) Ptr() *T {
return r.ptr
}
// Val returns the value itself.
func (r Ref[T]) Val() T {
return *r.ptr
}