mirror of https://github.com/status-im/nim-rlp.git
Allow specifying a custom serialization procedure for a particular field
This commit is contained in:
parent
1720345a24
commit
6556821572
6
rlp.nim
6
rlp.nim
|
@ -3,7 +3,7 @@
|
||||||
## https://ethereum.github.io/yellowpaper/paper.pdf
|
## https://ethereum.github.io/yellowpaper/paper.pdf
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, parseutils,
|
macros, strutils, parseutils,
|
||||||
rlp/[types, writer, object_serialization],
|
rlp/[types, writer, object_serialization],
|
||||||
rlp/priv/defs
|
rlp/priv/defs
|
||||||
|
|
||||||
|
@ -357,6 +357,10 @@ proc readImpl(rlp: var Rlp, T: typedesc[object|tuple],
|
||||||
rlp.position += payloadOffset
|
rlp.position += payloadOffset
|
||||||
|
|
||||||
template op(field) =
|
template op(field) =
|
||||||
|
when hasCustomPragma(field, rlpCustomSerialization):
|
||||||
|
field = rlp.read(type(field),
|
||||||
|
getCustomPragmaVal(field, rlpCustomSerialization))
|
||||||
|
else:
|
||||||
field = rlp.read(type(field))
|
field = rlp.read(type(field))
|
||||||
|
|
||||||
enumerateRlpFields(result, op)
|
enumerateRlpFields(result, op)
|
||||||
|
|
|
@ -20,3 +20,9 @@ template rlpInline* {.pragma.}
|
||||||
## This can be specified on a record field in order to avoid the
|
## This can be specified on a record field in order to avoid the
|
||||||
## default behavior of wrapping the record in a RLP list.
|
## default behavior of wrapping the record in a RLP list.
|
||||||
|
|
||||||
|
template rlpCustomSerialization*(T: typedesc) {.pragma.}
|
||||||
|
## This can be specified on a record field to trigger the use of a
|
||||||
|
## custom `read` and `append` serialization functions.
|
||||||
|
## The custom functions will be passed an additional `type` argument
|
||||||
|
## specefied in the pragma (it is used as an overload tag)
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,12 @@ proc appendTupleOrObject(self; data: object|tuple, wrapInList: bool) =
|
||||||
enumerateRlpFields(data, countFields)
|
enumerateRlpFields(data, countFields)
|
||||||
self.startList(fieldsCount)
|
self.startList(fieldsCount)
|
||||||
|
|
||||||
template op(x) = append(self, x)
|
template op(field) =
|
||||||
|
when hasCustomPragma(field, rlpCustomSerialization):
|
||||||
|
append(self, field, getCustomPragmaVal(field, rlpCustomSerialization))
|
||||||
|
else:
|
||||||
|
append(self, field)
|
||||||
|
|
||||||
enumerateRlpFields(data, op)
|
enumerateRlpFields(data, op)
|
||||||
|
|
||||||
proc appendImpl(self; data: object, wrapInList = wrapObjectsInList) {.inline.} =
|
proc appendImpl(self; data: object, wrapInList = wrapObjectsInList) {.inline.} =
|
||||||
|
|
|
@ -17,6 +17,11 @@ type
|
||||||
b: string
|
b: string
|
||||||
f: Foo
|
f: Foo
|
||||||
|
|
||||||
|
CompressedFoo = object
|
||||||
|
|
||||||
|
Bar2 = object
|
||||||
|
f {.rlpCustomSerialization: CompressedFoo}: Foo
|
||||||
|
|
||||||
rlpFields Foo,
|
rlpFields Foo,
|
||||||
x, y, z
|
x, y, z
|
||||||
|
|
||||||
|
@ -25,6 +30,14 @@ rlpFields Transaction,
|
||||||
|
|
||||||
proc default(T: typedesc): T = discard
|
proc default(T: typedesc): T = discard
|
||||||
|
|
||||||
|
proc append*(rlpWriter: var RlpWriter, f: Foo, tag: type CompressedFoo) =
|
||||||
|
rlpWriter.append(f.x)
|
||||||
|
rlpWriter.append(f.y.len)
|
||||||
|
|
||||||
|
proc read*(rlp: var Rlp, T: type Foo, tag: type CompressedFoo): Foo =
|
||||||
|
result.x = rlp.read(uint64)
|
||||||
|
result.y = newString(rlp.read(int))
|
||||||
|
|
||||||
test "encoding and decoding an object":
|
test "encoding and decoding an object":
|
||||||
var originalBar = Bar(b: "abracadabra",
|
var originalBar = Bar(b: "abracadabra",
|
||||||
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
|
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
|
||||||
|
@ -47,3 +60,13 @@ test "encoding and decoding an object":
|
||||||
t2.receiver == "Bob"
|
t2.receiver == "Bob"
|
||||||
t2.amount == 1000
|
t2.amount == 1000
|
||||||
|
|
||||||
|
test "custom field serialization":
|
||||||
|
var origVal = Bar2(f: Foo(x: 10'u64, y: "y", z: @[]))
|
||||||
|
var bytes = encode(origVal)
|
||||||
|
var r = rlpFromBytes(bytes)
|
||||||
|
var restored = r.read(Bar2)
|
||||||
|
|
||||||
|
check:
|
||||||
|
origVal.f.x == restored.f.x
|
||||||
|
origVal.f.y.len == restored.f.y.len
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue