From 266e9002f3c1445e276987c7e9526ea8a8863be2 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Thu, 11 May 2023 15:34:41 +0200 Subject: [PATCH] results: Add Opt/Result converters (#177) 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. --- stew/results.nim | 14 ++++++++++++++ tests/test_results.nim | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/stew/results.nim b/stew/results.nim index e6af21e2..f60af4c8 100644 --- a/stew/results.nim +++ b/stew/results.nim @@ -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() diff --git a/tests/test_results.nim b/tests/test_results.nim index 73203a34..ef767c8b 100644 --- a/tests/test_results.nim +++ b/tests/test_results.nim @@ -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() @@ -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]