mirror of https://github.com/status-im/nim-eth.git
Changes related to the new ETH interop spec
* RPC requests and responses with a single parameter are now inlined
This commit is contained in:
parent
98be627bcc
commit
14e99e0711
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
options,
|
options, sequtils,
|
||||||
stew/shims/macros, chronos, faststreams/output_stream
|
stew/shims/macros, chronos, faststreams/output_stream
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -15,7 +15,8 @@ type
|
||||||
kind*: MessageKind
|
kind*: MessageKind
|
||||||
procDef*: NimNode
|
procDef*: NimNode
|
||||||
timeoutParam*: NimNode
|
timeoutParam*: NimNode
|
||||||
recIdent*: NimNode
|
recName*: NimNode
|
||||||
|
strongRecName*: NimNode
|
||||||
recBody*: NimNode
|
recBody*: NimNode
|
||||||
protocol*: P2PProtocol
|
protocol*: P2PProtocol
|
||||||
response*: Message
|
response*: Message
|
||||||
|
@ -346,7 +347,7 @@ proc hasReqId*(msg: Message): bool =
|
||||||
proc ResponderType(msg: Message): NimNode =
|
proc ResponderType(msg: Message): NimNode =
|
||||||
var resp = if msg.kind == msgRequest: msg.response else: msg
|
var resp = if msg.kind == msgRequest: msg.response else: msg
|
||||||
newTree(nnkBracketExpr,
|
newTree(nnkBracketExpr,
|
||||||
msg.protocol.backend.ResponderType, resp.recIdent)
|
msg.protocol.backend.ResponderType, resp.recName)
|
||||||
|
|
||||||
proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
|
proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
|
||||||
procDef: NimNode, timeoutParam: NimNode = nil,
|
procDef: NimNode, timeoutParam: NimNode = nil,
|
||||||
|
@ -361,18 +362,35 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
|
||||||
msgName = $msgIdent
|
msgName = $msgIdent
|
||||||
recFields = newTree(nnkRecList)
|
recFields = newTree(nnkRecList)
|
||||||
recBody = newTree(nnkObjectTy, newEmptyNode(), newEmptyNode(), recFields)
|
recBody = newTree(nnkObjectTy, newEmptyNode(), newEmptyNode(), recFields)
|
||||||
recName = ident(msgName & "Obj")
|
strongRecName = ident(msgName & "Obj")
|
||||||
|
recName = strongRecName
|
||||||
|
|
||||||
for param, paramType in procDef.typedParams(skip = 1):
|
for param, paramType in procDef.typedParams(skip = 1):
|
||||||
recFields.add newTree(nnkIdentDefs,
|
recFields.add newTree(nnkIdentDefs,
|
||||||
newTree(nnkPostfix, ident("*"), param), # The fields are public
|
newTree(nnkPostfix, ident("*"), param), # The fields are public
|
||||||
chooseFieldType(paramType), # some types such as openarray
|
chooseFieldType(paramType), # some types such as openarray
|
||||||
# are automatically remapped
|
newEmptyNode()) # are automatically remapped
|
||||||
newEmptyNode())
|
|
||||||
|
|
||||||
result = Message(protocol: protocol, id: id, ident: msgIdent, kind: kind,
|
if recFields.len == 1:
|
||||||
procDef: procDef, recIdent: recName, recBody: recBody,
|
# When we have a single parameter, it's treated as the transferred message
|
||||||
timeoutParam: timeoutParam, response: response)
|
# type. `recName` will be resolved to the message type that's intended
|
||||||
|
# for serialization while `strongRecName` will be a distinct type over
|
||||||
|
# which overloads such as `msgId` can be defined. We must use a distinct
|
||||||
|
# type because otherwise Nim may see multiple overloads defined over the
|
||||||
|
# same request parameter type and this will be an ambiguity error.
|
||||||
|
recName = recFields[0][1]
|
||||||
|
recBody = newTree(nnkDistinctTy, recName)
|
||||||
|
|
||||||
|
result = Message(protocol: protocol,
|
||||||
|
id: id,
|
||||||
|
ident: msgIdent,
|
||||||
|
kind: kind,
|
||||||
|
procDef: procDef,
|
||||||
|
recName: recName,
|
||||||
|
strongRecName: strongRecName,
|
||||||
|
recBody: recBody,
|
||||||
|
timeoutParam: timeoutParam,
|
||||||
|
response: response)
|
||||||
|
|
||||||
if procDef.body.kind != nnkEmpty:
|
if procDef.body.kind != nnkEmpty:
|
||||||
var userHandler = copy procDef
|
var userHandler = copy procDef
|
||||||
|
@ -482,9 +500,9 @@ proc createSendProc*(msg: Message,
|
||||||
def[3][0] = if procType == nnkMacroDef:
|
def[3][0] = if procType == nnkMacroDef:
|
||||||
ident "untyped"
|
ident "untyped"
|
||||||
elif msg.kind == msgRequest and not isRawSender:
|
elif msg.kind == msgRequest and not isRawSender:
|
||||||
Fut(Opt(msg.response.recIdent))
|
Fut(Opt(msg.response.recName))
|
||||||
elif msg.kind == msgHandshake and not isRawSender:
|
elif msg.kind == msgHandshake and not isRawSender:
|
||||||
Fut(msg.recIdent)
|
Fut(msg.recName)
|
||||||
else:
|
else:
|
||||||
Fut(Void)
|
Fut(Void)
|
||||||
|
|
||||||
|
@ -518,13 +536,20 @@ proc writeParamsAsRecord*(params: openarray[NimNode],
|
||||||
writer, recordWriterCtx,
|
writer, recordWriterCtx,
|
||||||
newLit($param), param)
|
newLit($param), param)
|
||||||
|
|
||||||
result = quote do:
|
if params.len > 1:
|
||||||
mixin init, writerType, beginRecord, endRecord
|
result = quote do:
|
||||||
|
mixin init, writerType, beginRecord, endRecord
|
||||||
|
|
||||||
var `writer` = init(WriterType(`Format`), `outputStream`)
|
var `writer` = init(WriterType(`Format`), `outputStream`)
|
||||||
var `recordWriterCtx` = beginRecord(`writer`, `RecordType`)
|
var `recordWriterCtx` = beginRecord(`writer`, `RecordType`)
|
||||||
`appendParams`
|
`appendParams`
|
||||||
endRecord(`writer`, `recordWriterCtx`)
|
endRecord(`writer`, `recordWriterCtx`)
|
||||||
|
else:
|
||||||
|
let param = params[0]
|
||||||
|
|
||||||
|
result = quote do:
|
||||||
|
var `writer` = init(WriterType(`Format`), `outputStream`)
|
||||||
|
writeValue(`writer`, `param`)
|
||||||
|
|
||||||
proc useStandardBody*(sendProc: SendProc,
|
proc useStandardBody*(sendProc: SendProc,
|
||||||
preSerializationStep: proc(stream: NimNode): NimNode,
|
preSerializationStep: proc(stream: NimNode): NimNode,
|
||||||
|
@ -537,7 +562,7 @@ proc useStandardBody*(sendProc: SendProc,
|
||||||
|
|
||||||
initFuture = bindSym "initFuture"
|
initFuture = bindSym "initFuture"
|
||||||
recipient = sendProc.peerParam
|
recipient = sendProc.peerParam
|
||||||
msgRecName = msg.recIdent
|
msgRecName = msg.recName
|
||||||
Format = msg.protocol.backend.SerializationFormat
|
Format = msg.protocol.backend.SerializationFormat
|
||||||
|
|
||||||
preSerialization = if preSerializationStep.isNil: newStmtList()
|
preSerialization = if preSerializationStep.isNil: newStmtList()
|
||||||
|
@ -591,7 +616,7 @@ proc createSerializer*(msg: Message, procType = nnkProcDef): NimNode =
|
||||||
serializer.msgParams,
|
serializer.msgParams,
|
||||||
streamVar,
|
streamVar,
|
||||||
msg.protocol.backend.SerializationFormat,
|
msg.protocol.backend.SerializationFormat,
|
||||||
msg.recIdent)
|
msg.recName)
|
||||||
|
|
||||||
return serializer.def
|
return serializer.def
|
||||||
|
|
||||||
|
@ -612,10 +637,12 @@ proc genAwaitUserHandler*(msg: Message, receivedMsg: NimNode,
|
||||||
|
|
||||||
var userHandlerCall = newCall(msg.userHandler.name, leadingParams)
|
var userHandlerCall = newCall(msg.userHandler.name, leadingParams)
|
||||||
|
|
||||||
for param, paramType in msg.procDef.typedParams(skip = 1):
|
var params = toSeq(msg.procDef.typedParams(skip = 1))
|
||||||
# If there is user message handler, we'll place a call to it by
|
if params.len > 1:
|
||||||
# unpacking the fields of the received message:
|
for p in params:
|
||||||
userHandlerCall.add newDotExpr(receivedMsg, param)
|
userHandlerCall.add newDotExpr(receivedMsg, p[0])
|
||||||
|
else:
|
||||||
|
userHandlerCall.add receivedMsg
|
||||||
|
|
||||||
return newCall("await", userHandlerCall)
|
return newCall("await", userHandlerCall)
|
||||||
|
|
||||||
|
@ -646,7 +673,7 @@ proc createHandshakeTemplate*(msg: Message,
|
||||||
peerValue = forwardCall[1]
|
peerValue = forwardCall[1]
|
||||||
timeoutValue = msg.timeoutParam[0]
|
timeoutValue = msg.timeoutParam[0]
|
||||||
peerVarSym = genSym(nskLet, "peer")
|
peerVarSym = genSym(nskLet, "peer")
|
||||||
msgRecName = msg.recIdent
|
msgRecName = msg.recName
|
||||||
|
|
||||||
forwardCall[1] = peerVarSym
|
forwardCall[1] = peerVarSym
|
||||||
forwardCall.del(forwardCall.len - 1)
|
forwardCall.del(forwardCall.len - 1)
|
||||||
|
@ -771,12 +798,13 @@ proc genTypeSection*(p: P2PProtocol): NimNode =
|
||||||
let
|
let
|
||||||
msgId = msg.id
|
msgId = msg.id
|
||||||
msgName = msg.ident
|
msgName = msg.ident
|
||||||
msgRecName = msg.recIdent
|
msgRecName = msg.recName
|
||||||
|
msgStrongRecName = msg.strongRecName
|
||||||
msgRecBody = msg.recBody
|
msgRecBody = msg.recBody
|
||||||
|
|
||||||
result.add quote do:
|
result.add quote do:
|
||||||
# This is a type featuring a single field for each message param:
|
# This is a type featuring a single field for each message param:
|
||||||
type `msgRecName`* = `msgRecBody`
|
type `msgStrongRecName`* = `msgRecBody`
|
||||||
|
|
||||||
# Add a helper template for accessing the message type:
|
# Add a helper template for accessing the message type:
|
||||||
# e.g. p2p.hello:
|
# e.g. p2p.hello:
|
||||||
|
@ -784,8 +812,8 @@ proc genTypeSection*(p: P2PProtocol): NimNode =
|
||||||
|
|
||||||
# Add a helper template for obtaining the message Id for
|
# Add a helper template for obtaining the message Id for
|
||||||
# a particular message type:
|
# a particular message type:
|
||||||
template msgId*(T: type `msgRecName`): int = `msgId`
|
template msgId*(T: type `msgStrongRecName`): int = `msgId`
|
||||||
template msgProtocol*(T: type `msgRecName`): type = `protocolName`
|
template msgProtocol*(T: type `msgStrongRecName`): type = `protocolName`
|
||||||
|
|
||||||
proc genCode*(p: P2PProtocol): NimNode =
|
proc genCode*(p: P2PProtocol): NimNode =
|
||||||
# TODO: try switching to a simpler for msg in p.messages: loop
|
# TODO: try switching to a simpler for msg in p.messages: loop
|
||||||
|
|
|
@ -609,9 +609,9 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
|
||||||
msgId = msg.id
|
msgId = msg.id
|
||||||
msgIdent = msg.ident
|
msgIdent = msg.ident
|
||||||
msgName = $msgIdent
|
msgName = $msgIdent
|
||||||
msgRecName = msg.recIdent
|
msgRecName = msg.recName
|
||||||
responseMsgId = if msg.response != nil: msg.response.id else: -1
|
responseMsgId = if msg.response != nil: msg.response.id else: -1
|
||||||
ResponseRecord = if msg.response != nil: msg.response.recIdent else: nil
|
ResponseRecord = if msg.response != nil: msg.response.recName else: nil
|
||||||
hasReqId = msg.hasReqId
|
hasReqId = msg.hasReqId
|
||||||
protocol = msg.protocol
|
protocol = msg.protocol
|
||||||
userPragmas = msg.procDef.pragma
|
userPragmas = msg.procDef.pragma
|
||||||
|
|
Loading…
Reference in New Issue