From a4214de67cd394cbdd43cb5f4bca1d6dee6a67a8 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 25 Apr 2018 19:18:42 +0100 Subject: [PATCH] Reworked seq/array parameter construction --- eth-rpc/server/servertypes.nim | 92 ++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/eth-rpc/server/servertypes.nim b/eth-rpc/server/servertypes.nim index d08ea3b..92d921e 100644 --- a/eth-rpc/server/servertypes.nim +++ b/eth-rpc/server/servertypes.nim @@ -92,18 +92,24 @@ proc jsonGetFunc(paramType: string): NimNode = macro on*(server: var RpcServer, path: string, body: untyped): untyped = var - paramTemplates = newStmtList() + paramFetch = newStmtList() expectedParams = 0 let parameters = body.findChild(it.kind == nnkFormalParams) if not parameters.isNil: # process parameters of body into json fetch templates var resType = parameters[0] + if resType.kind != nnkEmpty: # TODO: transform result type and/or return to json discard var paramsIdent = ident"params" 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.. `name`.len: - raise newException(ValueError, "Array longer than parameter allows. Expected " & $`arrayLen` & ", data length is " & $`paramsIdent`.elems[`pos`].len) - else: - for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len: - `name`[`idx`] = `arrayType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`) - ) - else: - paramType.expectLen 2 - let - seqType = paramType[1] - getFunc = jsonGetFunc($seqType) - paramTemplates.add(quote do: - if `paramsIdent`.elems[`pos`].kind != JArray: - raise newException(ValueError, "Expected array but got " & $`paramsIdent`.elems[`pos`].kind) - var `name` = newSeq[`seqType`](`paramsIdent`.elems[`pos`].len) - for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len: - `name`[`idx`] = `seqType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`) + # arrays can only be up to the defined length + # note that passing smaller arrays is still valid and are padded with zeros + checks.add(quote do: + if `paramsIdent`.elems[`pos`].len > `name`.len: + raise newException(ValueError, "Provided array is longer than parameter allows. Expected " & `arrayLenStr` & ", data length is " & $`paramsIdent`.elems[`pos`].len) ) + of ltSeq: + listType = paramType[1] + varDecl = quote do: + var `name` = newSeq[`listType`](`paramsIdent`.elems[`pos`].len) + + let + getFunc = jsonGetFunc($listType) + idx = ident"i" + listParse = quote do: + for `idx` in 0 ..< `paramsIdent`.elems[`pos`].len: + `name`[`idx`] = `listType`(`paramsIdent`.elems[`pos`].elems[`idx`].`getFunc`) + # assemble fetch parameters code + paramFetch.add(quote do: + `varDecl` + `checks` + `listParse` + ) else: # other types var getFuncName = jsonGetFunc($paramType) assert getFuncName != nil # fetch parameter let getFunc = newIdentNode($getFuncName) - paramTemplates.add(quote do: + paramFetch.add(quote do: var `name`: `paramType` = `paramsIdent`.elems[`pos`].`getFunc` ) # create RPC proc @@ -185,7 +200,7 @@ macro on*(server: var RpcServer, path: string, body: untyped): untyped = result = quote do: proc `procName`*(`paramsIdent`: JsonNode): Future[JsonNode] {.async.} = `checkTypeError` - `paramTemplates` + `paramFetch` `procBody` `server`.register(`path`, `procName`) echo result.repr @@ -201,7 +216,7 @@ when isMainModule: 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): + s.on("the/path4") do(arr: array[0..5, byte], b: string): var res = newJArray() for item in arr: res.add %int(item) @@ -228,4 +243,7 @@ when isMainModule: var ckR2 = %["abc"] for i in 0..4: ckR2.add %(i + 1) check r2 == ckR2 + test "Runtime errors": + expect ValueError: + let r1 = waitfor thepath4(%[%[1, 2, 3, 4, 5, 6, 7, 8, 9, 0], %"hello"]) \ No newline at end of file