Skip to main content

src/molt@internal@utils.erl

-module(molt@internal@utils).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/molt/internal/utils.gleam").
-export([toml_kind/1, index_entry_to_string/1, is_bare_key/1, make_key_token/1, list_at/2, quote_key/1, path_to_string/1, resolve_index/2, resolve_insert_position/2, all_prefixes/1, split_at/2, reverse_concat/1, unescape_basic_string/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).

-file("src/molt/internal/utils.gleam", 12).
?DOC(false).
-spec toml_kind(molt@types:toml_kind()) -> binary().
toml_kind(Value) ->
    case Value of
        array ->
            <<"array"/utf8>>;

        array_element ->
            <<"array_element"/utf8>>;

        array_of_tables ->
            <<"array_of_tables"/utf8>>;

        bare_key ->
            <<"bare_key"/utf8>>;

        basic_string ->
            <<"basic_string"/utf8>>;

        binary_integer ->
            <<"binary_integer"/utf8>>;

        bom ->
            <<"bom"/utf8>>;

        bool_false ->
            <<"false"/utf8>>;

        bool_true ->
            <<"true"/utf8>>;

        comma ->
            <<"comma"/utf8>>;

        comment ->
            <<"comment"/utf8>>;

        dot ->
            <<"dot"/utf8>>;

        equals ->
            <<"equals"/utf8>>;

        error ->
            <<"error"/utf8>>;

        float ->
            <<"float"/utf8>>;

        hex_integer ->
            <<"hex_integer"/utf8>>;

        inf ->
            <<"unsigned_inf"/utf8>>;

        inline_table ->
            <<"inline_table"/utf8>>;

        integer ->
            <<"integer"/utf8>>;

        invalid_value ->
            <<"invalid_value"/utf8>>;

        invalid_basic_string ->
            <<"invalid_basic_string"/utf8>>;

        invalid_literal_string ->
            <<"invalid_literal_string"/utf8>>;

        invalid_multiline_basic_string ->
            <<"invalid_multiline_basic_string"/utf8>>;

        invalid_multiline_literal_string ->
            <<"invalid_multiline_literal_string"/utf8>>;

        key ->
            <<"key"/utf8>>;

        key_value ->
            <<"key_value"/utf8>>;

        left_brace ->
            <<"left_brace"/utf8>>;

        left_bracket ->
            <<"left_bracket"/utf8>>;

        literal_string ->
            <<"literal_string"/utf8>>;

        local_date ->
            <<"local_date"/utf8>>;

        local_date_time ->
            <<"local_datetime"/utf8>>;

        local_time ->
            <<"local_time"/utf8>>;

        multiline_basic_string ->
            <<"multiline_basic_string"/utf8>>;

        multiline_basic_string_nl ->
            <<"multiline_basic_string_nl"/utf8>>;

        multiline_literal_string ->
            <<"multiline_literal_string"/utf8>>;

        multiline_literal_string_nl ->
            <<"multiline_literal_string_nl"/utf8>>;

        na_n ->
            <<"unsigned_nan"/utf8>>;

        neg_inf ->
            <<"negative_inf"/utf8>>;

        neg_na_n ->
            <<"negative_nan"/utf8>>;

        newline ->
            <<"newline"/utf8>>;

        octal_integer ->
            <<"octal_integer"/utf8>>;

        offset_date_time ->
            <<"offset_datetime"/utf8>>;

        post_script ->
            <<"postscript"/utf8>>;

        pos_inf ->
            <<"positive_inf"/utf8>>;

        pos_na_n ->
            <<"positive_nan"/utf8>>;

        right_brace ->
            <<"right_brace"/utf8>>;

        right_bracket ->
            <<"right_bracket"/utf8>>;

        root ->
            <<"document"/utf8>>;

        table ->
            <<"table"/utf8>>;

        whitespace ->
            <<"whitespace"/utf8>>
    end.

-file("src/molt/internal/utils.gleam", 67).
?DOC(false).
-spec index_entry_to_string(molt@types:index_entry()) -> binary().
index_entry_to_string(Entry) ->
    case Entry of
        {index_table, _} ->
            <<"table"/utf8>>;

        {index_array_of_tables, _, _} ->
            <<"array of tables"/utf8>>;

        {index_array_of_tables_entry, _, _, _} ->
            <<"array of tables entry"/utf8>>;

        {index_implicit_table, _} ->
            <<"implicit table"/utf8>>;

        {index_scalar_value, _} ->
            <<"value"/utf8>>;

        {index_inline_table_value, _} ->
            <<"inline table"/utf8>>;

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

-file("src/molt/internal/utils.gleam", 173).
?DOC(false).
-spec escape_key(binary()) -> binary().
escape_key(Key) ->
    _pipe = Key,
    _pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
    gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"\\\""/utf8>>).

-file("src/molt/internal/utils.gleam", 169).
?DOC(false).
-spec is_bare_key_char(binary()) -> boolean().
is_bare_key_char(Char) ->
    (casefold:is_alnum_grapheme(Char) orelse (Char =:= <<"-"/utf8>>)) orelse (Char
    =:= <<"_"/utf8>>).

-file("src/molt/internal/utils.gleam", 139).
?DOC(false).
-spec is_bare_key(binary()) -> boolean().
is_bare_key(Key) ->
    (Key /= <<""/utf8>>) andalso begin
        _pipe = Key,
        _pipe@1 = gleam@string:to_graphemes(_pipe),
        gleam@list:all(_pipe@1, fun is_bare_key_char/1)
    end.

-file("src/molt/internal/utils.gleam", 79).
?DOC(false).
-spec make_key_token(binary()) -> greenwood:token(molt@types:toml_kind()).
make_key_token(Name) ->
    gleam@bool:guard(
        is_bare_key(Name),
        {token, bare_key, Name},
        fun() -> {token, basic_string, escape_key(Name)} end
    ).

-file("src/molt/internal/utils.gleam", 84).
?DOC(false).
-spec list_at(list(FUP), integer()) -> {ok, FUP} | {error, nil}.
list_at(Items, Index) ->
    _pipe = gleam@list:drop(Items, Index),
    gleam@list:first(_pipe).

-file("src/molt/internal/utils.gleam", 145).
?DOC(false).
-spec quote_key(binary()) -> binary().
quote_key(Key) ->
    gleam@bool:guard(
        is_bare_key(Key),
        Key,
        fun() ->
            <<<<"\""/utf8, (escape_key(Key))/binary>>/binary, "\""/utf8>>
        end
    ).

-file("src/molt/internal/utils.gleam", 88).
?DOC(false).
-spec path_to_string(list(molt@types:path_segment())) -> binary().
path_to_string(Segments) ->
    _pipe = gleam@list:map(Segments, fun(Segment) -> case Segment of
                {key_segment, Key} ->
                    quote_key(Key);

                {index_segment, Index} ->
                    <<<<"["/utf8, (erlang:integer_to_binary(Index))/binary>>/binary,
                        "]"/utf8>>
            end end),
    _pipe@1 = gleam@string:join(_pipe, <<"."/utf8>>),
    gleam@string:replace(_pipe@1, <<".["/utf8>>, <<"["/utf8>>).

-file("src/molt/internal/utils.gleam", 99).
?DOC(false).
-spec resolve_index(integer(), integer()) -> integer().
resolve_index(Index, Length) ->
    gleam@bool:guard(Index < 0, Length + Index, fun() -> Index end).

-file("src/molt/internal/utils.gleam", 107).
?DOC(false).
-spec resolve_insert_position(integer(), integer()) -> {ok, integer()} |
    {error, nil}.
resolve_insert_position(Index, Length) ->
    Min = 0 - Length,
    case Index of
        I when (I >= 0) andalso (I =< Length) ->
            {ok, I};

        I@1 when (I@1 < 0) andalso (I@1 >= Min) ->
            {ok, Length + I@1};

        _ ->
            {error, nil}
    end.

-file("src/molt/internal/utils.gleam", 124).
?DOC(false).
-spec do_all_prefixes(list(FUZ), list(FUZ), list(list(FUZ))) -> list(list(FUZ)).
do_all_prefixes(Segments, Current, Acc) ->
    case Segments of
        [] ->
            lists:reverse(Acc);

        [_] ->
            lists:reverse(Acc);

        [Segment | Path] ->
            Current@1 = lists:append(Current, [Segment]),
            do_all_prefixes(Path, Current@1, [Current@1 | Acc])
    end.

-file("src/molt/internal/utils.gleam", 120).
?DOC(false).
-spec all_prefixes(list(FUV)) -> list(list(FUV)).
all_prefixes(Segments) ->
    do_all_prefixes(Segments, [], []).

-file("src/molt/internal/utils.gleam", 153).
?DOC(false).
-spec split_at(binary(), integer()) -> {binary(), binary()}.
split_at(S, Index) ->
    Len = string:length(S),
    gleam@bool:guard(
        Len < Index,
        {S, <<""/utf8>>},
        fun() ->
            gleam@bool:lazy_guard(
                Index >= 0,
                fun() ->
                    {gleam@string:slice(S, 0, Index),
                        gleam@string:slice(S, Index, Len)}
                end,
                fun() ->
                    {gleam@string:slice(S, 0, Len + Index),
                        gleam@string:slice(S, Len + Index, Len)}
                end
            )
        end
    ).

-file("src/molt/internal/utils.gleam", 165).
?DOC(false).
-spec reverse_concat(list(binary())) -> binary().
reverse_concat(Strings) ->
    _pipe = Strings,
    _pipe@1 = lists:reverse(_pipe),
    erlang:list_to_binary(_pipe@1).

-file("src/molt/internal/utils.gleam", 235).
?DOC(false).
-spec skip_continuation_whitespace(list(binary())) -> list(binary()).
skip_continuation_whitespace(Input) ->
    case Input of
        [<<" "/utf8>> | Rest] ->
            skip_continuation_whitespace(Rest);

        [<<"\t"/utf8>> | Rest] ->
            skip_continuation_whitespace(Rest);

        [<<"\n"/utf8>> | Rest] ->
            skip_continuation_whitespace(Rest);

        [<<"\r"/utf8>> | Rest] ->
            skip_continuation_whitespace(Rest);

        _ ->
            Input
    end.

-file("src/molt/internal/utils.gleam", 226).
?DOC(false).
-spec skip_line_continuation(list(binary())) -> gleam@option:option(list(binary())).
skip_line_continuation(Input) ->
    case Input of
        [<<" "/utf8>> | Rest] ->
            skip_line_continuation(Rest);

        [<<"\t"/utf8>> | Rest] ->
            skip_line_continuation(Rest);

        [<<"\r"/utf8>>, <<"\n"/utf8>> | Rest@1] ->
            {some, skip_continuation_whitespace(Rest@1)};

        [<<"\n"/utf8>> | Rest@1] ->
            {some, skip_continuation_whitespace(Rest@1)};

        [<<"\r"/utf8>> | Rest@1] ->
            {some, skip_continuation_whitespace(Rest@1)};

        _ ->
            none
    end.

-file("src/molt/internal/utils.gleam", 243).
?DOC(false).
-spec decode_unicode(list(binary()), integer()) -> {binary(), list(binary())}.
decode_unicode(Input, N) ->
    {Hex, Rest} = gleam@list:split(Input, N),
    Hex@1 = erlang:list_to_binary(Hex),
    case gleam@int:base_parse(Hex@1, 16) of
        {ok, Codepoint} ->
            case gleam@string:utf_codepoint(Codepoint) of
                {ok, Cp} ->
                    {gleam_stdlib:utf_codepoint_list_to_string([Cp]), Rest};

                {error, nil} ->
                    {<<"\\u"/utf8, Hex@1/binary>>, Rest}
            end;

        {error, nil} ->
            {<<"\\u"/utf8, Hex@1/binary>>, Rest}
    end.

-file("src/molt/internal/utils.gleam", 199).
?DOC(false).
-spec interpret_basic_string_escape(list(binary())) -> {binary(),
    list(binary())}.
interpret_basic_string_escape(Input) ->
    case Input of
        [] ->
            {<<"\\"/utf8>>, []};

        [<<"b"/utf8>> | Rest] ->
            {<<"\x{0008}"/utf8>>, Rest};

        [<<"t"/utf8>> | Rest@1] ->
            {<<"\t"/utf8>>, Rest@1};

        [<<"n"/utf8>> | Rest@2] ->
            {<<"\n"/utf8>>, Rest@2};

        [<<"f"/utf8>> | Rest@3] ->
            {<<"\x{000C}"/utf8>>, Rest@3};

        [<<"r"/utf8>> | Rest@4] ->
            {<<"\r"/utf8>>, Rest@4};

        [<<"\""/utf8>> | Rest@5] ->
            {<<"\""/utf8>>, Rest@5};

        [<<"\\"/utf8>> | Rest@6] ->
            {<<"\\"/utf8>>, Rest@6};

        [<<"u"/utf8>> | Rest@7] ->
            decode_unicode(Rest@7, 4);

        [<<"U"/utf8>> | Rest@8] ->
            decode_unicode(Rest@8, 8);

        [<<"x"/utf8>> | Rest@9] ->
            decode_unicode(Rest@9, 2);

        _ ->
            case skip_line_continuation(Input) of
                {some, Rest@10} ->
                    {<<""/utf8>>, Rest@10};

                none ->
                    case Input of
                        [Ch | Rest@11] ->
                            {<<"\\"/utf8, Ch/binary>>, Rest@11};

                        [] ->
                            {<<"\\"/utf8>>, []}
                    end
            end
    end.

-file("src/molt/internal/utils.gleam", 185).
?DOC(false).
-spec do_unescape_basic_string(list(binary()), list(binary())) -> list(binary()).
do_unescape_basic_string(S, Acc) ->
    case S of
        [] ->
            lists:reverse(Acc);

        [<<"\\"/utf8>> | Rest] ->
            {Ch, Rest@1} = interpret_basic_string_escape(Rest),
            do_unescape_basic_string(Rest@1, [Ch | Acc]);

        [Ch@1 | Rest@2] ->
            do_unescape_basic_string(Rest@2, [Ch@1 | Acc])
    end.

-file("src/molt/internal/utils.gleam", 179).
?DOC(false).
-spec unescape_basic_string(binary()) -> binary().
unescape_basic_string(S) ->
    _pipe = gleam@string:to_graphemes(S),
    _pipe@1 = do_unescape_basic_string(_pipe, []),
    erlang:list_to_binary(_pipe@1).