-module(trove@internal@btree@diff). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/trove/internal/btree/diff.gleam"). -export([diff/6]). -export_type([entry/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). -type entry(OBC) :: {upserted, OBC} | removed. -file("src/trove/internal/btree/diff.gleam", 73). ?DOC(false). -spec do_merge_step( gleam@yielder:step({OBT, OBU}, gleam@yielder:yielder({OBT, OBU})), gleam@yielder:step({OBT, OBU}, gleam@yielder:yielder({OBT, OBU})), fun((OBT, OBT) -> gleam@order:order()) ) -> gleam@yielder:step({OBT, entry(OBU)}, {gleam@yielder:step({OBT, OBU}, gleam@yielder:yielder({OBT, OBU})), gleam@yielder:step({OBT, OBU}, gleam@yielder:yielder({OBT, OBU}))}). do_merge_step(Old_step, New_step, Compare) -> case {Old_step, New_step} of {done, done} -> done; {done, {next, {New_key, New_value}, New_rest}} -> {next, {New_key, {upserted, New_value}}, {done, gleam@yielder:step(New_rest)}}; {{next, {Old_key, _}, Old_rest}, done} -> {next, {Old_key, removed}, {gleam@yielder:step(Old_rest), done}}; {{next, {Old_key@1, Old_value}, Old_rest@1}, {next, {New_key@1, New_value@1}, New_rest@1}} -> case Compare(Old_key@1, New_key@1) of lt -> {next, {Old_key@1, removed}, {gleam@yielder:step(Old_rest@1), New_step}}; gt -> {next, {New_key@1, {upserted, New_value@1}}, {Old_step, gleam@yielder:step(New_rest@1)}}; eq -> case Old_value =:= New_value@1 of true -> do_merge_step( gleam@yielder:step(Old_rest@1), gleam@yielder:step(New_rest@1), Compare ); false -> {next, {New_key@1, {upserted, New_value@1}}, {gleam@yielder:step(Old_rest@1), gleam@yielder:step(New_rest@1)}} end end end. -file("src/trove/internal/btree/diff.gleam", 62). ?DOC(false). -spec lazy_merge_diff( gleam@yielder:yielder({OBN, OBO}), gleam@yielder:yielder({OBN, OBO}), fun((OBN, OBN) -> gleam@order:order()) ) -> gleam@yielder:yielder({OBN, entry(OBO)}). lazy_merge_diff(Old, New, Compare) -> gleam@yielder:unfold( {gleam@yielder:step(Old), gleam@yielder:step(New)}, fun(State) -> {Old_step, New_step} = State, do_merge_step(Old_step, New_step, Compare) end ). -file("src/trove/internal/btree/diff.gleam", 23). ?DOC(false). -spec diff( trove@internal@btree:btree(OBD, OBE), trove@internal@btree:btree(OBD, OBE), trove@internal@store:store(), trove@codec:codec(OBD), trove@codec:codec(OBE), fun((OBD, OBD) -> gleam@order:order()) ) -> gleam@yielder:yielder({OBD, entry(OBE)}). diff(Old, New, Store, Key_codec, Value_codec, Compare) -> gleam@bool:guard( trove@internal@btree:root(Old) =:= trove@internal@btree:root(New), gleam@yielder:empty(), fun() -> Old_yielder = trove@internal@btree@range:'query'( Old, Store, none, none, forward, Key_codec, Value_codec, Compare ), New_yielder = trove@internal@btree@range:'query'( New, Store, none, none, forward, Key_codec, Value_codec, Compare ), lazy_merge_diff(Old_yielder, New_yielder, Compare) end ).