From 1be7c939636d55d80454fd743b6408a131131fe8 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Tue, 16 Oct 2018 02:09:11 +0300 Subject: [PATCH] Add rlpFieldsCount helper and the ability to read objects not wrapped in lists --- rlp.nim | 5 ++++- rlp/object_serialization.nim | 11 +++++++++++ rlp/writer.nim | 19 +++++++------------ tests/test_object_serialization.nim | 6 ++++++ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/rlp.nim b/rlp.nim index 8221f61..5a6e244 100644 --- a/rlp.nim +++ b/rlp.nim @@ -354,7 +354,7 @@ proc readImpl[E](rlp: var Rlp, T: type openarray[E]): seq[E] = result = readImpl(rlp, seq[E]) proc readImpl(rlp: var Rlp, T: type[object|tuple], - wrappedInList = wrapObjectsInList): T = + wrappedInList = wrapObjsInList): T = mixin enumerateRlpFields, read if wrappedInList: @@ -391,6 +391,9 @@ proc toNodes*(self: var Rlp): RlpNode = template read*(rlp: var Rlp, T: type): auto = readImpl(rlp, T) +template readRecordType*(rlp: var Rlp, T: type, wrappedInList: bool): auto = + readImpl(rlp, T, wrappedInList) + proc decode*(bytes: openarray[byte]): RlpNode = var bytesCopy = @bytes diff --git a/rlp/object_serialization.nim b/rlp/object_serialization.nim index 37d3611..e98f01e 100644 --- a/rlp/object_serialization.nim +++ b/rlp/object_serialization.nim @@ -18,6 +18,17 @@ template enumerateRlpFields*[T](x: T, op: untyped) = when not hasCustomPragma(f, rlpIgnore): op(f) +proc rlpFieldsCount*(T: type): int = + mixin enumerateRlpFields + + proc helper: int = + var dummy: T + template countFields(x) = inc result + enumerateRlpFields(dummy, countFields) + + const res = helper() + return res + macro rlpFields*(T: typedesc, fields: varargs[untyped]): untyped = var body = newStmtList() let diff --git a/rlp/writer.nim b/rlp/writer.nim index 90e7566..e74c3c1 100644 --- a/rlp/writer.nim +++ b/rlp/writer.nim @@ -32,7 +32,7 @@ type Integer* = SomeInteger # or IntLike const - wrapObjectsInList* = true + wrapObjsInList* = true proc bytesNeeded(num: Integer): int = type IntType = type(num) @@ -214,16 +214,11 @@ proc appendImpl[T](self; listOrBlob: openarray[T]) = for i in 0 ..< listOrBlob.len: self.append listOrBlob[i] -proc appendTupleOrObject(self; obj: object|tuple, wrapInList: bool) = +proc appendRecordType*(self; obj: object|tuple, wrapInList = wrapObjsInList) = mixin enumerateRlpFields, append - const wrapInList = wrapObjectsInList - if wrapInList: - var fieldsCount = 0 - template countFields(x) = inc fieldsCount - enumerateRlpFields(obj, countFields) - self.startList(fieldsCount) + self.startList(static obj.type.rlpFieldsCount) template op(field) = when hasCustomPragma(field, rlpCustomSerialization): @@ -233,16 +228,16 @@ proc appendTupleOrObject(self; obj: object|tuple, wrapInList: bool) = enumerateRlpFields(obj, op) -proc appendImpl(self; data: object, wrapInList = wrapObjectsInList) {.inline.} = +proc appendImpl(self; data: object) {.inline.} = # TODO: This append proc should be overloaded by `BytesRange` after # nim bug #7416 is fixed. when data is BytesRange: self.appendBytesRange(data) else: - self.appendTupleOrObject(data, wrapInList) + self.appendRecordType(data) -proc appendImpl(self; data: tuple, wrapInList = wrapObjectsInList) {.inline.} = - self.appendTupleOrObject(data, wrapInList) +proc appendImpl(self; data: tuple) {.inline.} = + self.appendRecordType(data) # We define a single `append` template with a pretty low specifity # score in order to facilitate easier overloading with user types: diff --git a/tests/test_object_serialization.nim b/tests/test_object_serialization.nim index 12d343e..33c4606 100644 --- a/tests/test_object_serialization.nim +++ b/tests/test_object_serialization.nim @@ -74,3 +74,9 @@ test "custom field serialization": origVal.customFoo.y.len == restored.customFoo.y.len restored.ignored == 10 +test "RLP fields count": + check: + Bar.rlpFieldsCount == 2 + Foo.rlpFieldsCount == 3 + Transaction.rlpFieldsCount == 3 +