-module(radiant@internal@tree). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/radiant/internal/tree.gleam"). -export([new/0, insert/4, get_handler/3, to_routes/1, allowed_methods/2, match/3]). -export_type([node_/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -type node_(OMK) :: {node, gleam@dict:dict(gleam@http:method(), OMK), gleam@dict:dict(binary(), node_(OMK)), list({binary(), radiant@internal@path:param_type(), node_(OMK)}), gleam@option:option({binary(), node_(OMK)})}. -file("src/radiant/internal/tree.gleam", 18). ?DOC(false). -spec new() -> node_(any()). new() -> {node, maps:new(), maps:new(), [], none}. -file("src/radiant/internal/tree.gleam", 61). ?DOC(false). -spec unwrap_or_new({ok, node_(OMR)} | {error, nil}) -> node_(OMR). unwrap_or_new(R) -> case R of {ok, N} -> N; {error, _} -> new() end. -file("src/radiant/internal/tree.gleam", 69). ?DOC(false). -spec insert_capture( list({binary(), radiant@internal@path:param_type(), node_(OMW)}), binary(), radiant@internal@path:param_type(), node_(OMW) ) -> list({binary(), radiant@internal@path:param_type(), node_(OMW)}). insert_capture(Captures, Name, Ptype, Child) -> Entry = {Name, Ptype, Child}, case Ptype of int_t -> [Entry | Captures]; string_t -> lists:append(Captures, [Entry]) end. -file("src/radiant/internal/tree.gleam", 82). ?DOC(false). -spec pop_capture( list({binary(), radiant@internal@path:param_type(), node_(ONC)}), binary(), radiant@internal@path:param_type() ) -> {node_(ONC), list({binary(), radiant@internal@path:param_type(), node_(ONC)})}. pop_capture(Captures, Name, Ptype) -> case Captures of [] -> {new(), []}; [{N, P, Child} | Rest] when (N =:= Name) andalso (P =:= Ptype) -> {Child, Rest}; [Other | Rest@1] -> {Found, Remaining} = pop_capture(Rest@1, Name, Ptype), {Found, [Other | Remaining]} end. -file("src/radiant/internal/tree.gleam", 26). ?DOC(false). -spec insert( node_(OMN), gleam@http:method(), list(radiant@internal@path:segment()), OMN ) -> node_(OMN). insert(Node, Method, Segments, Handler) -> case Segments of [] -> {node, gleam@dict:insert(erlang:element(2, Node), Method, Handler), erlang:element(3, Node), erlang:element(4, Node), erlang:element(5, Node)}; [First | Rest] -> case First of {literal, S} -> Child = begin _pipe = gleam_stdlib:map_get(erlang:element(3, Node), S), unwrap_or_new(_pipe) end, {node, erlang:element(2, Node), gleam@dict:insert( erlang:element(3, Node), S, insert(Child, Method, Rest, Handler) ), erlang:element(4, Node), erlang:element(5, Node)}; {capture, Name, Ptype} -> {Child@1, Other} = pop_capture( erlang:element(4, Node), Name, Ptype ), Updated = insert(Child@1, Method, Rest, Handler), {node, erlang:element(2, Node), erlang:element(3, Node), insert_capture(Other, Name, Ptype, Updated), erlang:element(5, Node)}; {wildcard, Name@1} -> Child@2 = case erlang:element(5, Node) of {some, {_, N}} -> N; none -> new() end, {node, erlang:element(2, Node), erlang:element(3, Node), erlang:element(4, Node), {some, {Name@1, insert(Child@2, Method, Rest, Handler)}}} end end. -file("src/radiant/internal/tree.gleam", 129). ?DOC(false). -spec find_capture( list({binary(), radiant@internal@path:param_type(), node_(ONN)}), binary(), radiant@internal@path:param_type() ) -> {ok, node_(ONN)} | {error, nil}. find_capture(Captures, Name, Ptype) -> case Captures of [] -> {error, nil}; [{N, P, Child} | Rest] -> case (N =:= Name) andalso (P =:= Ptype) of true -> {ok, Child}; false -> find_capture(Rest, Name, Ptype) end end. -file("src/radiant/internal/tree.gleam", 101). ?DOC(false). -spec get_handler( node_(ONI), list(radiant@internal@path:segment()), gleam@http:method() ) -> {ok, ONI} | {error, nil}. get_handler(Node, Segments, Method) -> case Segments of [] -> gleam_stdlib:map_get(erlang:element(2, Node), Method); [First | Rest] -> case First of {literal, S} -> case gleam_stdlib:map_get(erlang:element(3, Node), S) of {ok, Child} -> get_handler(Child, Rest, Method); {error, _} -> {error, nil} end; {capture, Name, Ptype} -> case find_capture(erlang:element(4, Node), Name, Ptype) of {ok, Child@1} -> get_handler(Child@1, Rest, Method); {error, _} -> {error, nil} end; {wildcard, _} -> case erlang:element(5, Node) of {some, {_, Child@2}} -> get_handler(Child@2, Rest, Method); none -> {error, nil} end end end. -file("src/radiant/internal/tree.gleam", 221). ?DOC(false). -spec try_wildcard( node_(OOT), gleam@http:method(), list(binary()), gleam@dict:dict(binary(), binary()) ) -> {ok, {OOT, gleam@dict:dict(binary(), binary())}} | {error, nil}. try_wildcard(Node, Method, Segments, Params) -> case erlang:element(5, Node) of none -> {error, nil}; {some, {Name, Child}} -> case gleam_stdlib:map_get(erlang:element(2, Child), Method) of {ok, H} -> {ok, {H, gleam@dict:insert( Params, Name, gleam@string:join(Segments, <<"/"/utf8>>) )}}; {error, _} -> {error, nil} end end. -file("src/radiant/internal/tree.gleam", 287). ?DOC(false). -spec wildcard_methods(gleam@option:option({binary(), node_(any())})) -> list(gleam@http:method()). wildcard_methods(Wildcard) -> case Wildcard of none -> []; {some, {_, Child}} -> maps:keys(erlang:element(2, Child)) end. -file("src/radiant/internal/tree.gleam", 304). ?DOC(false). -spec do_to_routes(node_(OPX), list(radiant@internal@path:segment())) -> list({gleam@http:method(), list(radiant@internal@path:segment()), OPX}). do_to_routes(Node, Acc) -> Current = gleam@list:map( maps:to_list(erlang:element(2, Node)), fun(H) -> {erlang:element(1, H), lists:reverse(Acc), erlang:element(2, H)} end ), Lit = gleam@list:flat_map( maps:to_list(erlang:element(3, Node)), fun(E) -> do_to_routes( erlang:element(2, E), [{literal, erlang:element(1, E)} | Acc] ) end ), Cap = gleam@list:flat_map( erlang:element(4, Node), fun(C) -> do_to_routes( erlang:element(3, C), [{capture, erlang:element(1, C), erlang:element(2, C)} | Acc] ) end ), Wc = case erlang:element(5, Node) of none -> []; {some, {Name, Child}} -> do_to_routes(Child, [{wildcard, Name} | Acc]) end, lists:append(Current, lists:append(Lit, lists:append(Cap, Wc))). -file("src/radiant/internal/tree.gleam", 298). ?DOC(false). -spec to_routes(node_(OPT)) -> list({gleam@http:method(), list(radiant@internal@path:segment()), OPT}). to_routes(Node) -> do_to_routes(Node, []). -file("src/radiant/internal/tree.gleam", 265). ?DOC(false). -spec captures_allowed( list({binary(), radiant@internal@path:param_type(), node_(any())}), binary(), list(binary()) ) -> list(gleam@http:method()). captures_allowed(Captures, Seg, Rest) -> gleam@list:flat_map( Captures, fun(C) -> {_, Ptype, Child} = C, Valid = case Ptype of string_t -> true; int_t -> case gleam_stdlib:parse_int(Seg) of {ok, _} -> true; {error, _} -> false end end, case Valid of true -> do_allowed(Child, Rest); false -> [] end end ). -file("src/radiant/internal/tree.gleam", 249). ?DOC(false). -spec do_allowed(node_(any()), list(binary())) -> list(gleam@http:method()). do_allowed(Node, Segments) -> case Segments of [] -> lists:append( maps:keys(erlang:element(2, Node)), wildcard_methods(erlang:element(5, Node)) ); [Seg | Rest] -> Lit = case gleam_stdlib:map_get(erlang:element(3, Node), Seg) of {ok, Child} -> do_allowed(Child, Rest); {error, _} -> [] end, Cap = captures_allowed(erlang:element(4, Node), Seg, Rest), Wc = wildcard_methods(erlang:element(5, Node)), lists:append(Lit, lists:append(Cap, Wc)) end. -file("src/radiant/internal/tree.gleam", 241). ?DOC(false). -spec allowed_methods(node_(any()), list(binary())) -> list(gleam@http:method()). allowed_methods(Node, Segments) -> _pipe = do_allowed(Node, Segments), gleam@list:unique(_pipe). -file("src/radiant/internal/tree.gleam", 191). ?DOC(false). -spec try_captures( list({binary(), radiant@internal@path:param_type(), node_(OOJ)}), gleam@http:method(), binary(), list(binary()), gleam@dict:dict(binary(), binary()) ) -> {ok, {OOJ, gleam@dict:dict(binary(), binary())}} | {error, nil}. try_captures(Captures, Method, Seg, Rest, Params) -> case Captures of [] -> {error, nil}; [{Name, Ptype, Child} | Remaining] -> Valid = case Ptype of string_t -> true; int_t -> case gleam_stdlib:parse_int(Seg) of {ok, _} -> true; {error, _} -> false end end, case Valid of true -> case do_match( Child, Method, Rest, gleam@dict:insert(Params, Name, Seg) ) of {ok, R} -> {ok, R}; {error, _} -> try_captures(Remaining, Method, Seg, Rest, Params) end; false -> try_captures(Remaining, Method, Seg, Rest, Params) end end. -file("src/radiant/internal/tree.gleam", 156). ?DOC(false). -spec do_match( node_(OOA), gleam@http:method(), list(binary()), gleam@dict:dict(binary(), binary()) ) -> {ok, {OOA, gleam@dict:dict(binary(), binary())}} | {error, nil}. do_match(Node, Method, Segments, Params) -> case Segments of [] -> case gleam_stdlib:map_get(erlang:element(2, Node), Method) of {ok, H} -> {ok, {H, Params}}; {error, _} -> try_wildcard(Node, Method, [], Params) end; [Seg | Rest] -> Lit = case gleam_stdlib:map_get(erlang:element(3, Node), Seg) of {ok, Child} -> do_match(Child, Method, Rest, Params); {error, _} -> {error, nil} end, case Lit of {ok, R} -> {ok, R}; {error, _} -> Cap = try_captures( erlang:element(4, Node), Method, Seg, Rest, Params ), case Cap of {ok, R@1} -> {ok, R@1}; {error, _} -> try_wildcard(Node, Method, Segments, Params) end end end. -file("src/radiant/internal/tree.gleam", 148). ?DOC(false). -spec match(node_(ONT), gleam@http:method(), list(binary())) -> {ok, {ONT, gleam@dict:dict(binary(), binary())}} | {error, nil}. match(Node, Method, Segments) -> do_match(Node, Method, Segments, maps:new()).