nim-eth/eth/rlp/object_serialization.nim
andri lim 91b2b9d2ed
rlp codec support optional fields (#613)
Instead of patching BlockHeader or BlockBody codec
each time it get additional optional fields,
this PR make the rlp codec automatically handle
optional fields. Thus rlp codec overloading of
EthBlock, BlockHeader, and BlockBody can be removed.
2023-05-30 16:02:02 +03:00

44 lines
1.2 KiB
Nim

import
stew/shims/macros
template rlpIgnore* {.pragma.}
## Specifies that a certain field should be ignored for the purposes
## of RLP serialization
template rlpCustomSerialization* {.pragma.}
## This pragma can be applied to a record field to enable the
## use of custom `read` and `append` overloads that also take
## a reference to the object holding the field.
template enumerateRlpFields*[T](x: T, op: untyped) =
type RecordType = type x
for fieldName, field in fieldPairs(x):
when not hasCustomPragmaFixed(RecordType, fieldName, rlpIgnore):
op(RecordType, fieldName, field)
proc rlpFieldsCount*(T: type): int =
mixin enumerateRlpFields
proc helper: int =
var dummy: T
template countFields(RT, n, x) = inc result
enumerateRlpFields(dummy, countFields)
const res = helper()
return res
macro rlpFields*(T: typedesc, fields: varargs[untyped]): untyped =
var body = newStmtList()
let
ins = genSym(nskParam, "instance")
op = genSym(nskParam, "op")
for field in fields:
let fieldName = $field
body.add quote do: `op`(`T`, `fieldName`, `ins`.`field`)
result = quote do:
template enumerateRlpFields*(`ins`: `T`, `op`: untyped) {.inject.} =
`body`