diff --git a/stew/result.nim b/stew/result.nim index 3740c10..86f1e80 100644 --- a/stew/result.nim +++ b/stew/result.nim @@ -12,6 +12,8 @@ type ## Note: If error is of exception type, it will be raised instead! error*: E + ResultDefect* = object of Defect + Result*[T, E] = object ## Result type that can hold either a value or an error, but not both ## @@ -232,9 +234,9 @@ func mapErr*[T: not void, E, A]( func mapConvert*[T0, E0]( self: Result[T0, E0], T1: type): Result[T1, E0] {.inline.} = - ## Convert result value to A using an implicit conversion - ## Would be nice if it was automatic... - if self.isOk: result.ok(self.v) + ## Convert result value to A using an conversion + # Would be nice if it was automatic... + if self.isOk: result.ok(T1(self.v)) else: result.err(self.e) func mapCast*[T0, E0]( @@ -342,6 +344,25 @@ template unsafeGet*[T, E](self: Result[T, E]): T = self.v +func expect*[T: not void, E](self: Result[T, E], m: string): T = + ## Return value of Result, or raise a `Defect` with the given message - use + ## this helper to extract the value when an error is not expected, for example + ## because the program logic dictates that the operation should never fail + ## + ## ```nim + ## let r = Result[int, int].ok(42) + ## # Put here a helpful comment why you think this won't fail + ## echo r.expect("r was just set to ok(42)") + ## ``` + if not self.isOk(): + raise (ref ResultDefect)(msg: m) + self.v + +func expect*[T: not void, E](self: var Result[T, E], m: string): var T = + if not self.isOk(): + raise (ref ResultDefect)(msg: m) + self.v + func `$`*(self: Result): string = ## Returns string representation of `self` if self.isOk: "Ok(" & $self.v & ")" @@ -416,6 +437,10 @@ template unsafeGet*[E](self: Result[void, E]) = ## See also: Option.unsafeGet assert not self.isErr +func expect*[E](self: Result[void, E], msg: string) = + if not self.isOk(): + raise (ref ResultDefect)(msg: msg) + func `$`*[E](self: Result[void, E]): string = ## Returns string representation of `self` if self.isOk: "Ok()" diff --git a/tests/test_result.nim b/tests/test_result.nim index 2c965c9..7d7996a 100644 --- a/tests/test_result.nim +++ b/tests/test_result.nim @@ -107,6 +107,7 @@ doAssert $rOk == "Ok(42)" doAssert rOk.mapConvert(int64)[] == int64(42) doAssert rOk.mapCast(int8)[] == int8(42) +doAssert rOk.mapConvert(uint64)[] == uint64(42) # TODO there's a bunch of operators that one could lift through magic - this # is mainly an example @@ -147,6 +148,8 @@ func testErr(): Result[int, string] = doAssert testOk()[] == 42 doAssert testErr().error == "323" +doAssert testOk().expect("testOk never fails") == 42 + func testQn(): Result[int, string] = let x = ?works() - ?works() result.ok(x) @@ -209,6 +212,7 @@ doAssert vErr.isErr doAssert vErr2.isErr vOk.get() +vOk.expect("should never fail") doAssert vOk.map(proc (): int = 42).get() == 42