2023-05-26 12:41:13 +00:00
|
|
|
# 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:
|
2023-07-31 21:07:48 +00:00
|
|
|
error("Unexpected enum node for deserialization: " & $f.kind)
|
2023-05-26 12:41:13 +00:00
|
|
|
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
|