package core

// Result is a sum type representing either a successful value or an error.
// Exactly one of Ok or Err is non-nil at any time.
type Result[T any] struct {
	ok  *T
	err error
}

// Ok creates a successful Result.
func Ok[T any](v T) Result[T] {
	return Result[T]{ok: &v}
}

// Err creates a failed Result.
func Err[T any](err error) Result[T] {
	return Result[T]{err: err}
}

// IsOk returns true if the Result contains a value.
func (r Result[T]) IsOk() bool {
	return r.ok != nil
}

// IsErr returns true if the Result contains an error.
func (r Result[T]) IsErr() bool {
	return r.err != nil
}

// Unwrap returns the value or panics if the Result is an error.
func (r Result[T]) Unwrap() T {
	if r.ok == nil {
		panic("called Unwrap on an Err Result")
	}
	return *r.ok
}

// UnwrapErr returns the error or panics if the Result is Ok.
func (r Result[T]) UnwrapErr() error {
	if r.err == nil {
		panic("called UnwrapErr on an Ok Result")
	}
	return r.err
}

// UnwrapOr returns the value or a default if the Result is an error.
func (r Result[T]) UnwrapOr(def T) T {
	if r.ok != nil {
		return *r.ok
	}
	return def
}
