@@ -1287,7 +1287,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
12871287 /// assert_eq!(a[&5], "f");
12881288 /// ```
12891289 #[ unstable( feature = "btree_merge" , issue = "152152" ) ]
1290- pub fn merge ( & mut self , mut other : Self , conflict : impl FnMut ( & K , V , V ) -> V )
1290+ pub fn merge ( & mut self , mut other : Self , mut conflict : impl FnMut ( & K , V , V ) -> V )
12911291 where
12921292 K : Ord ,
12931293 A : Clone ,
@@ -1303,16 +1303,75 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
13031303 return ;
13041304 }
13051305
1306- let self_iter = mem:: replace ( self , Self :: new_in ( ( * self . alloc ) . clone ( ) ) ) . into_iter ( ) ;
1307- let other_iter = mem:: replace ( & mut other, Self :: new_in ( ( * self . alloc ) . clone ( ) ) ) . into_iter ( ) ;
1308- let root = self . root . get_or_insert_with ( || Root :: new ( ( * self . alloc ) . clone ( ) ) ) ;
1309- root. merge_from_sorted_iters_with (
1310- self_iter,
1311- other_iter,
1312- & mut self . length ,
1313- ( * self . alloc ) . clone ( ) ,
1314- conflict,
1315- )
1306+ let mut other_iter = other. into_iter ( ) ;
1307+ let ( first_other_key, first_other_val) = other_iter. next ( ) . unwrap ( ) ;
1308+
1309+ // find the first gap that has the smallest key greater than or equal to
1310+ // the first key from other
1311+ let mut self_cursor = self . lower_bound_mut ( Bound :: Included ( & first_other_key) ) ;
1312+
1313+ if let Some ( ( self_key, _) ) = self_cursor. peek_next ( ) {
1314+ match K :: cmp ( & first_other_key, self_key) {
1315+ Ordering :: Equal => {
1316+ self_cursor. with_next ( |self_key, self_val| {
1317+ conflict ( self_key, self_val, first_other_val)
1318+ } ) ;
1319+ }
1320+ Ordering :: Less =>
1321+ // SAFETY: we know our other_key's ordering is less than self_key,
1322+ // so inserting before will guarantee sorted order
1323+ unsafe {
1324+ self_cursor. insert_before_unchecked ( first_other_key, first_other_val) ;
1325+ } ,
1326+ Ordering :: Greater => {
1327+ unreachable ! ( "Cursor's peek_next should return None." ) ;
1328+ }
1329+ }
1330+ } else {
1331+ // SAFETY: reaching here means our cursor is at the end
1332+ // self BTreeMap so we just insert other_key here
1333+ unsafe {
1334+ self_cursor. insert_before_unchecked ( first_other_key, first_other_val) ;
1335+ }
1336+ }
1337+
1338+ for ( other_key, other_val) in other_iter {
1339+ loop {
1340+ if let Some ( ( self_key, _) ) = self_cursor. peek_next ( ) {
1341+ match K :: cmp ( & other_key, self_key) {
1342+ Ordering :: Equal => {
1343+ self_cursor. with_next ( |self_key, self_val| {
1344+ conflict ( self_key, self_val, other_val)
1345+ } ) ;
1346+ break ;
1347+ }
1348+ Ordering :: Less => {
1349+ // SAFETY: we know our other_key's ordering is less than self_key,
1350+ // so inserting before will guarantee sorted order
1351+ unsafe {
1352+ self_cursor. insert_before_unchecked ( other_key, other_val) ;
1353+ }
1354+ break ;
1355+ }
1356+ Ordering :: Greater => {
1357+ // FIXME: instead of doing a linear search here,
1358+ // this can be optimized to search the tree by starting
1359+ // from self_cursor and going towards the root and then
1360+ // back down to the proper node -- that should probably
1361+ // be a new method on Cursor*.
1362+ self_cursor. next ( ) ;
1363+ }
1364+ }
1365+ } else {
1366+ // SAFETY: reaching here means our cursor is at the end
1367+ // self BTreeMap so we just insert other_key here
1368+ unsafe {
1369+ self_cursor. insert_before_unchecked ( other_key, other_val) ;
1370+ }
1371+ break ;
1372+ }
1373+ }
1374+ }
13161375 }
13171376
13181377 /// Constructs a double-ended iterator over a sub-range of elements in the map.
@@ -3337,6 +3396,37 @@ impl<'a, K, V, A> CursorMutKey<'a, K, V, A> {
33373396
33383397// Now the tree editing operations
33393398impl < ' a , K : Ord , V , A : Allocator + Clone > CursorMutKey < ' a , K , V , A > {
3399+ /// Calls a function with ownership of the next element's key and
3400+ /// and value and expects it to return a value to write
3401+ /// back to the next element's key and value. The cursor is not
3402+ /// advanced forward.
3403+ ///
3404+ /// If the cursor is at the end of the map then the function is not called
3405+ /// and this essentially does not do anything.
3406+ ///
3407+ /// # Safety
3408+ ///
3409+ /// You must ensure that the `BTreeMap` invariants are maintained.
3410+ /// Specifically:
3411+ ///
3412+ /// * The next element's key must be unique in the tree.
3413+ /// * All keys in the tree must remain in sorted order.
3414+ #[ allow( dead_code) ] /* This function exists for consistency with CursorMut */
3415+ pub ( super ) fn with_next ( & mut self , f : impl FnOnce ( K , V ) -> ( K , V ) ) {
3416+ // if `f` unwinds, the next entry is already removed leaving
3417+ // the tree in valid state.
3418+ // FIXME: Once `MaybeDangling` is implemented, we can optimize
3419+ // this through using a drop handler and transmutating CursorMutKey<K, V>
3420+ // to CursorMutKey<ManuallyDrop<K>, ManuallyDrop<V>> (see PR #152418)
3421+ if let Some ( ( k, v) ) = self . remove_next ( ) {
3422+ // SAFETY: we remove the K, V out of the next entry,
3423+ // apply 'f' to get a new (K, V), and insert it back
3424+ // into the next entry that the cursor is pointing at
3425+ let ( k, v) = f ( k, v) ;
3426+ unsafe { self . insert_after_unchecked ( k, v) } ;
3427+ }
3428+ }
3429+
33403430 /// Inserts a new key-value pair into the map in the gap that the
33413431 /// cursor is currently pointing to.
33423432 ///
@@ -3542,6 +3632,29 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> {
35423632}
35433633
35443634impl < ' a , K : Ord , V , A : Allocator + Clone > CursorMut < ' a , K , V , A > {
3635+ /// Calls a function with a reference to the next element's key and
3636+ /// ownership of its value. The function is expected to return a value
3637+ /// to write back to the next element's value. The cursor is not
3638+ /// advanced forward.
3639+ ///
3640+ /// If the cursor is at the end of the map then the function is not called
3641+ /// and this essentially does not do anything.
3642+ pub ( super ) fn with_next ( & mut self , f : impl FnOnce ( & K , V ) -> V ) {
3643+ // FIXME: This can be optimized to not do all the removing/reinserting
3644+ // logic by using ptr::read, calling `f`, and then using ptr::write.
3645+ // if `f` unwinds, then we need to remove the entry while being careful to
3646+ // not cause UB by moving or dropping the already-dropped `V`
3647+ // for the entry. Some implementation ideas:
3648+ // https://github.com/rust-lang/rust/pull/152418#discussion_r2800232576
3649+ if let Some ( ( k, v) ) = self . remove_next ( ) {
3650+ // SAFETY: we remove the K, V out of the next entry,
3651+ // apply 'f' to get a new V, and insert (K, V) back
3652+ // into the next entry that the cursor is pointing at
3653+ let v = f ( & k, v) ;
3654+ unsafe { self . insert_after_unchecked ( k, v) } ;
3655+ }
3656+ }
3657+
35453658 /// Inserts a new key-value pair into the map in the gap that the
35463659 /// cursor is currently pointing to.
35473660 ///
0 commit comments