104 lines
2.6 KiB
Nim
104 lines
2.6 KiB
Nim
#
|
|
# REST API framework implementation
|
|
# (c) Copyright 2021-Present
|
|
# Status Research & Development GmbH
|
|
#
|
|
# Licensed under either of
|
|
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
|
# MIT license (LICENSE-MIT)
|
|
import std/[macros, strutils]
|
|
|
|
proc makeProcName*(m, s: string): string =
|
|
let path =
|
|
if s.endsWith("/"):
|
|
s & m.toLowerAscii()
|
|
else:
|
|
s & "/" & m.toLowerAscii()
|
|
var res = "rest"
|
|
var k = 0
|
|
var toUpper = false
|
|
while k < len(path):
|
|
let c = path[k]
|
|
case c
|
|
of {'/', '{', '_'}:
|
|
toUpper = true
|
|
of Letters + Digits:
|
|
if toUpper:
|
|
res.add(toUpperAscii(c))
|
|
toUpper = false
|
|
else:
|
|
res.add(c)
|
|
else:
|
|
discard
|
|
inc(k, 1)
|
|
res
|
|
|
|
proc getRestReturnType*(params: NimNode): NimNode =
|
|
if not(isNil(params)) and (len(params) > 0) and not(isNil(params[0])) and
|
|
(params[0].kind in {nnkIdent, nnkSym}):
|
|
params[0]
|
|
else:
|
|
nil
|
|
|
|
iterator paramsIter*(params: NimNode): tuple[name, ntype: NimNode] =
|
|
for i in 1 ..< params.len:
|
|
let arg = params[i]
|
|
let argType = arg[^2]
|
|
for j in 0 ..< arg.len-2:
|
|
yield (arg[j], argType)
|
|
|
|
proc isKnownType*(typeNode: NimNode, typeNames: varargs[string]): bool =
|
|
typeNode.kind in {nnkIdent, nnkSym} and
|
|
$typeNode in typeNames
|
|
|
|
proc isBracketExpr(n: NimNode, nodes: varargs[string]): bool =
|
|
let leadingIdx = if n.kind == nnkBracketExpr:
|
|
0
|
|
elif n.kind == nnkCall and
|
|
n[0].kind in {nnkOpenSymChoice, nnkClosedSymChoice} and
|
|
n[0].len > 0 and
|
|
$n[0][0] == "[]":
|
|
1
|
|
else:
|
|
return false
|
|
|
|
for idx, types in nodes:
|
|
let actualIdx = leadingIdx + idx
|
|
if actualIdx > n.len:
|
|
return false
|
|
if not isKnownType(n[actualIdx], types.split("|")):
|
|
return false
|
|
|
|
return true
|
|
|
|
proc isOptionalArg*(typeNode: NimNode): bool =
|
|
typeNode.isBracketExpr "Option"
|
|
|
|
proc isBytesArg*(typeNode: NimNode): bool =
|
|
typeNode.isBracketExpr("seq", "byte|uint8")
|
|
|
|
proc isSequenceArg*(typeNode: NimNode): bool =
|
|
typeNode.isBracketExpr("seq")
|
|
|
|
proc isContentBodyArg*(typeNode: NimNode): bool =
|
|
typeNode.isBracketExpr("Option", "ContentBody")
|
|
|
|
proc isResponseArg*(typeNode: NimNode): bool =
|
|
typeNode.isKnownType "HttpResponseRef"
|
|
|
|
proc getSequenceType*(typeNode: NimNode): NimNode =
|
|
if typeNode.isBracketExpr("seq"):
|
|
typeNode[1]
|
|
else:
|
|
nil
|
|
|
|
proc getOptionType*(typeNode: NimNode): NimNode =
|
|
if typeNode.isBracketExpr("Option"):
|
|
typeNode[1]
|
|
else:
|
|
nil
|
|
|
|
proc isPathArg*(typeNode: NimNode): bool =
|
|
isBytesArg(typeNode) or (not(isOptionalArg(typeNode)) and
|
|
not(isSequenceArg(typeNode)))
|