-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 ).