Skip to content

Commit

Permalink
results: Add Opt/Result converters (#177)
Browse files Browse the repository at this point in the history
Add `optError`, `optValue`, to convert back and forth between Opt and Result
These conversions end up being more common than others since "trivial"  success/fail-style API often use Opt while combining such API into combined operations tends to prefer richer error reporting.
  • Loading branch information
arnetheduck authored May 11, 2023
1 parent 111d939 commit 266e900
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
14 changes: 14 additions & 0 deletions stew/results.nim
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,20 @@ template unsafeError*[T](self: Result[T, void]) =
## See also: `unsafeGet`
assert not self.oResultPrivate # Emulate field access defect in debug builds

func optValue*[T, E](self: Result[T, E]): Opt[T] =
## Return the value of a Result as an Opt, or none if Result is an error
if self.oResultPrivate:
Opt.some(self.vResultPrivate)
else:
Opt.none(T)

func optError*[T, E](self: Result[T, E]): Opt[E] =
## Return the error of a Result as an Opt, or none if Result is a value
if self.oResultPrivate:
Opt.none(E)
else:
Opt.some(self.eResultPrivate)

# Alternative spellings for get
template value*[T, E](self: Result[T, E]): T = self.get()
template value*[T: not void, E](self: var Result[T, E]): var T = self.get()
Expand Down
10 changes: 10 additions & 0 deletions tests/test_results.nim
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ block:
# Expectations
doAssert rOk.expect("testOk never fails") == 42

# Conversions to Opt
doAssert rOk.optValue() == Opt.some(rOk.get())
doAssert rOk.optError().isNone()
doAssert rErr.optValue().isNone()
doAssert rErr.optError() == Opt.some(rErr.error())

# Question mark operator
func testQn(): Result[int, string] =
let x = ?works() - ?works()
Expand Down Expand Up @@ -371,6 +377,10 @@ block: # Result[T, void] aka `Opt`
doAssert Opt.some(42).get() == 42
doAssert Opt.none(int).isNone()

# Construct Result from Opt
doAssert oOk.orErr("error").value() == oOk.get()
doAssert oErr.orErr("error").error() == "error"

block: # `cstring` dangling reference protection
type CSRes = Result[void, cstring]

Expand Down

0 comments on commit 266e900

Please sign in to comment.