Arrays now marshalled to native types and other params are prefetched

This commit is contained in:
coffeepots 2018-04-24 17:37:01 +01:00 committed by zah
parent 4acd6b3ee6
commit c48167a1cc

View File

@ -81,6 +81,15 @@ macro multiRemove(s: string, values: varargs[string]): untyped =
body.add multiReplaceCall body.add multiReplaceCall
result = newBlockStmt(body) result = newBlockStmt(body)
proc jsonGetFunc(paramType: string): NimNode =
case paramType
of "string": result = ident"getStr"
of "int": result = ident"getInt"
of "float": result = ident"getFloat"
of "bool": result = ident"getBool"
of "byte": result = ident"getInt"
else: result = nil
macro on*(server: var RpcServer, path: string, body: untyped): untyped = macro on*(server: var RpcServer, path: string, body: untyped): untyped =
var paramTemplates = newStmtList() var paramTemplates = newStmtList()
let parameters = body.findChild(it.kind == nnkFormalParams) let parameters = body.findChild(it.kind == nnkFormalParams)
@ -90,29 +99,49 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped =
if resType.kind != nnkEmpty: if resType.kind != nnkEmpty:
# TODO: transform result type and/or return to json # TODO: transform result type and/or return to json
discard discard
#
var paramsIdent = ident"params"
for i in 1..<parameters.len: for i in 1..<parameters.len:
let pos = i - 1 # first index is return type
parameters[i].expectKind nnkIdentDefs parameters[i].expectKind nnkIdentDefs
#
let # take user's parameter name for template
name = parameters[i][0] # take user's parameter name for template let name = parameters[i][0]
paramType = parameters[i][1] var paramType = parameters[i][1]
var getFuncName: string
case $paramType # TODO: Object marshalling
of "string": getFuncName = "getStr"
of "int": getFuncName = "getInt" if paramType.kind == nnkBracketExpr:
of "float": getFuncName = "getFloat" # process array parameters
of "bool": getFuncName = "getBool" assert $paramType[0] == "array"
# TODO: array, object paramType.expectLen 3
else: discard let
# fetch parameter arrayType = paramType[2]
let arrayLen = paramType[1]
getFunc = ident(getFuncName) getFunc = jsonGetFunc($arrayType)
pos = i - 1 # first index is return type idx = ident"i"
paramsIdent = ident"params" # marshall json array to requested types
paramTemplates.add(quote do: # TODO: Replace length exception with async error return value
template `name`: `paramType` = `paramsIdent`.elems[`pos`].`getFunc` # We would need to pass the server in parameters to access the socket
) paramTemplates.add(quote do:
var `name`: `paramType`
block:
if `paramsIdent`.len > `name`.len:
raise newException(ValueError, "Array longer than parameter allows. Expected " & $`arrayLen` & ", data length is " & $`paramsIdent`.len)
else:
for `idx` in 0 ..< `paramsIdent`.len:
`name`[`idx`] = `arrayType`(`paramsIdent`.elems[`idx`].`getFunc`)
)
else:
# other types
var getFuncName = jsonGetFunc($paramType)
assert getFuncName != nil
# fetch parameter
let getFunc = newIdentNode($getFuncName)
paramTemplates.add(quote do:
var `name`: `paramType` = `paramsIdent`.elems[`pos`].`getFunc`
)
# create RPC proc # create RPC proc
let let
@ -132,16 +161,24 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped =
when isMainModule: when isMainModule:
import unittest import unittest
var s = newRpcServer("localhost") var s = newRpcServer("localhost")
s.on("the/path") do(a: int, b: string): s.on("the/path1"):
var node = %"test"
result = node
s.on("the/path2") do() -> int:
echo "hello2"
s.on("the/path3"):
echo "hello3" echo "hello3"
result = %1 result = %1
s.on("the/path2") do() -> int:
echo "hello2"
s.on("the/path3") do(a: int, b: string):
var node = %"test"
result = node
s.on("the/path4") do(arr: array[6, byte], b: string):
var res = newJArray()
for item in arr:
res.add %int(item)
result = res
suite "Server types": suite "Server types":
test "On macro registration": test "On macro registration":
check s.procs.hasKey("the/path") check s.procs.hasKey("the/path1")
check s.procs.hasKey("the/path2") check s.procs.hasKey("the/path2")
check s.procs.hasKey("the/path3") check s.procs.hasKey("the/path3")
test "Processing arrays":
let r = waitfor thepath4(%[1, 2, 3])
check r == %[1, 2, 3, 0, 0, 0]