Skip to main content

src/aws@internal@uri.erl

-module(aws@internal@uri).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/internal/uri.gleam").
-export([encode_segment/1, encode_component/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(
    " Percent-encoding helpers shared by SigV4 canonical-URI/query encoding and\n"
    " by HTTP-form encoding in the STS Web Identity provider. Kept in its own\n"
    " module so SigV4 and the STS provider can both depend on it without\n"
    " creating an import cycle through `aws/credentials`.\n"
).

-file("src/aws/internal/uri.gleam", 57).
-spec hex_digit(integer()) -> binary().
hex_digit(N) ->
    case N of
        0 ->
            <<"0"/utf8>>;

        1 ->
            <<"1"/utf8>>;

        2 ->
            <<"2"/utf8>>;

        3 ->
            <<"3"/utf8>>;

        4 ->
            <<"4"/utf8>>;

        5 ->
            <<"5"/utf8>>;

        6 ->
            <<"6"/utf8>>;

        7 ->
            <<"7"/utf8>>;

        8 ->
            <<"8"/utf8>>;

        9 ->
            <<"9"/utf8>>;

        10 ->
            <<"A"/utf8>>;

        11 ->
            <<"B"/utf8>>;

        12 ->
            <<"C"/utf8>>;

        13 ->
            <<"D"/utf8>>;

        14 ->
            <<"E"/utf8>>;

        _ ->
            <<"F"/utf8>>
    end.

-file("src/aws/internal/uri.gleam", 51).
-spec hex_byte(integer()) -> binary().
hex_byte(B) ->
    High = B div 16,
    Low = B rem 16,
    <<(hex_digit(High))/binary, (hex_digit(Low))/binary>>.

-file("src/aws/internal/uri.gleam", 43).
-spec byte_to_string(integer()) -> binary().
byte_to_string(B) ->
    Bits = <<B>>,
    case gleam@bit_array:to_string(Bits) of
        {ok, S} ->
            S;

        {error, _} ->
            <<""/utf8>>
    end.

-file("src/aws/internal/uri.gleam", 33).
-spec is_unreserved(integer()) -> boolean().
is_unreserved(B) ->
    (((((((B >= 16#41) andalso (B =< 16#5A)) orelse ((B >= 16#61) andalso (B =< 16#7A)))
    orelse ((B >= 16#30) andalso (B =< 16#39)))
    orelse (B =:= 16#2D))
    orelse (B =:= 16#5F))
    orelse (B =:= 16#2E))
    orelse (B =:= 16#7E).

-file("src/aws/internal/uri.gleam", 21).
-spec encode_bytes(bitstring(), binary()) -> binary().
encode_bytes(Bits, Acc) ->
    case Bits of
        <<>> ->
            Acc;

        <<B, Rest/bitstring>> ->
            case is_unreserved(B) of
                true ->
                    encode_bytes(
                        Rest,
                        <<Acc/binary, (byte_to_string(B))/binary>>
                    );

                false ->
                    encode_bytes(
                        Rest,
                        <<<<Acc/binary, "%"/utf8>>/binary,
                            (hex_byte(B))/binary>>
                    )
            end;

        _ ->
            Acc
    end.

-file("src/aws/internal/uri.gleam", 10).
?DOC(
    " Percent-encode a single URI path segment. RFC 3986 unreserved characters\n"
    " (`A-Za-z0-9-_.~`) pass through; everything else becomes `%HH`.\n"
).
-spec encode_segment(binary()) -> binary().
encode_segment(S) ->
    encode_bytes(gleam_stdlib:identity(S), <<""/utf8>>).

-file("src/aws/internal/uri.gleam", 98).
-spec hex_value(integer()) -> {ok, integer()} | {error, nil}.
hex_value(B) ->
    case B of
        _ when (B >= 16#30) andalso (B =< 16#39) ->
            {ok, B - 16#30};

        _ when (B >= 16#41) andalso (B =< 16#46) ->
            {ok, (B - 16#41) + 10};

        _ when (B >= 16#61) andalso (B =< 16#66) ->
            {ok, (B - 16#61) + 10};

        _ ->
            {error, nil}
    end.

-file("src/aws/internal/uri.gleam", 82).
-spec do_percent_decode(bitstring(), bitstring()) -> bitstring().
do_percent_decode(Bits, Acc) ->
    case Bits of
        <<>> ->
            Acc;

        <<16#25, H, L, Rest/bitstring>> ->
            case {hex_value(H), hex_value(L)} of
                {{ok, Hv}, {ok, Lv}} ->
                    Byte = (Hv * 16) + Lv,
                    do_percent_decode(
                        Rest,
                        gleam@bit_array:append(Acc, <<Byte>>)
                    );

                {_, _} ->
                    do_percent_decode(
                        Rest,
                        gleam@bit_array:append(Acc, <<16#25, H, L>>)
                    )
            end;

        <<B, Rest@1/bitstring>> ->
            do_percent_decode(Rest@1, gleam@bit_array:append(Acc, <<B>>));

        _ ->
            Acc
    end.

-file("src/aws/internal/uri.gleam", 78).
-spec percent_decode_bytes(bitstring()) -> bitstring().
percent_decode_bytes(Bits) ->
    do_percent_decode(Bits, <<>>).

-file("src/aws/internal/uri.gleam", 17).
?DOC(
    " Percent-encode a URI component, first decoding any pre-existing\n"
    " percent-escapes so callers can pass values that may or may not already\n"
    " be encoded.\n"
).
-spec encode_component(binary()) -> binary().
encode_component(S) ->
    encode_bytes(percent_decode_bytes(gleam_stdlib:identity(S)), <<""/utf8>>).