nim-codex/codex/utils/options.nim

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

72 lines
2.2 KiB
Nim
Raw Normal View History

import std/macros
import pkg/questionable
import pkg/questionable/operators
export questionable
proc `as`*[T](value: T, U: type): ?U =
## Casts a value to another type, returns an Option.
## When the cast succeeds, the option will contain the casted value.
## When the cast fails, the option will have no value.
Chore/update nim version (#1052) * Move to version 2.0.6 * Update nim-confutils submodule to latest version * Update dependencies * Update Nim version to 2.0.12 * Add gcsafe pragma * Add missing import * Update specific conf for Nim 2.x * Fix method signatures * Revert erasure coding attempt to fix bug * More gcsafe pragma * Duplicate code from libp2p because it is not exported anymore * Fix camelcase function names * Use alreadySeen because need is not a bool anymore * newLPStreamReadError does not exist anymore so use another error * Replace ValidIpAddress by IpAddress * Add gcsafe pragma * Restore maintenance parameter deleted by mistake when removing esasure coding fix attempt code * Update method signatures * Copy LPStreamReadError code from libp2p which was removed * Fix camel case * Fix enums in tests * Fix camel case * Extract node components to a variable to make Nim 2 happy * Update the tests using ValidIpAddress to IpAddress * Fix cast for value which is already an option * Set nim version to 2.0.x for CI * Set nim version to 2.0.x for CI * Move to miniupnp version 2.2.4 to avoid symlink error * Set core.symlinks to false for Windows for miniupnp >= 2.2.5 support * Update to Nim 2.0.14 * Update CI nim versions to 2.0.14 * Try with GCC 14 * Replace apt-fast by apt-get * Update ubuntu runner to latest * Use Ubuntu 20.04 for coverage * Disable CI cache for coverage * Add coverage property description * Remove commented test * Check the node value of seen instead of using alreadySeen * Fix the merge. The taskpool work was reverted. * Update nim-ethers submodule * Remove deprecated ValidIpAddress. Fix missing case and imports. * Fix a weird issue where nim-confutils cannot find NatAny * Fix tests and remove useless static keyword
2025-01-10 15:12:37 +01:00
# In Nim 2.0.x, check 42.some as int == none(int)
# Maybe because some 42.some looks like Option[Option[int]]
# So we check first that the value is an option of the expected type.
# In that case, we do not need to do anything, just return the value as it is.
when value is Option[U]:
return value
when value is U:
return some value
elif value is ref object:
if value of U:
return some U(value)
Option.liftBinary `as`
# Template that wraps type with `Option[]` only if it is already not `Option` type
template WrapOption*(input: untyped): type =
when input is Option:
input
else:
Option[input]
macro createType(t: typedesc): untyped =
var objectType = getType(t)
# Work around for https://github.com/nim-lang/Nim/issues/23112
while objectType.kind == nnkBracketExpr and objectType[0].eqIdent"typeDesc":
objectType = getType(objectType[1])
expectKind(objectType, NimNodeKind.nnkObjectTy)
var fields = nnkRecList.newTree()
# Generates the list of fields that are wrapped in `Option[T]`.
# Technically wrapped with `WrapOption` which is template used to prevent
# re-wrapping already filed which is `Option[T]`.
for field in objectType[2]:
let fieldType = getTypeInst(field)
let newFieldNode = nnkIdentDefs.newTree(
ident($field), nnkCall.newTree(ident("WrapOption"), fieldType), newEmptyNode()
)
fields.add(newFieldNode)
# Creates new object type T with the fields lists from steps above.
let tSym = genSym(nskType, "T")
nnkStmtList.newTree(
nnkTypeSection.newTree(
nnkTypeDef.newTree(
tSym,
newEmptyNode(),
nnkObjectTy.newTree(newEmptyNode(), newEmptyNode(), fields),
)
),
tSym,
)
template Optionalize*(t: typed): untyped =
## Takes object type and wraps all the first level fields into
## Option type unless it is already Option type.
createType(t)