fix: valueOr and withValue utilities (#1079)

This commit is contained in:
Ludovic Chenut 2024-04-04 17:15:50 +02:00 committed by GitHub
parent 03f67d3db5
commit 09b3e11956
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 97 additions and 8 deletions

View File

@ -112,24 +112,27 @@ template withValue*[T](self: Opt[T] | Option[T], value, body: untyped): untyped
let value {.inject.} = temp.get() let value {.inject.} = temp.get()
body body
macro withValue*[T](self: Opt[T] | Option[T], value, body, body2: untyped): untyped = macro withValue*[T](self: Opt[T] | Option[T], value, body, elseStmt: untyped): untyped =
let elseBody = body2[0] let elseBody = elseStmt[0]
quote do: quote do:
if `self`.isSome: let temp = (`self`)
let `value` {.inject.} = `self`.get() if temp.isSome:
let `value` {.inject.} = temp.get()
`body` `body`
else: else:
`elseBody` `elseBody`
template valueOr*[T](self: Option[T], body: untyped): untyped = template valueOr*[T](self: Option[T], body: untyped): untyped =
if self.isSome: let temp = (self)
self.get() if temp.isSome:
temp.get()
else: else:
body body
template toOpt*[T, E](self: Result[T, E]): Opt[T] = template toOpt*[T, E](self: Result[T, E]): Opt[T] =
if self.isOk: let temp = (self)
if temp.isOk:
when T is void: Result[void, void].ok() when T is void: Result[void, void].ok()
else: Opt.some(self.unsafeGet()) else: Opt.some(temp.unsafeGet())
else: else:
Opt.none(type(T)) Opt.none(type(T))

View File

@ -9,6 +9,7 @@
# This file may not be copied, modified, or distributed except according to # This file may not be copied, modified, or distributed except according to
# those terms. # those terms.
import options
import ./helpers import ./helpers
import ../libp2p/utility import ../libp2p/utility
@ -71,3 +72,88 @@ suite "Utility":
test "unsuccessful safeConvert from uint to int": test "unsuccessful safeConvert from uint to int":
check not (compiles do: check not (compiles do:
result: uint = safeConvert[int, uint](11.uint)) result: uint = safeConvert[int, uint](11.uint))
suite "withValue and valueOr templates":
type
TestObj = ref object
x: int
proc objIncAndOpt(self: TestObj): Opt[TestObj] =
self.x.inc()
return Opt.some(self)
proc objIncAndOption(self: TestObj): Option[TestObj] =
self.x.inc()
return some(self)
test "withValue calls right branch when Opt/Option is none":
var counter = 0
# check Opt/Option withValue with else
Opt.none(TestObj).withValue(v):
fail()
else:
counter.inc()
none(TestObj).withValue(v):
fail()
else:
counter.inc()
check counter == 2
# check Opt/Option withValue without else
Opt.none(TestObj).withValue(v):
fail()
none(TestObj).withValue(v):
fail()
test "withValue calls right branch when Opt/Option is some":
var counter = 1
# check Opt/Option withValue with else
Opt.some(counter).withValue(v):
counter.inc(v)
else:
fail()
some(counter).withValue(v):
counter.inc(v)
else:
fail()
# check Opt/Option withValue without else
Opt.some(counter).withValue(v):
counter.inc(v)
some(counter).withValue(v):
counter.inc(v)
check counter == 16
test "withValue calls right branch when Opt/Option is some with proc call":
var obj = TestObj(x: 0)
# check Opt/Option withValue with else
objIncAndOpt(obj).withValue(v):
v.x.inc()
else:
fail()
objIncAndOption(obj).withValue(v):
v.x.inc()
else:
fail()
# check Opt/Option withValue without else
objIncAndOpt(obj).withValue(v):
v.x.inc()
objIncAndOption(obj).withValue(v):
v.x.inc()
check obj.x == 8
test "valueOr calls with and without proc call":
var obj = none(TestObj).valueOr:
TestObj(x: 0)
check obj.x == 0
obj = some(TestObj(x: 2)).valueOr:
fail()
return
check obj.x == 2
obj = objIncAndOpt(obj).valueOr:
fail()
return
check obj.x == 3