nim-stew/stew/enums.nim

57 lines
1.6 KiB
Nim

# stew
# Copyright 2023 Status Research & Development GmbH
# Licensed under either of
#
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import std/[macros, options]
type EnumStyle* {.pure.} = enum
Numeric,
AssociatedStrings
func setMode(style: var Option[EnumStyle], s: EnumStyle, typ: auto) =
if style.isNone:
style = some s
elif style.get != s:
error("Mixed enum styles not supported for deserialization: " & $typ)
else:
discard
macro enumStyle*(t: typedesc[enum]): untyped =
let
typ = t.getTypeInst[1]
impl = typ.getImpl[2]
expectKind impl, nnkEnumTy
var style: Option[EnumStyle]
for f in impl:
case f.kind
of nnkEmpty:
continue
of nnkIdent:
error("Unexpected enum node for deserialization: " & $f.kind)
of nnkSym:
style.setMode(EnumStyle.Numeric, typ)
of nnkEnumFieldDef:
case f[1].kind
of nnkIntLit:
style.setMode(EnumStyle.Numeric, typ)
of nnkStrLit:
style.setMode(EnumStyle.AssociatedStrings, typ)
else: error("Unexpected enum tuple for deserialization: " & $f[1].kind)
else: error("Unexpected enum node for deserialization: " & $f.kind)
if style.isNone:
error("Cannot determine enum style for deserialization: " & $typ)
case style.get
of EnumStyle.Numeric:
quote do:
EnumStyle.Numeric
of EnumStyle.AssociatedStrings:
quote do:
EnumStyle.AssociatedStrings