Files
myasgi/app/subroutines/route.py
2025-04-09 16:54:34 +08:00

49 lines
1.8 KiB
Python

# / -> Exact("/")
# /foo -> Exact("/foo")
# /foo/ -> Exact("/foo/")
# /foo/bar -> Exact("/foo/bar")
# /foo/bar/{n} -> Exact("/foo/bar/"), Format("n")
# /foo/{n}/bar -> Exact("/foo/"), Format("n"), Exact("/bar")
# /foo{n:5}/bar -> Exact("/foo"), Format("n", minl=5, maxl=5), Exact("/bar")
# /foo/{m:1-}/{n:3-5}bar -> Exact("/foo/"), Format("m", minl=1, maxl=-1), Exact("/"), Format("n", minl=3, maxl=5), Exact("bar")
# /* -> Exact("/"), Format("_")
# /foo/*bar -> Exact("/foo/"), Format("_"), Exact("bar")
# /foo/*/bar -> Exact("/foo/"), Format("_"), Exact("/bar")
# /foo/**/bar -> Exact("/foo/"), Format("_", ignore_sep=True), Exact("/bar")
# ["foo", Format("m", minl=1, maxl=-1), [Format("n", minl=3, maxl=5), "bar"], "*"]
import ctypes
dll = ctypes.CDLL("./c_route.so")
dll.parse_route.restype = type("c_char_alloc", (ctypes.c_char_p,), {})
dll.free_parsed_route.argtypes = (ctypes.c_void_p,)
dll.free_parsed_route.restype = None
def compile_route(pattern: str) -> list[bytes]:
if pattern[0] != "/":
from app.exceptions import ParseError
raise ParseError("The first character in route pattern must be '/'.")
# res: list[str] = []
# for path in pattern[1:].split("/"):
# if (star_idx := path.find("*")) != -1:
# path = "".join((path[:star_idx], "{_}", path[star_idx + 1:]))
# if "{" not in path and "}" not in path and "*" not in path:
# res.append(path)
outlen = ctypes.c_size_t()
data = pattern[1:].encode()
ret = dll.parse_route(data, len(data), ctypes.byref(outlen))
res = ctypes.string_at(ret, outlen.value - 2).split(b"\x01")
dll.free_parsed_route(ret)
return res
if __name__ == "__main__":
print(compile_route("/foo/{n:5}foo/bar/**/baz"))
print(compile_route("/"))