140 lines
2.9 KiB
Go
140 lines
2.9 KiB
Go
package Type
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
func Expect[T any](val Unwrappable[T], msg string) T {
|
|
return val.Expect(msg)
|
|
}
|
|
|
|
func Unwrap[T any](val Unwrappable[T]) T {
|
|
return val.Unwrap()
|
|
}
|
|
|
|
func UnwrapOr[T any](val Unwrappable[T]) (def T) {
|
|
return val.UnwrapOr(def)
|
|
}
|
|
|
|
func UnwrapOrDefault[T any](val Unwrappable[T]) T {
|
|
return val.UnwrapOrDefault()
|
|
}
|
|
|
|
func UnwrapOrElse[T any](val Unwrappable[T], f func() T) T {
|
|
return val.UnwrapOrElse(f)
|
|
}
|
|
|
|
// Returns if the underlying data has a Value (false in case of None or Error)
|
|
func HasValue(val ValueContainer) bool {
|
|
return val.HasValue()
|
|
}
|
|
|
|
func ResultWrap[T any](val T, err error) Result[T] {
|
|
if err == nil {
|
|
return Ok(val)
|
|
}
|
|
return Err[T](err)
|
|
}
|
|
|
|
func ResultWrapb[T any](err error, val T) Result[T] {
|
|
if err == nil {
|
|
return Ok(val)
|
|
}
|
|
return Err[T](err)
|
|
}
|
|
|
|
func Ptr[T any](v T) *T {
|
|
return &v
|
|
}
|
|
|
|
// meant to be used as defer Type.CatchUnwrap(Type.Ptr(&res)) or Type.CatchUnwrap(&res) if res is already a pointer
|
|
// where res is a pointer to an Option or Result returned by a function (initialized to not be nil)
|
|
// func X() (res *Optional[int]) {
|
|
// res = None[int]()
|
|
// defer CatchUnwrap(&res)
|
|
//
|
|
// // Some possibly unsafe unwrapping of values
|
|
// return res
|
|
// }
|
|
// === OR ===
|
|
// func X() (res Optional[int]) {
|
|
// res = None[int]()
|
|
// defer Type.CatchUnwrap(Type.Ptr(&res))
|
|
//
|
|
// // Some possibly unsafe unwrapping of values
|
|
// return res
|
|
// }
|
|
|
|
func CatchUnwrap(ret interface{}) {
|
|
r := recover()
|
|
if r == nil {
|
|
return
|
|
}
|
|
vp := reflect.ValueOf(r)
|
|
if vp.Kind() != reflect.Pointer || vp.IsNil() {
|
|
panic(r)
|
|
}
|
|
|
|
if _, ok := r.(OptionalerMarker); ok {
|
|
if setOptionalNone(ret) {
|
|
return
|
|
}
|
|
}
|
|
|
|
if _, ok := r.(ResulterMarker); ok {
|
|
if setResultError(ret, fmt.Errorf("Tried to unwrap a failed result!")) {
|
|
return
|
|
}
|
|
}
|
|
|
|
panic(r)
|
|
}
|
|
|
|
func setOptionalNone(ret interface{}) bool {
|
|
v := reflect.ValueOf(ret)
|
|
if v.Kind() != reflect.Ptr || v.IsNil() {
|
|
return false
|
|
}
|
|
elem := v.Elem().Elem()
|
|
if elem.Kind() != reflect.Struct {
|
|
return false
|
|
}
|
|
presentField := elem.FieldByName("present")
|
|
if !presentField.IsValid() {
|
|
return false
|
|
}
|
|
if presentField.Kind() == reflect.Bool {
|
|
presentField = reflect.NewAt(presentField.Type(),
|
|
unsafe.Pointer(presentField.UnsafeAddr())).Elem()
|
|
presentField.SetBool(false) // Setting it to false (None)
|
|
} else {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func setResultError(ret interface{}, err error) bool {
|
|
v := reflect.ValueOf(ret)
|
|
if v.Kind() != reflect.Ptr || v.IsNil() {
|
|
return false
|
|
}
|
|
elem := v.Elem().Elem()
|
|
if elem.Kind() != reflect.Struct {
|
|
return false
|
|
}
|
|
errField := elem.FieldByName("err")
|
|
if !errField.IsValid() {
|
|
return false
|
|
}
|
|
if errField.Kind() == reflect.Interface {
|
|
errField = reflect.NewAt(errField.Type(),
|
|
unsafe.Pointer(errField.UnsafeAddr())).Elem()
|
|
errField.Set(reflect.ValueOf(err)) // Setting the error
|
|
} else {
|
|
return false
|
|
}
|
|
return true
|
|
}
|