From 6a73a9d8b0a98ebee78d2b33f144b3ef57f9c210 Mon Sep 17 00:00:00 2001 From: chirag-parmar Date: Thu, 24 Oct 2024 13:55:50 +0530 Subject: [PATCH] cleanup macros --- eth/rlp/writer.nim | 92 ++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/eth/rlp/writer.nim b/eth/rlp/writer.nim index e726ddc..a30959d 100644 --- a/eth/rlp/writer.nim +++ b/eth/rlp/writer.nim @@ -41,7 +41,7 @@ func writeCount(bytes: var auto, count: int, baseMarker: byte) = origLen = bytes.len lenPrefixBytes = uint64(count).bytesNeeded - bytes.setLen(origLen + int(lenPrefixBytes) + 1) + bytes.setLen(origLen + lenPrefixBytes + 1) bytes[origLen] = baseMarker + (THRESHOLD_LIST_LEN - 1) + byte(lenPrefixBytes) bytes.writeBigEndian(uint64(count), bytes.len - 1, lenPrefixBytes) @@ -104,13 +104,10 @@ proc appendRawBytes*(self: var RlpWriter, bytes: openArray[byte]) = self.output.len - bytes.len, self.output.len - 1), bytes) self.maybeClosePendingLists() -proc appendRawList(self: var RlpWriter, bytes: openArray[byte]) = - self.output.writeCount(bytes.len, LIST_START_MARKER) - self.appendRawBytes(bytes) - proc startList*(self: var RlpWriter, listSize: int) = if listSize == 0: - self.appendRawList([]) + self.output.writeCount(0, LIST_START_MARKER) + self.appendRawBytes([]) else: self.pendingLists.add((listSize, self.output.len)) @@ -159,43 +156,18 @@ proc appendImpl[T](self: var RlpWriter, listOrBlob: openArray[T]) = for i in 0 ..< listOrBlob.len: self.append listOrBlob[i] -proc hasOptionalFields(T: type): bool = +proc countOptionalFields(T: type): int = mixin enumerateRlpFields - proc helper: bool = - var dummy: T - result = false - template detectOptionalField(RT, n, x) {.used.} = - when x is Option or x is Opt: - return true - enumerateRlpFields(dummy, detectOptionalField) - - const res = helper() - return res - -proc optionalFieldsNum(x: openArray[bool]): int = - # count optional fields backward - for i in countdown(x.len-1, 0): - if x[i]: inc result - else: break - -proc checkedOptionalFields(T: type, FC: static[int]): int = - mixin enumerateRlpFields - - var - i = 0 - dummy: T - res: array[FC, bool] + var dummy: T + # closure signature matches the one in object_serialization.nim template op(RT, fN, f) = - res[i] = f is Option or f is Opt - inc i + when f is Option or f is Opt: + inc result enumerateRlpFields(dummy, op) - # ignoring first optional fields - optionalFieldsNum(res) - 1 - proc genPrevFields(obj: NimNode, fd: openArray[FieldDescription], hi, lo: int): NimNode = result = newStmtList() for i in countdown(hi, lo): @@ -230,32 +202,17 @@ macro genOptionalFieldsValidation(obj: untyped, T: type, num: static[int]): unty doAssert obj.blobGasUsed.isSome == obj.excessBlobGas.isSome, "blobGasUsed and excessBlobGas must both be present or absent" -macro countFieldsRuntimeImpl(obj: untyped, T: type, num: static[int]): untyped = - let - Tresolved = getType(T)[1] - fd = recordFields(Tresolved.getImpl) - res = ident("result") - mlen = fd.len - num - - result = newStmtList() - result.add quote do: - `res` = `mlen` - - for i in countdown(fd.high, fd.len-num): - let fieldName = fd[i].name - result.add quote do: - `res` += `obj`.`fieldName`.isSome.ord - proc countFieldsRuntime(obj: object|tuple): int = - # count mandatory fields and non empty optional fields - type ObjType = type obj + mixin enumerateRlpFields - const - fieldsCount = ObjType.rlpFieldsCount - # include first optional fields - cof = checkedOptionalFields(ObjType, fieldsCount) + 1 + template op(RT, fN, f) {.used.} = + when f is Option or f is Opt: + if f.isSome: # if optional and non empty + inc result + else: # if mandatory field + inc result - countFieldsRuntimeImpl(obj, ObjType, cof) + enumerateRlpFields(obj, op) proc appendRecordType*(self: var RlpWriter, obj: object|tuple, wrapInList = wrapObjsInList) = mixin enumerateRlpFields, append @@ -263,25 +220,22 @@ proc appendRecordType*(self: var RlpWriter, obj: object|tuple, wrapInList = wrap type ObjType = type obj const - hasOptional = hasOptionalFields(ObjType) - fieldsCount = ObjType.rlpFieldsCount + cof = countOptionalFields(ObjType) - when hasOptional: - const - cof = checkedOptionalFields(ObjType, fieldsCount) - when cof > 0: - genOptionalFieldsValidation(obj, ObjType, cof) + when cof > 0: + # ignoring first optional fields + genOptionalFieldsValidation(obj, ObjType, cof - 1) if wrapInList: - when hasOptional: + when cof > 0: self.startList(obj.countFieldsRuntime) else: - self.startList(fieldsCount) + self.startList(ObjType.rlpFieldsCount) template op(RecordType, fieldName, field) {.used.} = when hasCustomPragmaFixed(RecordType, fieldName, rlpCustomSerialization): append(self, obj, field) - elif (field is Option or field is Opt) and hasOptional: + elif (field is Option or field is Opt) and cof > 0: # this works for optional fields at the end of an object/tuple # if the optional field is followed by a mandatory field, # custom serialization for a field or for the parent object