src/molt@internal@document@arrays.erl
-module(molt@internal@document@arrays).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/molt/internal/document/arrays.gleam").
-export([append/3, concat/3, insert/4]).
-export_type([array_position/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 array_position() :: at_end | {before, integer()}.
-file("src/molt/internal/document/arrays.gleam", 355).
?DOC(false).
-spec insert_bounds_error(list(molt@types:path_segment()), integer(), integer()) -> molt@error:molt_error().
insert_bounds_error(Segments, Before, Len) ->
{index_out_of_range, molt@internal@path:to_string(Segments), Before, Len}.
-file("src/molt/internal/document/arrays.gleam", 341).
?DOC(false).
-spec resolve_array_position(
array_position(),
list(greenwood:node_(molt@types:toml_kind())),
list(molt@types:path_segment())
) -> {ok, integer()} | {error, molt@error:molt_error()}.
resolve_array_position(Position, Items, Segments) ->
Len = erlang:length(Items),
case Position of
at_end ->
{ok, Len};
{before, I} ->
_pipe = molt@internal@utils:resolve_insert_position(I, Len),
gleam@result:replace_error(
_pipe,
insert_bounds_error(Segments, I, Len)
)
end.
-file("src/molt/internal/document/arrays.gleam", 288).
?DOC(false).
-spec do_modify_inline_array(
molt@types:document(),
gleam@dict:dict(molt@types:index_key(), molt@types:index_entry()),
list(molt@types:path_segment()),
array_position(),
molt@value:value()
) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}.
do_modify_inline_array(Doc, Idx, Segments, Position, New_value) ->
gleam@result:'try'(
begin
_pipe = molt@internal@cst@query:get_cursor(
erlang:element(4, Doc),
Segments
),
gleam@result:replace_error(
_pipe,
molt@error:not_found_path(Segments)
)
end,
fun(Cursor) ->
gleam@result:'try'(
case molt@internal@document@primitives:find_kv_value(
erlang:element(2, Cursor),
array
) of
{ok, Array_node} ->
Items = molt@internal@cst@elements:extract_array_items(
Array_node
),
gleam@result:'try'(
resolve_array_position(Position, Items, Segments),
fun(I) ->
Layout = molt@internal@cst@elements:array_layout(
Array_node
),
New_item = molt@internal@cst@elements:build_array_item(
molt@value:to_cst(New_value),
Layout
),
{Head, Tail} = gleam@list:split(Items, I),
New_array = molt@internal@cst@elements:rebuild_array(
Array_node,
lists:append([Head, [New_item], Tail])
),
{ok, {node_element, New_array}}
end
);
{error, nil} ->
Got = case molt@internal@document@primitives:find_kv_value(
erlang:element(2, Cursor),
inline_table
) of
{ok, _} ->
<<"inline table"/utf8>>;
{error, nil} ->
<<"scalar value"/utf8>>
end,
{error,
{type_mismatch,
{some, molt@internal@path:to_string(Segments)},
<<"array"/utf8>>,
Got}}
end,
fun(New_value_el) ->
molt@internal@document@primitives:cursor_replace_value(
Doc,
Idx,
Segments,
New_value_el
)
end
)
end
).
-file("src/molt/internal/document/arrays.gleam", 268).
?DOC(false).
-spec build_aot_entry_node(
list(molt@types:path_segment()),
list({binary(), molt@value:value()})
) -> greenwood:node_(molt@types:toml_kind()).
build_aot_entry_node(Segments, Entries) ->
Key_path = molt@internal@path:path_to_table_header(Segments),
Header = molt@internal@cst@builder:build_empty_array_of_tables(Key_path),
Kv_children = gleam@list:map(
Entries,
fun(Entry) ->
{K, V} = Entry,
{node_element,
molt@internal@cst@builder:build_kv_node(K, molt@value:to_cst(V))}
end
),
{node,
erlang:element(2, Header),
lists:append(erlang:element(3, Header), Kv_children),
erlang:element(4, Header)}.
-file("src/molt/internal/document/arrays.gleam", 256).
?DOC(false).
-spec table_entries_or_mismatch(
list(molt@types:path_segment()),
molt@value:value()
) -> {ok, list({binary(), molt@value:value()})} |
{error, molt@error:molt_error()}.
table_entries_or_mismatch(Segments, Val) ->
_pipe = molt@value:table_to_list(Val),
gleam@result:replace_error(
_pipe,
{type_mismatch,
{some, molt@internal@path:to_string(Segments)},
<<"table"/utf8>>,
molt@value:type_of(Val)}
).
-file("src/molt/internal/document/arrays.gleam", 228).
?DOC(false).
-spec do_modify_aot(
molt@types:document(),
list(molt@types:path_segment()),
array_position(),
molt@value:value()
) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}.
do_modify_aot(Doc, Segments, Position, Val) ->
gleam@result:'try'(
table_entries_or_mismatch(Segments, Val),
fun(Entries) ->
Entry_node = build_aot_entry_node(Segments, Entries),
case Position of
at_end ->
_pipe = molt@cst:insert_array_of_tables_entry(
erlang:element(4, Doc),
Segments,
Entry_node,
entry_at_end
),
gleam@result:map(
_pipe,
fun(Tree) ->
molt@internal@document@primitives:rebuild(Doc, Tree)
end
);
{before, I} ->
_pipe@1 = molt@cst:insert_array_of_tables_entry(
erlang:element(4, Doc),
Segments,
Entry_node,
{before_index, I}
),
gleam@result:map(
_pipe@1,
fun(Tree@1) ->
molt@internal@document@primitives:rebuild(
Doc,
Tree@1
)
end
)
end
end
).
-file("src/molt/internal/document/arrays.gleam", 23).
?DOC(false).
-spec append(molt@types:document(), binary(), molt@value:value()) -> {ok,
molt@types:document()} |
{error, molt@error:molt_error()}.
append(Doc, P, Val) ->
gleam@bool:guard(
molt@value:type_of(Val) =:= <<"invalid"/utf8>>,
{error, {invalid_toml_value, P, molt@value:invalid_text(Val)}},
fun() ->
gleam@result:'try'(
molt@internal@path:parse(P),
fun(Segments) ->
molt@internal@document@index:with_index(
Doc,
fun(Idx) ->
case molt@internal@document@index:resolve(
Idx,
Segments
) of
{hit, _, {index_array_of_tables, _, _}} ->
do_modify_aot(Doc, Segments, at_end, Val);
{hit, _, {index_array_value, _}} ->
do_modify_inline_array(
Doc,
Idx,
Segments,
at_end,
Val
);
{hit, _, Entry} ->
{error,
{type_mismatch,
{some, P},
<<"array or array of tables"/utf8>>,
molt@internal@utils:index_entry_to_string(
Entry
)}};
{miss, _, Ancestor, _} ->
case Ancestor of
{index_array_value, _} ->
do_modify_inline_array(
Doc,
Idx,
Segments,
at_end,
Val
);
_ ->
{error,
{type_mismatch,
{some, P},
<<"array"/utf8>>,
molt@internal@utils:index_entry_to_string(
Ancestor
)}}
end;
{fresh, _} ->
{error, molt@error:not_found(P)}
end
end
)
end
)
end
).
-file("src/molt/internal/document/arrays.gleam", 133).
?DOC(false).
-spec concat_aot(
molt@types:document(),
list(molt@types:path_segment()),
list(molt@value:value())
) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}.
concat_aot(Doc, Segments, Vals) ->
gleam@result:'try'(
gleam@list:try_map(
Vals,
fun(Val) ->
gleam@result:'try'(
table_entries_or_mismatch(Segments, Val),
fun(Entries) ->
{ok, build_aot_entry_node(Segments, Entries)}
end
)
end
),
fun(Entry_nodes) ->
gleam@result:'try'(
gleam@list:try_fold(
Entry_nodes,
erlang:element(4, Doc),
fun(Tree, Entry_node) ->
molt@cst:insert_array_of_tables_entry(
Tree,
Segments,
Entry_node,
entry_at_end
)
end
),
fun(New_tree) ->
{ok,
molt@internal@document@primitives:rebuild(Doc, New_tree)}
end
)
end
).
-file("src/molt/internal/document/arrays.gleam", 88).
?DOC(false).
-spec concat(molt@types:document(), binary(), list(molt@value:value())) -> {ok,
molt@types:document()} |
{error, molt@error:molt_error()}.
concat(Doc, P, Vals) ->
gleam@result:'try'(
molt@internal@path:parse(P),
fun(Segments) ->
molt@internal@document@index:with_index(
Doc,
fun(Idx) ->
case molt@internal@document@index:resolve(Idx, Segments) of
{hit, _, {index_array_of_tables, _, _}} ->
concat_aot(Doc, Segments, Vals);
{hit, _, {index_array_value, _}} ->
gleam@list:try_fold(
Vals,
Doc,
fun(D, Val) -> append(D, P, Val) end
);
{miss, _, {index_array_value, _}, _} ->
gleam@list:try_fold(
Vals,
Doc,
fun(D, Val) -> append(D, P, Val) end
);
{hit, _, Entry} ->
{error,
{type_mismatch,
{some, P},
<<"array or array of tables"/utf8>>,
molt@internal@utils:index_entry_to_string(
Entry
)}};
{miss, _, Ancestor, _} ->
{error,
{type_mismatch,
{some, P},
<<"array"/utf8>>,
molt@internal@utils:index_entry_to_string(
Ancestor
)}};
{fresh, _} ->
{error, molt@error:not_found(P)}
end
end
)
end
).
-file("src/molt/internal/document/arrays.gleam", 157).
?DOC(false).
-spec insert(molt@types:document(), binary(), integer(), molt@value:value()) -> {ok,
molt@types:document()} |
{error, molt@error:molt_error()}.
insert(Doc, P, Before, Val) ->
gleam@bool:guard(
molt@value:type_of(Val) =:= <<"invalid"/utf8>>,
{error, {invalid_toml_value, P, molt@value:invalid_text(Val)}},
fun() ->
gleam@result:'try'(
molt@internal@path:parse(P),
fun(Segments) ->
molt@internal@document@index:with_index(
Doc,
fun(Idx) ->
case molt@internal@document@index:resolve(
Idx,
Segments
) of
{hit, _, {index_array_value, _}} ->
do_modify_inline_array(
Doc,
Idx,
Segments,
{before, Before},
Val
);
{hit, _, {index_array_of_tables, Count, _}} ->
gleam@result:'try'(
begin
_pipe = molt@internal@utils:resolve_insert_position(
Before,
Count
),
gleam@result:replace_error(
_pipe,
insert_bounds_error(
Segments,
Before,
Count
)
)
end,
fun(I) ->
Position = case I =:= Count of
true ->
at_end;
false ->
{before, I}
end,
do_modify_aot(
Doc,
Segments,
Position,
Val
)
end
);
{hit, _, Entry} ->
{error,
{type_mismatch,
{some, P},
<<"array or array of tables"/utf8>>,
molt@internal@utils:index_entry_to_string(
Entry
)}};
{miss, _, Ancestor, _} ->
case Ancestor of
{index_array_value, _} ->
do_modify_inline_array(
Doc,
Idx,
Segments,
{before, Before},
Val
);
_ ->
{error,
{type_mismatch,
{some, P},
<<"array"/utf8>>,
molt@internal@utils:index_entry_to_string(
Ancestor
)}}
end;
{fresh, _} ->
{error, molt@error:not_found(P)}
end
end
)
end
)
end
).