2023-05-30 13:02:02 +00:00
|
|
|
import
|
|
|
|
stew/shims/macros
|
2019-02-05 12:01:10 +00:00
|
|
|
|
|
|
|
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) =
|
2024-02-13 12:34:27 +00:00
|
|
|
type RecordType {.used.} = type x
|
2023-05-30 13:02:02 +00:00
|
|
|
for fieldName, field in fieldPairs(x):
|
|
|
|
when not hasCustomPragmaFixed(RecordType, fieldName, rlpIgnore):
|
|
|
|
op(RecordType, fieldName, field)
|
2019-02-05 12:01:10 +00:00
|
|
|
|
|
|
|
proc rlpFieldsCount*(T: type): int =
|
|
|
|
mixin enumerateRlpFields
|
|
|
|
|
|
|
|
proc helper: int =
|
|
|
|
var dummy: T
|
2024-02-13 12:34:27 +00:00
|
|
|
template countFields(RT, n, x) {.used.} = inc result
|
2019-02-05 12:01:10 +00:00
|
|
|
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:
|
2023-05-30 13:02:02 +00:00
|
|
|
let fieldName = $field
|
|
|
|
body.add quote do: `op`(`T`, `fieldName`, `ins`.`field`)
|
2019-02-05 12:01:10 +00:00
|
|
|
|
|
|
|
result = quote do:
|
|
|
|
template enumerateRlpFields*(`ins`: `T`, `op`: untyped) {.inject.} =
|
|
|
|
`body`
|
|
|
|
|