-module(radiant@internal@path). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/radiant/internal/path.gleam"). -export([split/1, parse/1]). -export_type([param_type/0, segment/0]). -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 param_type() :: string_t | int_t. -type segment() :: {literal, binary()} | {capture, binary(), param_type()} | {wildcard, binary()}. -file("src/radiant/internal/path.gleam", 18). ?DOC(false). -spec split(binary()) -> list(binary()). split(Request_path) -> _pipe = Request_path, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end), gleam@list:map( _pipe@2, fun(S@1) -> _pipe@3 = gleam_stdlib:percent_decode(S@1), gleam@result:unwrap(_pipe@3, S@1) end ). -file("src/radiant/internal/path.gleam", 58). ?DOC(false). -spec check_wildcard_position(list(segment()), binary()) -> nil. check_wildcard_position(Segments, Pattern) -> case Segments of [] -> nil; [{wildcard, _}, _ | _] -> erlang:error(#{gleam_error => panic, message => (<<<<"Radiant: Wildcard must be the last segment in pattern: "/utf8, Pattern/binary>>/binary, ". Segments after a wildcard are never reachable."/utf8>>), file => <>, module => <<"radiant/internal/path"/utf8>>, function => <<"check_wildcard_position"/utf8>>, line => 62}); [_ | Rest] -> check_wildcard_position(Rest, Pattern) end. -file("src/radiant/internal/path.gleam", 93). ?DOC(false). -spec find_duplicate(list(binary())) -> {ok, binary()} | {error, nil}. find_duplicate(Names) -> case Names of [] -> {error, nil}; [Name | Rest] -> case gleam@list:contains(Rest, Name) of true -> {ok, Name}; false -> find_duplicate(Rest) end end. -file("src/radiant/internal/path.gleam", 71). ?DOC(false). -spec check_duplicate_names(list(segment()), binary()) -> nil. check_duplicate_names(Segments, Pattern) -> Names = gleam@list:filter_map(Segments, fun(Seg) -> case Seg of {capture, Name, _} -> {ok, Name}; {wildcard, Name@1} -> {ok, Name@1}; {literal, _} -> {error, nil} end end), case find_duplicate(Names) of {ok, Dup} -> erlang:error(#{gleam_error => panic, message => (<<<<<<<<"Radiant: Duplicate capture name '"/utf8, Dup/binary>>/binary, "' in pattern: "/utf8>>/binary, Pattern/binary>>/binary, ". Each capture and wildcard must have a distinct name."/utf8>>), file => <>, module => <<"radiant/internal/path"/utf8>>, function => <<"check_duplicate_names"/utf8>>, line => 82}); {error, _} -> nil end. -file("src/radiant/internal/path.gleam", 104). ?DOC(false). -spec parse_capture(binary(), binary()) -> segment(). parse_capture(Content, Full_pattern) -> case Content of <<""/utf8>> -> erlang:error(#{gleam_error => panic, message => (<<"Radiant: Capture name cannot be empty in pattern: "/utf8, Full_pattern/binary>>), file => <>, module => <<"radiant/internal/path"/utf8>>, function => <<"parse_capture"/utf8>>, line => 107}); _ -> {capture, Content, string_t} end. -file("src/radiant/internal/path.gleam", 114). ?DOC(false). -spec parse_bracket_capture(binary(), binary()) -> segment(). parse_bracket_capture(Rest, Full_pattern) -> case gleam_stdlib:string_ends_with(Rest, <<">"/utf8>>) of true -> Content = gleam@string:drop_end(Rest, 1), case gleam@string:split_once(Content, <<":"/utf8>>) of {ok, {Name, <<"int"/utf8>>}} -> {capture, Name, int_t}; {ok, {Name@1, <<"string"/utf8>>}} -> {capture, Name@1, string_t}; {ok, {_, T}} -> erlang:error(#{gleam_error => panic, message => (<<<<<<"Radiant: Unsupported type constraint '"/utf8, T/binary>>/binary, "' in pattern: "/utf8>>/binary, Full_pattern/binary>>), file => <>, module => <<"radiant/internal/path"/utf8>>, function => <<"parse_bracket_capture"/utf8>>, line => 122}); {error, nil} -> parse_capture(Content, Full_pattern) end; false -> {literal, <<"<"/utf8, Rest/binary>>} end. -file("src/radiant/internal/path.gleam", 32). ?DOC(false). -spec parse(binary()) -> list(segment()). parse(Pattern) -> Segments = begin _pipe = Pattern, _pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>), _pipe@2 = gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end), gleam@list:map(_pipe@2, fun(S@1) -> case S@1 of <<":"/utf8, Name/binary>> -> parse_capture(Name, Pattern); <<"<"/utf8, Rest/binary>> -> parse_bracket_capture(Rest, Pattern); <<"*"/utf8, Name@1/binary>> -> case Name@1 of <<""/utf8>> -> erlang:error(#{gleam_error => panic, message => (<<"Radiant: Wildcard name cannot be empty in pattern: "/utf8, Pattern/binary>>), file => <>, module => <<"radiant/internal/path"/utf8>>, function => <<"parse"/utf8>>, line => 44}); _ -> {wildcard, Name@1} end; _ -> {literal, S@1} end end) end, _ = check_wildcard_position(Segments, Pattern), _ = check_duplicate_names(Segments, Pattern), Segments.