github.com/enetx/g@v1.0.80/result.go (about)

     1  package g
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  )
     9  
    10  // Ok returns a new Result[T] containing the given value.
    11  func Ok[T any](value T) Result[T] { return Result[T]{value: &value, err: nil} }
    12  
    13  // Err returns a new Result[T] containing the given error.
    14  func Err[T any](err error) Result[T] { return Result[T]{value: nil, err: err} }
    15  
    16  // ResultOf returns a new Result[T] based on the provided value and error.
    17  // If err is not nil, it returns an Result containing the error.
    18  // Otherwise, it returns an Result containing the value.
    19  func ResultOf[T any](value T, err error) Result[T] {
    20  	if err != nil {
    21  		return Err[T](err)
    22  	}
    23  
    24  	return Ok(value)
    25  }
    26  
    27  // ResultMap applies the given function to the value inside the Result, producing a new Result with the transformed value.
    28  // If the input Result contains a value, the provided function is applied to it.
    29  // If the input Result contains an error, the output Result will also contain the same error.
    30  // Parameters:
    31  //   - r: The input Result to map over.
    32  //   - fn: The function that returns a Result to apply to the value inside the Result.
    33  //
    34  // Returns:
    35  //
    36  //	A new Result with the transformed value, or the same error if the input Result contained an error.
    37  func ResultMap[T, U any](r Result[T], fn func(T) Result[U]) Result[U] {
    38  	if r.IsErr() {
    39  		return Err[U](r.Err())
    40  	}
    41  
    42  	return fn(r.Ok())
    43  }
    44  
    45  // ResultOfMap applies the given function to the value inside the Result, producing a new Result with the transformed value.
    46  // If the input Result contains a value, the provided function is applied to it.
    47  // If the input Result contains an error, the output Result will also contain the same error.
    48  // Parameters:
    49  //   - r: The input Result to map over.
    50  //   - fn: The function that returns a tuple (U, error) to apply to the value inside the Result.
    51  //
    52  // Returns:
    53  //
    54  //	A new Result with the transformed value, or the same error if the input Result contained an error.
    55  func ResultOfMap[T, U any](r Result[T], fn func(T) (U, error)) Result[U] {
    56  	if r.IsErr() {
    57  		return Err[U](r.Err())
    58  	}
    59  
    60  	return ResultOf(fn(r.Ok()))
    61  }
    62  
    63  // Ok returns the value held in the Result.
    64  func (r Result[T]) Ok() T { return *r.value }
    65  
    66  // Err returns the error held in the Result.
    67  func (r Result[T]) Err() error { return r.err }
    68  
    69  // IsOk returns true if the Result contains a value (no error).
    70  func (r Result[T]) IsOk() bool { return r.err == nil }
    71  
    72  // IsErr returns true if the Result contains an error.
    73  func (r Result[T]) IsErr() bool { return r.err != nil }
    74  
    75  // Result returns the value held in the Result and its error.
    76  func (r Result[T]) Result() (T, error) {
    77  	if r.IsErr() {
    78  		return *new(T), r.Err()
    79  	}
    80  
    81  	return r.Ok(), nil
    82  }
    83  
    84  // Unwrap returns the value held in the Result. If the Result contains an error, it panics.
    85  func (r Result[T]) Unwrap() T {
    86  	if r.IsErr() {
    87  		if pc, file, line, ok := runtime.Caller(1); ok {
    88  			out := fmt.Sprintf("[%s:%d] [%s] %v", filepath.Base(file), line, runtime.FuncForPC(pc).Name(), r.err)
    89  			fmt.Fprintln(os.Stderr, out)
    90  		}
    91  
    92  		panic(r.err)
    93  	}
    94  
    95  	return r.Ok()
    96  }
    97  
    98  // UnwrapOr returns the value held in the Result. If the Result contains an error, it returns the provided default value.
    99  func (r Result[T]) UnwrapOr(value T) T {
   100  	if r.IsErr() {
   101  		return value
   102  	}
   103  
   104  	return r.Ok()
   105  }
   106  
   107  // UnwrapOrDefault returns the value held in the Result. If the Result contains an error,
   108  // it returns the default value for type T. Otherwise, it returns the value held in the Result.
   109  func (r Result[T]) UnwrapOrDefault() T {
   110  	if r.IsErr() {
   111  		return *new(T)
   112  	}
   113  
   114  	return r.Ok()
   115  }
   116  
   117  // Expect returns the value held in the Result. If the Result contains an error, it panics with the provided message.
   118  func (r Result[T]) Expect(msg string) T {
   119  	if r.IsErr() {
   120  		out := fmt.Sprintf("%s: %v", msg, r.err)
   121  		fmt.Fprintln(os.Stderr, out)
   122  		panic(out)
   123  	}
   124  
   125  	return r.Ok()
   126  }
   127  
   128  // Then applies the function fn to the value inside the Result and returns a new Result.
   129  // If the Result contains an error, it returns the same Result without applying fn.
   130  func (r Result[T]) Then(fn func(T) Result[T]) Result[T] {
   131  	if r.IsErr() {
   132  		return r
   133  	}
   134  
   135  	return fn(r.Ok())
   136  }
   137  
   138  // ThenOf applies the function fn to the value inside the Result, expecting
   139  // fn to return a tuple (T, error), and returns a new Result based on the
   140  // returned tuple. If the Result contains an error, it returns the same Result
   141  // without applying fn.
   142  func (r Result[T]) ThenOf(fn func(T) (T, error)) Result[T] {
   143  	if r.IsErr() {
   144  		return r
   145  	}
   146  
   147  	return ResultOf(fn(r.Ok()))
   148  }
   149  
   150  // Option converts a Result into an Option.
   151  // If the Result contains an error, it returns None.
   152  // If the Result contains a value, it returns Some with the value.
   153  // Parameters:
   154  //   - r: The input Result to convert into an Option.
   155  //
   156  // Returns:
   157  //
   158  //	An Option representing the value of the Result, if any.
   159  func (r Result[T]) Option() Option[T] {
   160  	if r.IsErr() {
   161  		return None[T]()
   162  	}
   163  
   164  	return Some(r.Ok())
   165  }
   166  
   167  func (r Result[T]) String() string {
   168  	if r.IsOk() {
   169  		return fmt.Sprintf("Ok(%v)", r.Ok())
   170  	}
   171  
   172  	return fmt.Sprintf("Err(%s)", r.Err().Error())
   173  }