Skip to main content

src/tomlet@path.erl

-module(tomlet@path).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/tomlet/path.gleam").
-export([get/2]).

-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/tomlet/path.gleam", 74).
?DOC(false).
-spec scan_inline_entry(
    tomlet@ast:key(),
    tomlet@ast:value(),
    list(tomlet@ast:inline_table_entry()),
    list(binary()),
    list(binary())
) -> {ok, tomlet@ast:value()} | {error, nil}.
scan_inline_entry(Key, Value, Rest, Active_path, Target) ->
    Full_key = lists:append(Active_path, tomlet@key:to_strings(Key)),
    gleam@bool:guard(Full_key =:= Target, {ok, Value}, fun() -> case Value of
                {inline_table, Nested_entries, _} ->
                    case scan_inline_entries(Nested_entries, Full_key, Target) of
                        {ok, Found} ->
                            {ok, Found};

                        {error, nil} ->
                            scan_inline_entries(Rest, Active_path, Target)
                    end;

                _ ->
                    scan_inline_entries(Rest, Active_path, Target)
            end end).

-file("src/tomlet/path.gleam", 62).
?DOC(false).
-spec scan_inline_entries(
    list(tomlet@ast:inline_table_entry()),
    list(binary()),
    list(binary())
) -> {ok, tomlet@ast:value()} | {error, nil}.
scan_inline_entries(Entries, Active_path, Target) ->
    case Entries of
        [] ->
            {error, nil};

        [{inline_table_entry, _, Key, Value, _} | Rest] ->
            scan_inline_entry(Key, Value, Rest, Active_path, Target)
    end.

-file("src/tomlet/path.gleam", 43).
?DOC(false).
-spec scan_key_value(
    tomlet@ast:key(),
    tomlet@ast:value(),
    list(tomlet@ast:entry()),
    list(binary()),
    list(binary())
) -> {ok, tomlet@ast:value()} | {error, nil}.
scan_key_value(Key, Value, Rest, Active_table, Target) ->
    Full_key = lists:append(Active_table, tomlet@key:to_strings(Key)),
    gleam@bool:guard(Full_key =:= Target, {ok, Value}, fun() -> case Value of
                {inline_table, Inline_entries, _} ->
                    case scan_inline_entries(Inline_entries, Full_key, Target) of
                        {ok, Found} ->
                            {ok, Found};

                        {error, nil} ->
                            scan_entries(Rest, Active_table, Target)
                    end;

                _ ->
                    scan_entries(Rest, Active_table, Target)
            end end).

-file("src/tomlet/path.gleam", 20).
?DOC(false).
-spec scan_entries(list(tomlet@ast:entry()), list(binary()), list(binary())) -> {ok,
        tomlet@ast:value()} |
    {error, nil}.
scan_entries(Entries, Active_table, Target) ->
    case Entries of
        [] ->
            {error, nil};

        [Entry | Rest] ->
            case Entry of
                {table_header, {header, Key, standard_table, _}} ->
                    scan_entries(Rest, tomlet@key:to_strings(Key), Target);

                {table_header, {header, Key@1, array_of_tables_header, _}} ->
                    scan_entries(Rest, tomlet@key:to_strings(Key@1), Target);

                {key_value, _, Key@2, Value, _} ->
                    scan_key_value(Key@2, Value, Rest, Active_table, Target);

                _ ->
                    scan_entries(Rest, Active_table, Target)
            end
    end.

-file("src/tomlet/path.gleam", 158).
?DOC(false).
-spec finish_array_table(
    gleam@option:option(tomlet@ast:header()),
    list(tomlet@ast:entry()),
    list(tomlet@ast:table())
) -> list(tomlet@ast:table()).
finish_array_table(Current_header, Current_entries, Tables) ->
    case Current_header of
        {some, Header} ->
            [{table, lists:reverse(Current_entries), {some, Header}} | Tables];

        none ->
            Tables
    end.

-file("src/tomlet/path.gleam", 140).
?DOC(false).
-spec collect_array_table_header(
    tomlet@ast:header(),
    list(tomlet@ast:entry()),
    list(binary()),
    list(tomlet@ast:table())
) -> list(tomlet@ast:table()).
collect_array_table_header(Header, Rest, Target, Next_tables) ->
    case Header of
        {header, Key, array_of_tables_header, _} ->
            Next_header = case tomlet@key:to_strings(Key) =:= Target of
                true ->
                    {some, Header};

                false ->
                    none
            end,
            collect_array_tables_loop(
                Rest,
                Target,
                Next_header,
                [],
                Next_tables
            );

        _ ->
            collect_array_tables_loop(Rest, Target, none, [], Next_tables)
    end.

-file("src/tomlet/path.gleam", 100).
?DOC(false).
-spec collect_array_tables_loop(
    list(tomlet@ast:entry()),
    list(binary()),
    gleam@option:option(tomlet@ast:header()),
    list(tomlet@ast:entry()),
    list(tomlet@ast:table())
) -> list(tomlet@ast:table()).
collect_array_tables_loop(
    Entries,
    Target,
    Current_header,
    Current_entries,
    Tables
) ->
    case Entries of
        [] ->
            lists:reverse(
                finish_array_table(Current_header, Current_entries, Tables)
            );

        [Entry | Rest] ->
            case Entry of
                {table_header, Header} ->
                    Next_tables = finish_array_table(
                        Current_header,
                        Current_entries,
                        Tables
                    ),
                    collect_array_table_header(
                        Header,
                        Rest,
                        Target,
                        Next_tables
                    );

                _ ->
                    case Current_header of
                        {some, _} ->
                            collect_array_tables_loop(
                                Rest,
                                Target,
                                Current_header,
                                [Entry | Current_entries],
                                Tables
                            );

                        none ->
                            collect_array_tables_loop(
                                Rest,
                                Target,
                                Current_header,
                                Current_entries,
                                Tables
                            )
                    end
            end
    end.

-file("src/tomlet/path.gleam", 93).
?DOC(false).
-spec collect_array_tables(list(tomlet@ast:entry()), list(binary())) -> list(tomlet@ast:table()).
collect_array_tables(Entries, Target) ->
    collect_array_tables_loop(Entries, Target, none, [], []).

-file("src/tomlet/path.gleam", 12).
?DOC(false).
-spec get(tomlet@ast:table(), list(binary())) -> {ok, tomlet@ast:value()} |
    {error, nil}.
get(Table, Path) ->
    {table, Entries, _} = Table,
    case collect_array_tables(Entries, Path) of
        [] ->
            scan_entries(Entries, [], Path);

        Tables ->
            {ok, {array_of_tables, Tables}}
    end.