mirror of https://github.com/status-im/nim-eth.git
cleanup macros
This commit is contained in:
parent
470baf82bd
commit
6a73a9d8b0
|
@ -41,7 +41,7 @@ func writeCount(bytes: var auto, count: int, baseMarker: byte) =
|
||||||
origLen = bytes.len
|
origLen = bytes.len
|
||||||
lenPrefixBytes = uint64(count).bytesNeeded
|
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[origLen] = baseMarker + (THRESHOLD_LIST_LEN - 1) + byte(lenPrefixBytes)
|
||||||
bytes.writeBigEndian(uint64(count), bytes.len - 1, 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.output.len - bytes.len, self.output.len - 1), bytes)
|
||||||
self.maybeClosePendingLists()
|
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) =
|
proc startList*(self: var RlpWriter, listSize: int) =
|
||||||
if listSize == 0:
|
if listSize == 0:
|
||||||
self.appendRawList([])
|
self.output.writeCount(0, LIST_START_MARKER)
|
||||||
|
self.appendRawBytes([])
|
||||||
else:
|
else:
|
||||||
self.pendingLists.add((listSize, self.output.len))
|
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:
|
for i in 0 ..< listOrBlob.len:
|
||||||
self.append listOrBlob[i]
|
self.append listOrBlob[i]
|
||||||
|
|
||||||
proc hasOptionalFields(T: type): bool =
|
proc countOptionalFields(T: type): int =
|
||||||
mixin enumerateRlpFields
|
mixin enumerateRlpFields
|
||||||
|
|
||||||
proc helper: bool =
|
var dummy: T
|
||||||
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]
|
|
||||||
|
|
||||||
|
# closure signature matches the one in object_serialization.nim
|
||||||
template op(RT, fN, f) =
|
template op(RT, fN, f) =
|
||||||
res[i] = f is Option or f is Opt
|
when f is Option or f is Opt:
|
||||||
inc i
|
inc result
|
||||||
|
|
||||||
enumerateRlpFields(dummy, op)
|
enumerateRlpFields(dummy, op)
|
||||||
|
|
||||||
# ignoring first optional fields
|
|
||||||
optionalFieldsNum(res) - 1
|
|
||||||
|
|
||||||
proc genPrevFields(obj: NimNode, fd: openArray[FieldDescription], hi, lo: int): NimNode =
|
proc genPrevFields(obj: NimNode, fd: openArray[FieldDescription], hi, lo: int): NimNode =
|
||||||
result = newStmtList()
|
result = newStmtList()
|
||||||
for i in countdown(hi, lo):
|
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,
|
doAssert obj.blobGasUsed.isSome == obj.excessBlobGas.isSome,
|
||||||
"blobGasUsed and excessBlobGas must both be present or absent"
|
"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 =
|
proc countFieldsRuntime(obj: object|tuple): int =
|
||||||
# count mandatory fields and non empty optional fields
|
mixin enumerateRlpFields
|
||||||
type ObjType = type obj
|
|
||||||
|
|
||||||
const
|
template op(RT, fN, f) {.used.} =
|
||||||
fieldsCount = ObjType.rlpFieldsCount
|
when f is Option or f is Opt:
|
||||||
# include first optional fields
|
if f.isSome: # if optional and non empty
|
||||||
cof = checkedOptionalFields(ObjType, fieldsCount) + 1
|
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) =
|
proc appendRecordType*(self: var RlpWriter, obj: object|tuple, wrapInList = wrapObjsInList) =
|
||||||
mixin enumerateRlpFields, append
|
mixin enumerateRlpFields, append
|
||||||
|
@ -263,25 +220,22 @@ proc appendRecordType*(self: var RlpWriter, obj: object|tuple, wrapInList = wrap
|
||||||
type ObjType = type obj
|
type ObjType = type obj
|
||||||
|
|
||||||
const
|
const
|
||||||
hasOptional = hasOptionalFields(ObjType)
|
cof = countOptionalFields(ObjType)
|
||||||
fieldsCount = ObjType.rlpFieldsCount
|
|
||||||
|
|
||||||
when hasOptional:
|
when cof > 0:
|
||||||
const
|
# ignoring first optional fields
|
||||||
cof = checkedOptionalFields(ObjType, fieldsCount)
|
genOptionalFieldsValidation(obj, ObjType, cof - 1)
|
||||||
when cof > 0:
|
|
||||||
genOptionalFieldsValidation(obj, ObjType, cof)
|
|
||||||
|
|
||||||
if wrapInList:
|
if wrapInList:
|
||||||
when hasOptional:
|
when cof > 0:
|
||||||
self.startList(obj.countFieldsRuntime)
|
self.startList(obj.countFieldsRuntime)
|
||||||
else:
|
else:
|
||||||
self.startList(fieldsCount)
|
self.startList(ObjType.rlpFieldsCount)
|
||||||
|
|
||||||
template op(RecordType, fieldName, field) {.used.} =
|
template op(RecordType, fieldName, field) {.used.} =
|
||||||
when hasCustomPragmaFixed(RecordType, fieldName, rlpCustomSerialization):
|
when hasCustomPragmaFixed(RecordType, fieldName, rlpCustomSerialization):
|
||||||
append(self, obj, field)
|
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
|
# this works for optional fields at the end of an object/tuple
|
||||||
# if the optional field is followed by a mandatory field,
|
# if the optional field is followed by a mandatory field,
|
||||||
# custom serialization for a field or for the parent object
|
# custom serialization for a field or for the parent object
|
||||||
|
|
Loading…
Reference in New Issue