mirror of
https://github.com/logos-storage/nim-json-rpc.git
synced 2026-08-03 13:43:15 +00:00
Reworked seq/array parameter construction
This commit is contained in:
parent
0ff11d4598
commit
a4214de67c
@ -92,18 +92,24 @@ proc jsonGetFunc(paramType: string): NimNode =
|
|||||||
|
|
||||||
macro on*(server: var RpcServer, path: string, body: untyped): untyped =
|
macro on*(server: var RpcServer, path: string, body: untyped): untyped =
|
||||||
var
|
var
|
||||||
paramTemplates = newStmtList()
|
paramFetch = newStmtList()
|
||||||
expectedParams = 0
|
expectedParams = 0
|
||||||
let parameters = body.findChild(it.kind == nnkFormalParams)
|
let parameters = body.findChild(it.kind == nnkFormalParams)
|
||||||
if not parameters.isNil:
|
if not parameters.isNil:
|
||||||
# process parameters of body into json fetch templates
|
# process parameters of body into json fetch templates
|
||||||
var resType = parameters[0]
|
var resType = parameters[0]
|
||||||
|
|
||||||
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"
|
var paramsIdent = ident"params"
|
||||||
expectedParams = parameters.len - 1
|
expectedParams = parameters.len - 1
|
||||||
|
let expectedStr = "Expected " & $`expectedParams` & " Json parameter(s) but got "
|
||||||
|
paramFetch.add(quote do:
|
||||||
|
if `paramsIdent`.len != `expectedParams`:
|
||||||
|
raise newException(ValueError, `expectedStr` & $`paramsIdent`.len)
|
||||||
|
)
|
||||||
|
|
||||||
for i in 1..<parameters.len:
|
for i in 1..<parameters.len:
|
||||||
let pos = i - 1 # first index is return type
|
let pos = i - 1 # first index is return type
|
||||||
@ -112,10 +118,6 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped =
|
|||||||
# take user's parameter name for template
|
# take user's parameter name for template
|
||||||
let name = parameters[i][0]
|
let name = parameters[i][0]
|
||||||
var paramType = parameters[i][1]
|
var paramType = parameters[i][1]
|
||||||
paramTemplates.add(quote do:
|
|
||||||
if `paramsIdent`.len != `expectedParams`:
|
|
||||||
raise newException(ValueError, "Expected " & $`expectedParams` & " Json parameters but got " & $`paramsIdent`.len)
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: marshalling for object types
|
# TODO: marshalling for object types
|
||||||
# TODO: Replace exception with async error return values
|
# TODO: Replace exception with async error return values
|
||||||
@ -123,47 +125,60 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped =
|
|||||||
|
|
||||||
if paramType.kind == nnkBracketExpr:
|
if paramType.kind == nnkBracketExpr:
|
||||||
# process array and seq parameters
|
# process array and seq parameters
|
||||||
# and marshall json arrays to requested types
|
# and marshal json arrays to native types
|
||||||
let paramTypeStr = $paramType[0]
|
let paramTypeStr = $paramType[0]
|
||||||
assert paramTypeStr == "array" or paramTypeStr == "seq"
|
assert paramTypeStr == "array" or paramTypeStr == "seq"
|
||||||
|
|
||||||
let idx = ident"i"
|
type ListFormat = enum ltArray, ltSeq
|
||||||
|
let listFormat = if paramTypeStr == "array": ltArray else: ltSeq
|
||||||
|
|
||||||
if paramTypeStr == "array":
|
if listFormat == ltArray: paramType.expectLen 3 else: paramType.expectLen 2
|
||||||
paramType.expectLen 3
|
|
||||||
let arrayLen = paramType[1]
|
|
||||||
let arrayType = paramType[2]
|
|
||||||
let getFunc = jsonGetFunc($arrayType)
|
|
||||||
|
|
||||||
paramTemplates.add(quote do:
|
var
|
||||||
if `paramsIdent`.elems[`pos`].kind != JArray:
|
listType: NimNode
|
||||||
raise newException(ValueError, "Expected array but got " & $`paramsIdent`.elems[`pos`].kind)
|
checks = newStmtList()
|
||||||
|
varDecl: NimNode
|
||||||
|
# always include check for array type
|
||||||
|
checks.add quote do:
|
||||||
|
if `paramsIdent`.elems[`pos`].kind != JArray:
|
||||||
|
raise newException(ValueError, "Expected " & `paramTypeStr` & " but got " & $`paramsIdent`.elems[`pos`].kind)
|
||||||
|
|
||||||
|
case listFormat
|
||||||
|
of ltArray:
|
||||||
|
let arrayLenStr = paramType[1].repr
|
||||||
|
listType = paramType[2]
|
||||||
|
varDecl = quote do:
|
||||||
var `name`: `paramType`
|
var `name`: `paramType`
|
||||||
if `paramsIdent`.len > `name`.len:
|
# arrays can only be up to the defined length
|
||||||
raise newException(ValueError, "Array longer than parameter allows. Expected " & $`arrayLen` & ", data length is " & $`paramsIdent`.elems[`pos`].len)
|
# note that passing smaller arrays is still valid and are padded with zeros
|
||||||
else:
|
checks.add(quote do:
|
||||||
for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len:
|
if `paramsIdent`.elems[`pos`].len > `name`.len:
|
||||||
`name`[`idx`] = `arrayType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`)
|
raise newException(ValueError, "Provided array is longer than parameter allows. Expected " & `arrayLenStr` & ", data length is " & $`paramsIdent`.elems[`pos`].len)
|
||||||
)
|
)
|
||||||
else:
|
of ltSeq:
|
||||||
paramType.expectLen 2
|
listType = paramType[1]
|
||||||
let
|
varDecl = quote do:
|
||||||
seqType = paramType[1]
|
var `name` = newSeq[`listType`](`paramsIdent`.elems[`pos`].len)
|
||||||
getFunc = jsonGetFunc($seqType)
|
|
||||||
paramTemplates.add(quote do:
|
let
|
||||||
if `paramsIdent`.elems[`pos`].kind != JArray:
|
getFunc = jsonGetFunc($listType)
|
||||||
raise newException(ValueError, "Expected array but got " & $`paramsIdent`.elems[`pos`].kind)
|
idx = ident"i"
|
||||||
var `name` = newSeq[`seqType`](`paramsIdent`.elems[`pos`].len)
|
listParse = quote do:
|
||||||
for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len:
|
for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len:
|
||||||
`name`[`idx`] = `seqType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`)
|
`name`[`idx`] = `listType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`)
|
||||||
)
|
# assemble fetch parameters code
|
||||||
|
paramFetch.add(quote do:
|
||||||
|
`varDecl`
|
||||||
|
`checks`
|
||||||
|
`listParse`
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# other types
|
# other types
|
||||||
var getFuncName = jsonGetFunc($paramType)
|
var getFuncName = jsonGetFunc($paramType)
|
||||||
assert getFuncName != nil
|
assert getFuncName != nil
|
||||||
# fetch parameter
|
# fetch parameter
|
||||||
let getFunc = newIdentNode($getFuncName)
|
let getFunc = newIdentNode($getFuncName)
|
||||||
paramTemplates.add(quote do:
|
paramFetch.add(quote do:
|
||||||
var `name`: `paramType` = `paramsIdent`.elems[`pos`].`getFunc`
|
var `name`: `paramType` = `paramsIdent`.elems[`pos`].`getFunc`
|
||||||
)
|
)
|
||||||
# create RPC proc
|
# create RPC proc
|
||||||
@ -185,7 +200,7 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped =
|
|||||||
result = quote do:
|
result = quote do:
|
||||||
proc `procName`*(`paramsIdent`: JsonNode): Future[JsonNode] {.async.} =
|
proc `procName`*(`paramsIdent`: JsonNode): Future[JsonNode] {.async.} =
|
||||||
`checkTypeError`
|
`checkTypeError`
|
||||||
`paramTemplates`
|
`paramFetch`
|
||||||
`procBody`
|
`procBody`
|
||||||
`server`.register(`path`, `procName`)
|
`server`.register(`path`, `procName`)
|
||||||
echo result.repr
|
echo result.repr
|
||||||
@ -201,7 +216,7 @@ when isMainModule:
|
|||||||
s.on("the/path3") do(a: int, b: string):
|
s.on("the/path3") do(a: int, b: string):
|
||||||
var node = %"test"
|
var node = %"test"
|
||||||
result = node
|
result = node
|
||||||
s.on("the/path4") do(arr: array[6, byte], b: string):
|
s.on("the/path4") do(arr: array[0..5, byte], b: string):
|
||||||
var res = newJArray()
|
var res = newJArray()
|
||||||
for item in arr:
|
for item in arr:
|
||||||
res.add %int(item)
|
res.add %int(item)
|
||||||
@ -228,4 +243,7 @@ when isMainModule:
|
|||||||
var ckR2 = %["abc"]
|
var ckR2 = %["abc"]
|
||||||
for i in 0..4: ckR2.add %(i + 1)
|
for i in 0..4: ckR2.add %(i + 1)
|
||||||
check r2 == ckR2
|
check r2 == ckR2
|
||||||
|
test "Runtime errors":
|
||||||
|
expect ValueError:
|
||||||
|
let r1 = waitfor thepath4(%[%[1, 2, 3, 4, 5, 6, 7, 8, 9, 0], %"hello"])
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user