-module(molt@internal@document@values). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/molt/internal/document/values.gleam"). -export([set/3, replace/3, insert_key/5, update/3]). -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/document/values.gleam", 23). ?DOC(false). -spec set(molt@types:document(), binary(), molt@value:value()) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. set(Doc, P, Val) -> Type_of = molt@value:type_of(Val), gleam@bool:guard( Type_of =:= <<"invalid"/utf8>>, {error, {invalid_toml_value, P, molt@value:invalid_text(Val)}}, fun() -> gleam@bool:guard( (Type_of =:= <<"table"/utf8>>) orelse (Type_of =:= <<"array_of_tables"/utf8>>), {error, {type_mismatch, {some, P}, <<"scalar, array, or inline-table value"/utf8>>, Type_of}}, 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_scalar_value, _}} -> molt@internal@document@primitives:cursor_replace_value( Doc, Idx, Segments, molt@value:to_cst(Val) ); {hit, _, {index_array_value, _}} -> molt@internal@document@primitives:cursor_replace_value( Doc, Idx, Segments, molt@value:to_cst(Val) ); {hit, _, {index_inline_table_value, _}} -> molt@internal@document@primitives:cursor_replace_value( Doc, Idx, Segments, molt@value:to_cst(Val) ); {hit, _, {index_implicit_table, _}} -> {error, {type_mismatch, {some, P}, <<"scalar or array value"/utf8>>, <<"implicit table"/utf8>>}}; {hit, _, {index_table, _}} -> {error, {type_mismatch, {some, P}, <<"scalar or array value"/utf8>>, <<"table"/utf8>>}}; {hit, _, {index_array_of_tables, _, _}} -> {error, {type_mismatch, {some, P}, <<"scalar or array value (use an index to select an entry)"/utf8>>, <<"array of tables"/utf8>>}}; {hit, _, {index_array_of_tables_entry, _, _, _}} -> {error, {type_mismatch, {some, P}, <<"a key within the array entry"/utf8>>, <<"array of tables entry"/utf8>>}}; {miss, Ancestor_path, Ancestor, _} -> gleam@result:'try'( molt@internal@document@index:insertion_site( Idx, Ancestor_path, Ancestor, Segments ), fun(Site) -> molt@internal@document@primitives:write_at_site( Doc, Idx, Site, Segments, Val ) end ); {fresh, _} -> molt@internal@document@primitives:write_at_site( Doc, Idx, {root_dotted_key, Segments}, Segments, Val ) end end ) end ) end ) end ). -file("src/molt/internal/document/values.gleam", 153). ?DOC(false). -spec replace_array_of_tables( molt@types:document(), binary(), list(molt@value:value()) ) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. replace_array_of_tables(Doc, P, Items) -> case Items of [] -> {ok, Doc}; [First | Rest] -> gleam@result:'try'( molt@value:table_to_list(First), fun(First_entries) -> gleam@result:'try'( molt@internal@document@structure:ensure_exists( Doc, P, array_of_tables ), fun(D0) -> gleam@result:'try'( molt@internal@document@structure:merge_values( D0, <

>, First_entries, on_conflict_error ), fun(D1) -> gleam@list:try_fold( Rest, D1, fun(D, Item) -> molt@internal@document@arrays:append( D, P, Item ) end ) end ) end ) end ) end. -file("src/molt/internal/document/values.gleam", 109). ?DOC(false). -spec replace(molt@types:document(), binary(), molt@value:value()) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. replace(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) -> gleam@result:'try'( case molt@internal@document@index:resolve( Idx, Segments ) of {hit, _, _} -> molt@internal@document@remove:prune( Doc, Idx, Segments ); {miss, _, _, _} -> {ok, Doc}; {fresh, _} -> {ok, Doc} end, fun(Doc2) -> case molt@value:type_of(Val) of <<"table"/utf8>> -> gleam@result:'try'( molt@value:table_to_list(Val), fun(Entries) -> gleam@result:'try'( molt@internal@document@structure:ensure_exists( Doc2, P, table ), fun(Doc3) -> molt@internal@document@structure:merge_values( Doc3, P, Entries, on_conflict_error ) end ) end ); <<"array_of_tables"/utf8>> -> gleam@result:'try'( molt@value:array_to_list(Val), fun(Items) -> replace_array_of_tables( Doc2, P, Items ) end ); _ -> set(Doc2, P, Val) end end ) end ) end ) end ). -file("src/molt/internal/document/values.gleam", 395). ?DOC(false). -spec insert_before_root_kv_with_path( list(greenwood:element(molt@types:toml_kind())), list(binary()), greenwood:element(molt@types:toml_kind()) ) -> list(greenwood:element(molt@types:toml_kind())). insert_before_root_kv_with_path(Children, Target_key_path, New_el) -> case Children of [] -> [New_el]; [{node_element, N} | Rest] when erlang:element(2, N) =:= key_value -> case molt@internal@cst@elements:key_path(erlang:element(3, N)) of {some, Kp} when Kp =:= Target_key_path -> [New_el, {node_element, N} | Rest]; _ -> [{node_element, N} | insert_before_root_kv_with_path( Rest, Target_key_path, New_el )] end; [El | Rest@1] -> [El | insert_before_root_kv_with_path(Rest@1, Target_key_path, New_el)] end. -file("src/molt/internal/document/values.gleam", 386). ?DOC(false). -spec key_segment_names(list(molt@types:path_segment())) -> list(binary()). key_segment_names(Path) -> gleam@list:filter_map(Path, fun(Seg) -> case Seg of {key_segment, Name} -> {ok, molt@internal@utils:quote_key(Name)}; _ -> {error, nil} end end). -file("src/molt/internal/document/values.gleam", 320). ?DOC(false). -spec insert_key_in_implicit( molt@types:document(), gleam@dict:dict(molt@types:index_key(), molt@types:index_entry()), list(molt@types:path_segment()), binary(), binary(), molt@value:value() ) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. insert_key_in_implicit(Doc, Idx, Container, Before, Key, Val) -> case molt@internal@path:split_at_last_index(Container) of {error, nil} -> Before_keys = molt@internal@path:path_to_table_header( lists:append(Container, [{key_segment, Before}]) ), New_key_path = lists:append(Container, [{key_segment, Key}]), Kv = molt@internal@cst@builder:build_kv_from_path( key_segment_names(New_key_path), molt@value:to_cst(Val) ), New_children = insert_before_root_kv_with_path( erlang:element(3, erlang:element(4, Doc)), Before_keys, {node_element, Kv} ), New_tree = begin _record = erlang:element(4, Doc), {node, erlang:element(2, _record), New_children, erlang:element(4, _record)} end, Idx_key = molt@internal@document@index:path_to_index_key( New_key_path ), Entry = molt@internal@document@index:entry_for_value(Val, Container), Idx@1 = molt@internal@document@index:insert_entry( Idx, Idx_key, Entry ), {ok, molt@internal@document@primitives:patch(Doc, New_tree, Idx@1)}; {ok, {Entry_path, Rel_container}} -> Before_keys@1 = molt@internal@path:path_to_table_header( lists:append(Rel_container, [{key_segment, Before}]) ), Rel_key_path = lists:append(Rel_container, [{key_segment, Key}]), Kv@1 = molt@internal@cst@builder:build_kv_from_path( key_segment_names(Rel_key_path), molt@value:to_cst(Val) ), gleam@result:'try'( begin _pipe = molt@internal@cst@query:get_cursor( erlang:element(4, Doc), Entry_path ), gleam@result:replace_error( _pipe, molt@error:not_found_path(Container) ) end, fun(Cursor) -> Entry@1 = erlang:element(2, Cursor), New_entry = {node, erlang:element(2, Entry@1), insert_before_root_kv_with_path( erlang:element(3, Entry@1), Before_keys@1, {node_element, Kv@1} ), erlang:element(4, Entry@1)}, New_tree@1 = begin _pipe@1 = greenwood@zipper:set_focus(Cursor, New_entry), greenwood@zipper:unzip(_pipe@1) end, {ok, molt@internal@document@primitives:rebuild( Doc, New_tree@1 )} end ) end. -file("src/molt/internal/document/values.gleam", 180). ?DOC(false). -spec insert_key( molt@types:document(), binary(), binary(), binary(), molt@value:value() ) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. insert_key(Doc, P, Before, Key, Val) -> 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_table, _}} -> Kv = molt@internal@cst@builder:build_kv_node( molt@internal@utils:quote_key(Key), molt@value:to_cst(Val) ), gleam@result:'try'( case molt@cst:insert_kv( erlang:element(4, Doc), Segments, Kv, {before_key, Before} ) of {error, {not_found, _, _}} -> molt@cst:insert_kv( erlang:element(4, Doc), Segments, Kv, kv_at_end ); Other -> Other end, fun(New_tree) -> Full_path = lists:append( Segments, [{key_segment, Key}] ), Idx_key = molt@internal@document@index:path_to_index_key( Full_path ), Entry = molt@internal@document@index:entry_for_value( Val, Segments ), Idx@1 = molt@internal@document@index:insert_entry( Idx, Idx_key, Entry ), {ok, molt@internal@document@primitives:patch( Doc, New_tree, Idx@1 )} end ); {hit, _, {index_array_of_tables_entry, _, _, _}} -> Kv = molt@internal@cst@builder:build_kv_node( molt@internal@utils:quote_key(Key), molt@value:to_cst(Val) ), gleam@result:'try'( case molt@cst:insert_kv( erlang:element(4, Doc), Segments, Kv, {before_key, Before} ) of {error, {not_found, _, _}} -> molt@cst:insert_kv( erlang:element(4, Doc), Segments, Kv, kv_at_end ); Other -> Other end, fun(New_tree) -> Full_path = lists:append( Segments, [{key_segment, Key}] ), Idx_key = molt@internal@document@index:path_to_index_key( Full_path ), Entry = molt@internal@document@index:entry_for_value( Val, Segments ), Idx@1 = molt@internal@document@index:insert_entry( Idx, Idx_key, Entry ), {ok, molt@internal@document@primitives:patch( Doc, New_tree, Idx@1 )} end ); {hit, _, {index_implicit_table, _}} -> insert_key_in_implicit( Doc, Idx, Segments, Before, Key, Val ); {hit, _, Entry@1} -> {error, {type_mismatch, {some, P}, <<"table or array of tables entry"/utf8>>, molt@internal@utils:index_entry_to_string( Entry@1 )}}; {miss, _, _, _} -> {error, molt@error:not_found(P)}; {fresh, _} -> {error, molt@error:not_found(P)} end end ) end ). -file("src/molt/internal/document/values.gleam", 280). ?DOC(false). -spec cursor_transform_value( molt@types:document(), gleam@dict:dict(molt@types:index_key(), molt@types:index_entry()), list(molt@types:path_segment()), fun((molt@value:value()) -> {ok, molt@value:value()} | {error, molt@error:molt_error()}) ) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. cursor_transform_value(Doc, Idx, Segments, Transform) -> 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) -> Current = molt@value:from_cst(erlang:element(2, Cursor)), gleam@result:'try'( Transform(Current), fun(New_val) -> Path_str = molt@internal@path:to_string(Segments), New_val_type = molt@value:type_of(New_val), gleam@bool:guard( (New_val_type =:= <<"table"/utf8>>) orelse (New_val_type =:= <<"array_of_tables"/utf8>>), {error, {type_mismatch, {some, Path_str}, <<"scalar or inline value"/utf8>>, New_val_type}}, fun() -> gleam@bool:guard( New_val_type =:= <<"invalid"/utf8>>, {error, {invalid_toml_value, Path_str, molt@value:invalid_text(New_val)}}, fun() -> New_node = case erlang:element( 2, erlang:element(2, Cursor) ) of array_element -> molt@internal@document@primitives:rebuild_array_element( erlang:element(2, Cursor), molt@value:to_cst(New_val) ); _ -> molt@internal@document@primitives:rebuild_kv_value( erlang:element(2, Cursor), molt@value:to_cst(New_val) ) end, _pipe@1 = greenwood@zipper:set_focus( Cursor, New_node ), _pipe@2 = greenwood@zipper:unzip(_pipe@1), _pipe@3 = molt@internal@document@primitives:patch( Doc, _pipe@2, Idx ), {ok, _pipe@3} end ) end ) end ) end ). -file("src/molt/internal/document/values.gleam", 243). ?DOC(false). -spec update( molt@types:document(), binary(), fun((molt@value:value()) -> {ok, molt@value:value()} | {error, molt@error:molt_error()}) ) -> {ok, molt@types:document()} | {error, molt@error:molt_error()}. update(Doc, P, Transform) -> 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_scalar_value, _}} -> cursor_transform_value( Doc, Idx, Segments, Transform ); {hit, _, {index_array_value, _}} -> cursor_transform_value( Doc, Idx, Segments, Transform ); {hit, _, {index_inline_table_value, _}} -> cursor_transform_value( Doc, Idx, Segments, Transform ); {hit, _, Entry} -> {error, {type_mismatch, {some, P}, <<"scalar, array, or inline table"/utf8>>, molt@internal@utils:index_entry_to_string( Entry )}}; {miss, _, Ancestor, _} -> case Ancestor of {index_scalar_value, _} -> cursor_transform_value( Doc, Idx, Segments, Transform ); {index_array_value, _} -> cursor_transform_value( Doc, Idx, Segments, Transform ); {index_inline_table_value, _} -> cursor_transform_value( Doc, Idx, Segments, Transform ); _ -> {error, molt@error:not_found(P)} end; {fresh, _} -> {error, molt@error:not_found(P)} end end ) end ).