btree-slab-0.6.1/.cargo_vcs_info.json0000644000000001360000000000100130600ustar { "git": { "sha1": "fb67001e9e42a896f3ee20ebccbd0024ffc39f5c" }, "path_in_vcs": "" }btree-slab-0.6.1/.github/FUNDING.yml000064400000000000000000000000251046102023000150220ustar 00000000000000patreon: thaudebourg btree-slab-0.6.1/.github/workflows/ci.yml000064400000000000000000000026141046102023000163660ustar 00000000000000name: CI on: [push, pull_request] env: CARGO_TERM_COLORS: always jobs: test: name: Test Suite runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: nightly profile: minimal override: true - name: Build run: cargo build --all-features --verbose - name: Run tests run: cargo test --all-features --verbose rustfmt: name: rustfmt runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: nightly profile: minimal override: true components: rustfmt - name: Check formatting uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check clippy: name: clippy runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: nightly profile: minimal override: true components: clippy - name: Clippy Check uses: actions-rs/cargo@v1 with: command: clippy args: --all-features -- -D warningsbtree-slab-0.6.1/.gitignore000064400000000000000000000000221046102023000136320ustar 00000000000000target Cargo.lock btree-slab-0.6.1/.rustfmt.toml000064400000000000000000000000201046102023000143170ustar 00000000000000hard_tabs = truebtree-slab-0.6.1/.vscode/launch.json000064400000000000000000000023321046102023000153560ustar 00000000000000{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "Debug unit tests in library 'local-btree'", "cargo": { "args": [ "test", "--no-run", "--lib", "--package=local-btree" ], "filter": { "name": "local-btree", "kind": "lib" } }, "args": [], "cwd": "${workspaceFolder}" }, { "type": "lldb", "request": "launch", "name": "Debug integration test 'iter'", "cargo": { "args": [ "test", "--no-run", "--test=iter", "--package=local-btree" ], "filter": { "name": "iter", "kind": "test" } }, "args": ["--nocapture"], "cwd": "${workspaceFolder}" }, { "type": "lldb", "request": "launch", "name": "Debug integration test 'basic'", "cargo": { "args": [ "test", "--no-run", "--test=basic", "--package=local-btree" ], "filter": { "name": "basic", "kind": "test" } }, "args": [], "cwd": "${workspaceFolder}" } ] }btree-slab-0.6.1/Cargo.toml0000644000000022730000000000100110620ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "btree-slab" version = "0.6.1" authors = ["Timothée Haudebourg "] description = "A memory compact Slab-based B-tree implementation" documentation = "https://docs.rs/btree-slab" readme = "README.md" keywords = [ "btree", "map", "set", "slab", ] categories = ["data-structures"] license = "MIT/Apache-2.0" repository = "https://github.com/timothee-haudebourg/btree-slab" [dependencies.cc-traits] version = "2.0" [dependencies.slab] version = "0.4.5" optional = true [dependencies.smallvec] version = "1.8.0" [dev-dependencies.rand] version = "0.8.5" features = ["small_rng"] [features] default = ["std-slab"] dot = [] std-slab = [ "slab", "cc-traits/slab", ] btree-slab-0.6.1/Cargo.toml.orig000064400000000000000000000012501046102023000145350ustar 00000000000000[package] name = "btree-slab" version = "0.6.1" authors = ["Timothée Haudebourg "] edition = "2021" categories = ["data-structures"] keywords = ["btree", "map", "set", "slab"] description = "A memory compact Slab-based B-tree implementation" repository = "https://github.com/timothee-haudebourg/btree-slab" documentation = "https://docs.rs/btree-slab" license = "MIT/Apache-2.0" readme = "README.md" [features] default = ["std-slab"] dot = [] std-slab = ["slab", "cc-traits/slab"] [dependencies] smallvec = "1.8.0" cc-traits = "2.0" slab = { version = "0.4.5", optional = true } [dev-dependencies] rand = { version = "0.8.5", features = ["small_rng"] } btree-slab-0.6.1/LICENSE-APACHE000064400000000000000000000251371046102023000136040ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. btree-slab-0.6.1/LICENSE-MIT000064400000000000000000000017771046102023000133200ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. btree-slab-0.6.1/README.md000064400000000000000000000103041046102023000131250ustar 00000000000000# Slab-based B-Tree implementation [![CI](https://github.com/timothee-haudebourg/btree-slab/workflows/CI/badge.svg)](https://github.com/timothee-haudebourg/btree-slab/actions) [![Crate informations](https://img.shields.io/crates/v/btree-slab.svg?style=flat-square)](https://crates.io/crates/btree-slab) [![License](https://img.shields.io/crates/l/btree-slab.svg?style=flat-square)](https://github.com/timothee-haudebourg/btree-slab#license) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/btree-slab) This crate provides an alternative implementation to the standard `BTreeMap` and `BTreeSet` data structures based on a slab data-structure. In principle, this implementation is more flexible and more memory efficient. It is more flexible by providing an extended set of low-level operations on B-Trees through the `BTreeExt` trait which can be used to further extend the functionalities of the `BTreeMap` collection. In addition, the underlying node allocation scheme is abstracted by a type parameter that can be instantiated by any data structure implementing slab-like operations. By default, the `Slab` type (from the `slab` crate) is used, which means that every node of the tree are allocated in a contiguous memory region, reducing the number of allocations needed. In theory, another type could be used to store the entire B-Tree on the stack. ### Usage From the user point of view, the collection provided by this crate can be used just like the standard `BTreeMap` and `BTreeSet` collections. ```rust use btree_slab::BTreeMap; // type inference lets us omit an explicit type signature (which // would be `BTreeMap<&str, &str>` in this example). let mut movie_reviews = BTreeMap::new(); // review some movies. movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); movie_reviews.insert("Pulp Fiction", "Masterpiece."); movie_reviews.insert("The Godfather", "Very enjoyable."); movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); // check for a specific one. if !movie_reviews.contains_key("Les Misérables") { println!("We've got {} reviews, but Les Misérables ain't one.", movie_reviews.len()); } // oops, this review has a lot of spelling mistakes, let's delete it. movie_reviews.remove("The Blues Brothers"); // look up the values associated with some keys. let to_find = ["Up!", "Office Space"]; for movie in &to_find { match movie_reviews.get(movie) { Some(review) => println!("{}: {}", movie, review), None => println!("{} is unreviewed.", movie) } } // Look up the value for a key (will panic if the key is not found). println!("Movie review: {}", movie_reviews["Office Space"]); // iterate over everything. for (movie, review) in &movie_reviews { println!("{}: \"{}\"", movie, review); } ``` #### Custom node allocation One can use `btree_slab::generic::BTreeMap` to use a custom slab type to handle nodes allocation. ```rust use slab::Slab; use btree_slab::generic::BTreeMap; let mut map: BTreeMap>> = BTreeMap::new(); ``` In this example, the `Slab>` type is a slab-like data structure responsible for the nodes allocation. It must implement all the traits defining the `cc_traits::Slab` trait alias. ### Extended API & Addressing In this implementation of B-Trees, each node of a tree is addressed by the `Address` type. The extended API, visible through the `BTreeExt` trait, allows the caller to explore, access and modify the internal structure of the tree using this addressing system. This can be used to further extend the functionalities of the `BTreeMap` collection, for example in the [`btree-range-map`](https://crates.io/crates/btree-range-map) crate. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. btree-slab-0.6.1/README.tpl000064400000000000000000000020451046102023000133270ustar 00000000000000# Slab-based B-Tree implementation [![CI](https://github.com/timothee-haudebourg/{{crate}}/workflows/CI/badge.svg)](https://github.com/timothee-haudebourg/{{crate}}/actions) [![Crate informations](https://img.shields.io/crates/v/{{crate}}.svg?style=flat-square)](https://crates.io/crates/{{crate}}) [![License](https://img.shields.io/crates/l/{{crate}}.svg?style=flat-square)](https://github.com/timothee-haudebourg/{{crate}}#license) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/{{crate}}) {{readme}} ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. btree-slab-0.6.1/src/generic/map/entry.rs000064400000000000000000000271251046102023000163460ustar 00000000000000use crate::generic::{ map::{BTreeExt, BTreeExtMut, BTreeMap}, node::{Address, Item, Node}, }; use cc_traits::{SimpleCollectionMut, SimpleCollectionRef, Slab, SlabMut}; use std::fmt; /// A view into a single entry in a map, which may either be vacant or occupied. /// /// This enum is constructed from the [`entry`](`BTreeMap#entry`) method on [`BTreeMap`]. pub enum Entry<'a, K, V, C = slab::Slab>> { Vacant(VacantEntry<'a, K, V, C>), Occupied(OccupiedEntry<'a, K, V, C>), } use Entry::*; impl<'a, K, V, C: Slab>> Entry<'a, K, V, C> where C: SimpleCollectionRef, { /// Gets the address of the entry in the B-Tree. #[inline] pub fn address(&self) -> Address { match self { Occupied(entry) => entry.address(), Vacant(entry) => entry.address(), } } /// Returns a reference to this entry's key. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` #[inline] pub fn key(&self) -> &K { match *self { Occupied(ref entry) => entry.key(), Vacant(ref entry) => entry.key(), } } } impl<'a, K, V, C: SlabMut>> Entry<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); /// ``` #[inline] pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), } } /// Ensures a value is in the entry by inserting the result of the default function if empty, /// and returns a mutable reference to the value in the entry. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); /// let s = "hoho".to_string(); /// /// map.entry("poneyland").or_insert_with(|| s); /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` #[inline] pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), } } /// Ensures a value is in the entry by inserting, if empty, the result of the default function, /// which takes the key as its argument, and returns a mutable reference to the value in the /// entry. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); /// /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => { let value = default(entry.key()); entry.insert(value) } } } /// Provides in-place mutable access to an occupied entry before any /// potential inserts into the map. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// /// map.entry("poneyland") /// .and_modify(|e| { *e += 1 }) /// .or_insert(42); /// assert_eq!(map["poneyland"], 42); /// /// map.entry("poneyland") /// .and_modify(|e| { *e += 1 }) /// .or_insert(42); /// assert_eq!(map["poneyland"], 43); /// ``` #[inline] pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut V), { match self { Occupied(mut entry) => { f(entry.get_mut()); Occupied(entry) } Vacant(entry) => Vacant(entry), } } /// Ensures a value is in the entry by inserting the default value if empty, /// and returns a mutable reference to the value in the entry. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); /// map.entry("poneyland").or_default(); /// /// assert_eq!(map["poneyland"], None); /// ``` #[inline] pub fn or_default(self) -> &'a mut V where V: Default, { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(Default::default()), } } } impl<'a, K: fmt::Debug, V: fmt::Debug, C: Slab>> fmt::Debug for Entry<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Occupied(entry) => entry.fmt(f), Vacant(entry) => entry.fmt(f), } } } /// A view into a vacant entry in a [`BTreeMap`]. /// It is part of the [`Entry`] enum. pub struct VacantEntry<'a, K, V, C = slab::Slab>> { pub(crate) map: &'a mut BTreeMap, pub(crate) key: K, pub(crate) addr: Address, } impl<'a, K, V, C: Slab>> VacantEntry<'a, K, V, C> { /// Gets the address of the vacant entry in the B-Tree. #[inline] pub fn address(&self) -> Address { self.addr } /// Gets a reference to the keys that would be used when inserting a value through the `VacantEntry`. /// /// ## Example /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` #[inline] pub fn key(&self) -> &K { &self.key } /// Take ownership of the key. /// /// ## Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// /// if let Entry::Vacant(v) = map.entry("poneyland") { /// v.into_key(); /// } /// ``` #[inline] pub fn into_key(self) -> K { self.key } } impl<'a, K, V, C: SlabMut>> VacantEntry<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Sets the value of the entry with the `VacantEntry`'s key, /// and returns a mutable reference to it. /// /// ## Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, u32> = BTreeMap::new(); /// /// if let Entry::Vacant(o) = map.entry("poneyland") { /// o.insert(37); /// } /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] pub fn insert(self, value: V) -> &'a mut V { let addr = self.map.insert_at(self.addr, Item::new(self.key, value)); self.map.item_mut(addr).unwrap().value_mut() } } impl<'a, K: fmt::Debug, V, C: Slab>> fmt::Debug for VacantEntry<'a, K, V, C> { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry").field(self.key()).finish() } } /// A view into an occupied entry in a [`BTreeMap`]. /// It is part of the [`Entry`] enum. pub struct OccupiedEntry<'a, K, V, C = slab::Slab>> { pub(crate) map: &'a mut BTreeMap, pub(crate) addr: Address, } impl<'a, K, V, C: Slab>> OccupiedEntry<'a, K, V, C> where C: SimpleCollectionRef, { /// Gets the address of the occupied entry in the B-Tree. #[inline] pub fn address(&self) -> Address { self.addr } /// Gets a reference to the value in the entry. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// assert_eq!(o.get(), &12); /// } /// ``` #[inline] pub fn get(&self) -> &V { self.map.item(self.addr).unwrap().value() } /// Gets a reference to the key in the entry. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` #[inline] pub fn key(&self) -> &K { self.map.item(self.addr).unwrap().key() } } impl<'a, K, V, C: SlabMut>> OccupiedEntry<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Gets a mutable reference to the value in the entry. /// /// If you need a reference to the OccupiedEntry that may outlive /// the destruction of the Entry value, see into_mut. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); /// if let Entry::Occupied(mut o) = map.entry("poneyland") { /// *o.get_mut() += 10; /// assert_eq!(*o.get(), 22); /// /// // We can use the same Entry multiple times. /// *o.get_mut() += 2; /// } /// assert_eq!(map["poneyland"], 24); /// ``` #[inline] pub fn get_mut(&mut self) -> &mut V { self.map.item_mut(self.addr).unwrap().value_mut() } /// Sets the value of the entry with the OccupiedEntry's key, /// and returns the entry's old value. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(mut o) = map.entry("poneyland") { /// assert_eq!(o.insert(15), 12); /// } /// assert_eq!(map["poneyland"], 15); /// ``` #[inline] pub fn insert(&mut self, value: V) -> V { self.map.item_mut(self.addr).unwrap().set_value(value) } /// Converts the entry into a mutable reference to its value. /// /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. /// /// [`get_mut`]: #method.get_mut /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); /// if let Entry::Occupied(o) = map.entry("poneyland") { /// *o.into_mut() += 10; /// } /// assert_eq!(map["poneyland"], 22); /// ``` #[inline] pub fn into_mut(self) -> &'a mut V { self.map.item_mut(self.addr).unwrap().value_mut() } /// Takes the value of the entry out of the map, and returns it. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// assert_eq!(o.remove(), 12); /// } /// // If we try to get "poneyland"'s value, it'll panic: /// // println!("{}", map["poneyland"]); /// ``` #[inline] pub fn remove(self) -> V { self.map.remove_at(self.addr).unwrap().0.into_value() } /// Take ownership of the key and value from the map. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// use btree_slab::generic::map::Entry; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// // We delete the entry from the map. /// o.remove_entry(); /// } /// /// // If now try to get the value, it will panic: /// // println!("{}", map["poneyland"]); /// ``` #[inline] pub fn remove_entry(self) -> (K, V) { self.map.remove_at(self.addr).unwrap().0.into_pair() } } impl<'a, K: fmt::Debug, V: fmt::Debug, C: Slab>> fmt::Debug for OccupiedEntry<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) .field("value", self.get()) .finish() } } btree-slab-0.6.1/src/generic/map/ext.rs000064400000000000000000001061101046102023000157750ustar 00000000000000use crate::generic::{ map::{BTreeMap, M}, node::{Address, Balance, Item, Node, Offset}, }; use cc_traits::{SimpleCollectionMut, SimpleCollectionRef, Slab, SlabMut}; use smallvec::SmallVec; use std::{borrow::Borrow, mem::MaybeUninit}; /// Extended API. /// /// This trait can be imported to access the internal functions of the B-Tree. /// These functions are not intended to be directly called by the users, but can be used to /// extends the data structure with new functionalities. /// /// # Addressing /// /// In this implementation of B-Trees, each node of a tree is addressed /// by the [`Address`] type. /// Each node is identified by a `usize`, and each item/entry in the node by an [`Offset`]. /// This extended API allows the caller to explore, access and modify the /// internal structure of the tree using this addressing system. /// /// Note that a valid address does not always refer to an actual item in the tree. /// See the [`Address`] type documentation for more details. pub trait BTreeExt { /// Get the root node id. /// /// Returns `None` if the tree is empty. fn root_id(&self) -> Option; /// Get the node associated to the given `id`. /// /// Panics if `id` is out of bounds. fn node(&self, id: usize) -> &Node; /// Get a reference to the value associated to the given `key` in the node `id`, if any. fn get_in(&self, key: &Q, id: usize) -> Option<&V> where K: Borrow, Q: Ord; /// Get a reference to the item located at the given address. fn item(&self, addr: Address) -> Option<&Item>; /// Get the first item address, if any. /// /// Returns the first occupied valid address, or `None` if the tree is empty. fn first_item_address(&self) -> Option
; /// Get the first back address. /// /// The returned address may not be occupied if the tree is empty. fn first_back_address(&self) -> Address; /// Get the last item address, if any. /// /// Returns the last occupied valid address, or `None` if the tree is empty. fn last_item_address(&self) -> Option
; /// Get the last valid address in the tree. fn last_valid_address(&self) -> Address; /// Normalizes the given item address so that an out-of-node-bounds address points to the next item. fn normalize(&self, addr: Address) -> Option
; /// Returns the greatest valid leaf address that directly precedes the given address. /// /// A "leaf address" is an address located in a leaf node. fn leaf_address(&self, addr: Address) -> Address; /// Get the previous item address. /// /// Returns the previous valid occupied address. /// /// The following diagram shows the order between addresses defined by this function. /// ```text /// ┌───────────┐ /// ╔═════════════╪══╗ ╔══╗ │ /// ║ │┌─v─┐║┌─v─┐│ /// ┌───────────╫─────────────││ 0 │║│ 1 ││──────────────────────┐ /// │ ║ │└─v─┘║└─v─┘│ │ /// │ ║ └──╫──╫──╫──┘ │ /// start v │ ║ ║ ║│ ╚══════════════════════╗ │ ^ end /// ║ │ ║ ╔══╝ ╚╪══════════╗ ║ │ ║ /// ┌──╫──────────────┐ ║ ┌──╫──────────────┐ ║ ┌──╫─────╫──┐ /// │ ║ ╔═════╗ │ ║ │ ║ ╔═════╗ │ ║ │ ║ ║ │ /// │┌─v─┐ ┌─^─┐ ┌─v─┐│ ║ │┌─v─┐ ┌─^─┐ ┌─v─┐│ ║ │┌─v─┐ ┌─^─┐│ /// ││ 0 │ │ 1 │ │ 2 ││ ║ ││ 0 │ │ 1 │ │ 2 ││ ║ ││ 0 │ │ 1 ││ /// │└─v─┘ └─^─┘ └─v─┘│ ║ │└─v─┘ └─^─┘ └─v─┘│ ║ │└─v─┘ └─^─┘│ /// │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ │ /// └─────────────────┘ └─────────────────┘ └───────────┘ /// ``` fn previous_item_address(&self, addr: Address) -> Option
; /// Get the previous front address. /// /// A "front address" is a valid address whose offset is less that the number of items in the node. /// If `addr.offset` is equal to `-1`, then it doesn't actually refer to an existing item in the node. /// /// The following diagram shows the order between addresses defined by this function. /// ```text /// ^ end /// ┌─────────║──┐ /// ╔═══════════════╗ │╔══╗ ║ │ /// ║ ┌─v─┐│║┌─v─┐ ┌─^─┐│ /// ┌─────╫─────────────│-1 ││║│ 0 │ │ 1 ││ ─────────────────────┐ /// │ ║ └─v─┘│║└─v─┘ └─^─┘│ │ /// │ ║ ║ └╫──╫─────╫──┘ │ /// │ ║ ║ ║ ║ │ ╚═════════════════════════╪═══════╗ /// start v │ ║ ║ ║ ╚══╪═══════════════════╗ │ ║ /// ║ │ ║ ╔═╝ ╚═════╪═════╗ ║ │ ║ /// ║ ┌──────────────╫──┐ ║ ┌──────────────╫──┐ ║ ┌───────────┐ ║ /// ║ │ ╔═════╗ ║ │ ║ │ ╔═════╗ ║ │ ║ │ ╔═════╗ │ ║ /// ┌─v─┐│┌─^─┐ ┌─v─┐ ┌─^─┐│ ┌─v─┐│┌─^─┐ ┌─v─┐ ┌─^─┐│ ┌─v─┐│┌─^─┐ ┌─v─┐│ ║ /// │-1 │││ 0 │ │ 1 │ │ 2 ││ │-1 │││ 0 │ │ 1 │ │ 2 ││ │-1 │││ 0 │ │ 1 ││ ║ /// └─v─┘│└─^─┘ └─v─┘ └─^─┘│ └─v─┘│└─^─┘ └─v─┘ └─^─┘│ └─v─┘│└─^─┘ └─v─┘│ ║ /// ╚══╪══╝ ╚═════╝ │ ╚══╪══╝ ╚═════╝ │ ╚══╪══╝ ╚══╪═╝ /// └─────────────────┘ └─────────────────┘ └───────────┘ /// ``` fn previous_front_address(&self, addr: Address) -> Option
; /// Get the next item address. /// /// Returns the next valid occupied address. /// /// The following diagram shows the order between addresses defined by this function. /// ```text /// ┌───────────┐ /// ╔═════════════╪══╗ ╔══╗ │ /// ║ │┌─v─┐║┌─v─┐│ /// ┌───────────╫─────────────││ 0 │║│ 1 ││──────────────────────┐ /// │ ║ │└─v─┘║└─v─┘│ │ /// │ ║ └──╫──╫──╫──┘ │ /// start v │ ║ ║ ║│ ╚══════════════════════╗ │ ^ end /// ║ │ ║ ╔══╝ ╚╪══════════╗ ║ │ ║ /// ┌──╫──────────────┐ ║ ┌──╫──────────────┐ ║ ┌──╫─────╫──┐ /// │ ║ ╔═════╗ │ ║ │ ║ ╔═════╗ │ ║ │ ║ ║ │ /// │┌─v─┐ ┌─^─┐ ┌─v─┐│ ║ │┌─v─┐ ┌─^─┐ ┌─v─┐│ ║ │┌─v─┐ ┌─^─┐│ /// ││ 0 │ │ 1 │ │ 2 ││ ║ ││ 0 │ │ 1 │ │ 2 ││ ║ ││ 0 │ │ 1 ││ /// │└─v─┘ └─^─┘ └─v─┘│ ║ │└─v─┘ └─^─┘ └─v─┘│ ║ │└─v─┘ └─^─┘│ /// │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ │ /// └─────────────────┘ └─────────────────┘ └───────────┘ /// ``` fn next_item_address(&self, addr: Address) -> Option
; /// Get the next back address. /// /// A "back address" is a valid address whose offset is at least `0`. /// If `addr.offset` is equal to the number of items in the node then it doesn't actually refer /// to an existing item in the node, /// but it can be used to insert a new item with `BTreeExt::insert_at`. /// /// The following diagram shows the order between addresses defined by this function. /// ```text /// ┌───────────┐ ^ end /// ╔═════════════╪══╗ ╔══╗ │ ║ /// ║ │┌─v─┐║┌─v─┐│┌─^─┐ /// ┌───────────╫─────────────││ 0 │║│ 1 │││ 2 │─────────────────┐ /// │ ║ │└─v─┘║└─v─┘│└─^─┘ │ /// │ ║ └──╫──╫──╫──┘ ╚═══════════════════╪════════════╗ /// start v │ ║ ║ ║│ ╚══════════════════════╗ │ ║ /// ║ │ ║ ╔══╝ ╚╪══════════╗ ║ │ ║ /// ┌──╫──────────────┐ ║ ┌──╫──────────────┐ ║ ┌──╫────────┐ ║ /// │ ║ ╔═════╗ │ ║ │ ║ ╔═════╗ │ ║ │ ║ ╔══╪══╗ ║ /// │┌─v─┐ ┌─^─┐ ┌─v─┐│┌─^─┐ │┌─v─┐ ┌─^─┐ ┌─v─┐│┌─^─┐ │┌─v─┐ ┌─^─┐│┌─v─┐ ║ /// ││ 0 │ │ 1 │ │ 2 │││ 3 │ ││ 0 │ │ 1 │ │ 2 │││ 3 │ ││ 0 │ │ 1 │││ 2 >═╝ /// │└─v─┘ └─^─┘ └─v─┘│└─^─┘ │└─v─┘ └─^─┘ └─v─┘│└─^─┘ │└─v─┘ └─^─┘│└───┘ /// │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ ╚══╪══╝ │ ╚═════╝ │ /// └─────────────────┘ └─────────────────┘ └───────────┘ /// ``` fn next_back_address(&self, addr: Address) -> Option
; /// Get the next item address if any, or the next back address otherwise. fn next_item_or_back_address(&self, addr: Address) -> Option
; /// Get the address of the given key. /// /// Returns `Ok(addr)` if the key is used in the tree. /// If the key is not used in the tree then `Err(addr)` is returned, /// where `addr` can be used to insert the missing key. fn address_of(&self, key: &Q) -> Result where K: Borrow, Q: Ord; /// Search for the address of the given key from the given node `id`. /// /// Users should directly use [`BTreeExt::address_of`]. fn address_in(&self, id: usize, key: &Q) -> Result where K: Borrow, Q: Ord; /// Validate the tree. /// /// Panics if the tree is not a valid B-Tree. #[cfg(debug_assertions)] fn validate(&self) where K: Ord; /// Validate the given node and returns the depth of the node. /// /// Panics if the tree is not a valid B-Tree. #[cfg(debug_assertions)] fn validate_node( &self, id: usize, parent: Option, min: Option<&K>, max: Option<&K>, ) -> usize where K: Ord; } /// Extended mutable API. /// /// This trait can be imported to access and modify the internal functions of the B-Tree. /// These functions are not intended to be directly called by the users, but can be used to /// extends the data structure with new functionalities. /// /// # Correctness /// /// The user of this trait is responsible to preserve the invariants of the data-structure. /// In particular, no item must be modified or inserted in a way that /// break the order between keys. pub trait BTreeExtMut { /// Set the new known number of items in the tree. fn set_len(&mut self, len: usize); /// Set the root node identifier. fn set_root_id(&mut self, id: Option); /// Get the node associated to the given `id` mutably. /// /// Panics if `id` is out of bounds. fn node_mut(&mut self, id: usize) -> &mut Node; /// Get a mutable reference to the value associated to the given `key` in the node `id`, if any. fn get_mut_in(&mut self, key: &K, id: usize) -> Option<&mut V> where K: Ord; /// Get a mutable reference to the item located at the given address. fn item_mut(&mut self, addr: Address) -> Option<&mut Item>; /// Insert an item at the given address. /// /// The address is first converted into a leaf address using [`BTreeExt::leaf_address`] /// and the item inserted using [`BTreeExtMut::insert_exactly_at`]. fn insert_at(&mut self, addr: Address, item: Item) -> Address; /// Insert an item at the given address. /// /// If the address refers to an internal node, /// `opt_right_id` defines the identifier of the child node inserted on the right of the inserted item. /// /// Returns the address of the inserted item in the tree /// (it may differ from the input address if the tree is rebalanced). /// /// # Correctness /// /// It is assumed that it is btree-correct to insert the given item at the given address. /// /// # Panic /// /// This function panics if the address refers to an internal node and `opt_right_id` is `None`. fn insert_exactly_at( &mut self, addr: Address, item: Item, opt_right_id: Option, ) -> Address; /// Replaces the key-value binding at the given address. fn replace_at(&mut self, addr: Address, key: K, value: V) -> (K, V); /// Replaces the value at the given address. fn replace_value_at(&mut self, addr: Address, value: V) -> V; /// Removes the item at the given address, if any. /// /// If an item is removed then /// this function returns a pair where the first hand side is the removed item, /// and the right hand side is the updated address where the item can be reinserted at. fn remove_at(&mut self, addr: Address) -> Option<(Item, Address)>; /// Rebalance a node, if necessary. fn rebalance(&mut self, node_id: usize, addr: Address) -> Address; /// Update a value in the given node `node_id`. fn update_in(&mut self, id: usize, key: K, action: F) -> T where K: Ord, F: FnOnce(Option) -> (Option, T); /// Update a valud at the given address. fn update_at(&mut self, addr: Address, action: F) -> T where K: Ord, F: FnOnce(V) -> (Option, T); /// Take the right-most leaf value in the given node. /// /// Note that this does not change the registred length of the tree. /// The returned item is expected to be reinserted in the tree. fn remove_rightmost_leaf_of(&mut self, node_id: usize) -> (Item, usize); /// Allocate a free identifier for the given node. fn allocate_node(&mut self, node: Node) -> usize; /// Release the given node identifier and return the node it used to identify. fn release_node(&mut self, id: usize) -> Node; } impl>> BTreeExt for BTreeMap where C: SimpleCollectionRef, { #[inline] fn root_id(&self) -> Option { self.root } #[inline] fn node(&self, id: usize) -> &Node { C::into_ref(self.nodes.get(id).unwrap()) } #[inline] fn get_in(&self, key: &Q, mut id: usize) -> Option<&V> where K: Borrow, Q: Ord, { loop { match self.node(id).get(key) { Ok(value_opt) => return value_opt, Err(child_id) => id = child_id, } } } fn item(&self, addr: Address) -> Option<&Item> { self.node(addr.id).item(addr.offset) } fn first_item_address(&self) -> Option
{ match self.root { Some(mut id) => loop { match self.node(id).child_id_opt(0) { Some(child_id) => id = child_id, None => return Some(Address::new(id, 0.into())), } }, None => None, } } fn first_back_address(&self) -> Address { match self.root { Some(mut id) => loop { match self.node(id).child_id_opt(0) { Some(child_id) => id = child_id, None => return Address::new(id, 0.into()), // TODO FIXME thechnically not the first } }, None => Address::nowhere(), } } fn last_item_address(&self) -> Option
{ match self.root { Some(mut id) => loop { let node = self.node(id); let index = node.item_count(); match node.child_id_opt(index) { Some(child_id) => id = child_id, None => return Some(Address::new(id, (index - 1).into())), } }, None => None, } } fn last_valid_address(&self) -> Address { match self.root { Some(mut id) => loop { let node = self.node(id); let index = node.item_count(); match node.child_id_opt(index) { Some(child_id) => id = child_id, None => return Address::new(id, index.into()), } }, None => Address::nowhere(), } } fn normalize(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { None } else { loop { let node = self.node(addr.id); if addr.offset >= node.item_count() { match node.parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.id = parent_id; } None => return None, } } else { return Some(addr); } } } } #[inline] fn leaf_address(&self, mut addr: Address) -> Address { if !addr.is_nowhere() { loop { let node = self.node(addr.id); match node.child_id_opt(addr.offset.unwrap()) { // TODO unwrap may fail here! Some(child_id) => { addr.id = child_id; addr.offset = self.node(child_id).item_count().into() } None => break, } } } addr } /// Get the address of the item located before this address. #[inline] fn previous_item_address(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { return None; } loop { let node = self.node(addr.id); match node.child_id_opt(addr.offset.unwrap()) { // TODO unwrap may fail here. Some(child_id) => { addr.offset = self.node(child_id).item_count().into(); addr.id = child_id; } None => loop { if addr.offset > 0 { addr.offset.decr(); return Some(addr); } match self.node(addr.id).parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.id = parent_id; } None => return None, } }, } } } #[inline] fn previous_front_address(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { return None; } loop { let node = self.node(addr.id); match addr.offset.value() { Some(offset) => { let index = if offset < node.item_count() { offset } else { node.item_count() }; match node.child_id_opt(index) { Some(child_id) => { addr.offset = (self.node(child_id).item_count()).into(); addr.id = child_id; } None => { addr.offset.decr(); break; } } } None => match node.parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.offset.decr(); addr.id = parent_id; break; } None => return None, }, } } Some(addr) } /// Get the address of the item located after this address if any. #[inline] fn next_item_address(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { return None; } let item_count = self.node(addr.id).item_count(); match addr.offset.partial_cmp(&item_count) { Some(std::cmp::Ordering::Less) => { addr.offset.incr(); } Some(std::cmp::Ordering::Greater) => { return None; } _ => (), } // let original_addr_shifted = addr; loop { let node = self.node(addr.id); match node.child_id_opt(addr.offset.unwrap()) { // unwrap may fail here. Some(child_id) => { addr.offset = 0.into(); addr.id = child_id; } None => { loop { let node = self.node(addr.id); if addr.offset < node.item_count() { return Some(addr); } match node.parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.id = parent_id; } None => { // return Some(original_addr_shifted) return None; } } } } } } } #[inline] fn next_back_address(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { return None; } loop { let node = self.node(addr.id); let index = match addr.offset.value() { Some(offset) => offset + 1, None => 0, }; if index <= node.item_count() { match node.child_id_opt(index) { Some(child_id) => { addr.offset = Offset::before(); addr.id = child_id; } None => { addr.offset = index.into(); break; } } } else { match node.parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.id = parent_id; break; } None => return None, } } } Some(addr) } #[inline] fn next_item_or_back_address(&self, mut addr: Address) -> Option
{ if addr.is_nowhere() { return None; } let item_count = self.node(addr.id).item_count(); match addr.offset.partial_cmp(&item_count) { Some(std::cmp::Ordering::Less) => { addr.offset.incr(); } Some(std::cmp::Ordering::Greater) => { return None; } _ => (), } let original_addr_shifted = addr; loop { let node = self.node(addr.id); match node.child_id_opt(addr.offset.unwrap()) { // TODO unwrap may fail here. Some(child_id) => { addr.offset = 0.into(); addr.id = child_id; } None => loop { let node = self.node(addr.id); if addr.offset < node.item_count() { return Some(addr); } match node.parent() { Some(parent_id) => { addr.offset = self.node(parent_id).child_index(addr.id).unwrap().into(); addr.id = parent_id; } None => return Some(original_addr_shifted), } }, } } } fn address_of(&self, key: &Q) -> Result where K: Borrow, Q: Ord, { match self.root { Some(id) => self.address_in(id, key), None => Err(Address::nowhere()), } } fn address_in(&self, mut id: usize, key: &Q) -> Result where K: Borrow, Q: Ord, { loop { match self.node(id).offset_of(key) { Ok(offset) => return Ok(Address { id, offset }), Err((offset, None)) => return Err(Address::new(id, offset.into())), Err((_, Some(child_id))) => { id = child_id; } } } } #[cfg(debug_assertions)] fn validate(&self) where K: Ord, { if let Some(id) = self.root { self.validate_node(id, None, None, None); } } /// Validate the given node and returns the depth of the node. #[cfg(debug_assertions)] fn validate_node( &self, id: usize, parent: Option, mut min: Option<&K>, mut max: Option<&K>, ) -> usize where K: Ord, { let node = self.node(id); node.validate(parent, min, max); let mut depth = None; for (i, child_id) in node.children().enumerate() { let (child_min, child_max) = node.separators(i); let min = child_min.or_else(|| min.take()); let max = child_max.or_else(|| max.take()); let child_depth = self.validate_node(child_id, Some(id), min, max); match depth { None => depth = Some(child_depth), Some(depth) => { if depth != child_depth { panic!("tree not balanced") } } } } match depth { Some(depth) => depth + 1, None => 0, } } } impl>> BTreeExtMut for BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn set_len(&mut self, new_len: usize) { self.len = new_len } #[inline] fn set_root_id(&mut self, id: Option) { self.root = id } #[inline] fn node_mut(&mut self, id: usize) -> &mut Node { C::into_mut(self.nodes.get_mut(id).unwrap()) } #[inline] fn get_mut_in<'a>(&'a mut self, key: &K, mut id: usize) -> Option<&'a mut V> where K: Ord, { // The borrow checker is unable to predict that `*self` // is not borrowed more that once at a time. // That's why we need this little unsafe pointer gymnastic. let value_ptr = loop { match self.node_mut(id).get_mut(key) { Ok(value_opt) => break value_opt.map(|value_ref| value_ref as *mut V), Err(child_id) => id = child_id, } }; unsafe { value_ptr.map(|ptr| &mut *ptr) } } fn item_mut(&mut self, addr: Address) -> Option<&mut Item> { self.node_mut(addr.id).item_mut(addr.offset) } fn insert_at(&mut self, addr: Address, item: Item) -> Address { self.insert_exactly_at(self.leaf_address(addr), item, None) } fn insert_exactly_at( &mut self, addr: Address, item: Item, opt_right_id: Option, ) -> Address { if addr.is_nowhere() { if self.is_empty() { let new_root = Node::leaf(None, item); let id = self.allocate_node(new_root); self.root = Some(id); self.len += 1; Address { id, offset: 0.into(), } } else { panic!("invalid item address") } } else if self.is_empty() { panic!("invalid item address") } else { self.node_mut(addr.id) .insert(addr.offset, item, opt_right_id); let new_addr = self.rebalance(addr.id, addr); self.len += 1; new_addr } } fn replace_at(&mut self, addr: Address, key: K, value: V) -> (K, V) { self.node_mut(addr.id) .item_mut(addr.offset) .unwrap() .set(key, value) } fn replace_value_at(&mut self, addr: Address, value: V) -> V { self.node_mut(addr.id) .item_mut(addr.offset) .unwrap() .set_value(value) } #[inline] fn remove_at(&mut self, addr: Address) -> Option<(Item, Address)> { self.len -= 1; match self.node_mut(addr.id).leaf_remove(addr.offset) { Some(Ok(item)) => { // removed from a leaf. let addr = self.rebalance(addr.id, addr); Some((item, addr)) } Some(Err(left_child_id)) => { // removed from an internal node. let new_addr = self.next_item_or_back_address(addr).unwrap(); let (separator, leaf_id) = self.remove_rightmost_leaf_of(left_child_id); let item = self.node_mut(addr.id).replace(addr.offset, separator); let addr = self.rebalance(leaf_id, new_addr); Some((item, addr)) } None => None, } } fn update_in(&mut self, mut id: usize, key: K, action: F) -> T where K: Ord, F: FnOnce(Option) -> (Option, T), { loop { match self.node(id).offset_of(&key) { Ok(offset) => unsafe { let mut value = MaybeUninit::uninit(); let item = self.node_mut(id).item_mut(offset).unwrap(); std::mem::swap(&mut value, item.maybe_uninit_value_mut()); let (opt_new_value, result) = action(Some(value.assume_init())); match opt_new_value { Some(new_value) => { let mut new_value = MaybeUninit::new(new_value); std::mem::swap(&mut new_value, item.maybe_uninit_value_mut()); } None => { let (item, _) = self.remove_at(Address::new(id, offset)).unwrap(); // item's value is NOT initialized here. // It must not be dropped. item.forget_value() } } return result; }, Err((offset, None)) => { let (opt_new_value, result) = action(None); if let Some(new_value) = opt_new_value { let leaf_addr = Address::new(id, offset.into()); self.insert_exactly_at(leaf_addr, Item::new(key, new_value), None); } return result; } Err((_, Some(child_id))) => { id = child_id; } } } } fn update_at(&mut self, addr: Address, action: F) -> T where K: Ord, F: FnOnce(V) -> (Option, T), { unsafe { let mut value = MaybeUninit::uninit(); let item = self.node_mut(addr.id).item_mut(addr.offset).unwrap(); std::mem::swap(&mut value, item.maybe_uninit_value_mut()); let (opt_new_value, result) = action(value.assume_init()); match opt_new_value { Some(new_value) => { let mut new_value = MaybeUninit::new(new_value); std::mem::swap(&mut new_value, item.maybe_uninit_value_mut()); } None => { let (item, _) = self.remove_at(addr).unwrap(); // item's value is NOT initialized here. // It must not be dropped. item.forget_value() } } result } } #[inline] fn rebalance(&mut self, mut id: usize, mut addr: Address) -> Address { let mut balance = self.node(id).balance(); loop { match balance { Balance::Balanced => break, Balance::Overflow => { assert!(!self.node_mut(id).is_underflowing()); let (median_offset, median, right_node) = self.node_mut(id).split(); let right_id = self.allocate_node(right_node); match self.node(id).parent() { Some(parent_id) => { let parent = self.node_mut(parent_id); let offset = parent.child_index(id).unwrap().into(); parent.insert(offset, median, Some(right_id)); // new address. if addr.id == id { match addr.offset.partial_cmp(&median_offset) { Some(std::cmp::Ordering::Equal) => { addr = Address { id: parent_id, offset, } } Some(std::cmp::Ordering::Greater) => { addr = Address { id: right_id, offset: (addr.offset.unwrap() - median_offset - 1) .into(), } } _ => (), } } else if addr.id == parent_id && addr.offset >= offset { addr.offset.incr() } id = parent_id; balance = parent.balance() } None => { let left_id = id; let new_root = Node::binary(None, left_id, median, right_id); let root_id = self.allocate_node(new_root); self.root = Some(root_id); self.node_mut(left_id).set_parent(Some(root_id)); self.node_mut(right_id).set_parent(Some(root_id)); // new address. if addr.id == id { match addr.offset.partial_cmp(&median_offset) { Some(std::cmp::Ordering::Equal) => { addr = Address { id: root_id, offset: 0.into(), } } Some(std::cmp::Ordering::Greater) => { addr = Address { id: right_id, offset: (addr.offset.unwrap() - median_offset - 1) .into(), } } _ => (), } } break; } }; } Balance::Underflow(is_empty) => { match self.node(id).parent() { Some(parent_id) => { let index = self.node(parent_id).child_index(id).unwrap(); // An underflow append in the child node. // First we try to rebalance the tree by rotation. if self.try_rotate_left(parent_id, index, &mut addr) || self.try_rotate_right(parent_id, index, &mut addr) { break; } else { // Rotation didn't work. // This means that all existing child sibling have enough few elements to be merged with this child. let (new_balance, new_addr) = self.merge(parent_id, index, addr); balance = new_balance; addr = new_addr; // The `merge` function returns the current balance of the parent node, // since it may underflow after the merging operation. id = parent_id } } None => { // if root is empty. if is_empty { self.root = self.node(id).child_id_opt(0); // update root's parent and addr. match self.root { Some(root_id) => { let root = self.node_mut(root_id); root.set_parent(None); if addr.id == id { addr.id = root_id; addr.offset = root.item_count().into() } } None => addr = Address::nowhere(), } self.release_node(id); } break; } } } } } addr } #[inline] fn remove_rightmost_leaf_of(&mut self, mut id: usize) -> (Item, usize) { loop { match self.node_mut(id).remove_rightmost_leaf() { Ok(result) => return (result, id), Err(child_id) => { id = child_id; } } } } #[inline] fn allocate_node(&mut self, node: Node) -> usize { let mut children: SmallVec<[usize; M]> = SmallVec::new(); let id = self.nodes.insert(node); for child_id in self.node(id).children() { children.push(child_id) } for child_id in children { self.node_mut(child_id).set_parent(Some(id)) } id } #[inline] fn release_node(&mut self, id: usize) -> Node { self.nodes.remove(id).unwrap() } } btree-slab-0.6.1/src/generic/map.rs000064400000000000000000001741041046102023000152050ustar 00000000000000use crate::generic::node::{Address, Balance, Item, Node, WouldUnderflow}; use cc_traits::{SimpleCollectionMut, SimpleCollectionRef, Slab, SlabMut}; use std::{ borrow::Borrow, cmp::Ordering, hash::{Hash, Hasher}, iter::{DoubleEndedIterator, ExactSizeIterator, FromIterator, FusedIterator}, marker::PhantomData, ops::{Bound, Index, RangeBounds}, }; mod entry; mod ext; pub use entry::*; pub use ext::*; /// Knuth order of the B-Trees. /// /// Must be at least 4. pub const M: usize = 8; /// A map based on a B-Tree. /// /// This offers an alternative over the standard implementation of B-Trees where nodes are /// allocated in a contiguous array of [`Node`]s, reducing the cost of tree nodes allocations. /// In addition the crate provides advanced functions to iterate through and update the map /// efficiently. /// /// # Basic usage /// /// Basic usage is similar to the map data structures offered by the standard library. /// ``` /// use btree_slab::BTreeMap; /// /// // type inference lets us omit an explicit type signature (which /// // would be `BTreeMap<&str, &str>` in this example). /// let mut movie_reviews = BTreeMap::new(); /// /// // review some movies. /// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); /// movie_reviews.insert("Pulp Fiction", "Masterpiece."); /// movie_reviews.insert("The Godfather", "Very enjoyable."); /// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); /// /// // check for a specific one. /// if !movie_reviews.contains_key("Les Misérables") { /// println!("We've got {} reviews, but Les Misérables ain't one.", /// movie_reviews.len()); /// } /// /// // oops, this review has a lot of spelling mistakes, let's delete it. /// movie_reviews.remove("The Blues Brothers"); /// /// // look up the values associated with some keys. /// let to_find = ["Up!", "Office Space"]; /// for movie in &to_find { /// match movie_reviews.get(movie) { /// Some(review) => println!("{}: {}", movie, review), /// None => println!("{} is unreviewed.", movie) /// } /// } /// /// // Look up the value for a key (will panic if the key is not found). /// println!("Movie review: {}", movie_reviews["Office Space"]); /// /// // iterate over everything. /// for (movie, review) in &movie_reviews { /// println!("{}: \"{}\"", movie, review); /// } /// ``` /// /// # Advanced usage /// /// ## Entry API /// /// This crate also reproduces the Entry API defined by the standard library, /// which allows for more complex methods of getting, setting, updating and removing keys and /// their values: /// ``` /// use btree_slab::BTreeMap; /// /// // type inference lets us omit an explicit type signature (which /// // would be `BTreeMap<&str, u8>` in this example). /// let mut player_stats: BTreeMap<&str, u8> = BTreeMap::new(); /// /// fn random_stat_buff() -> u8 { /// // could actually return some random value here - let's just return /// // some fixed value for now /// 42 /// } /// /// // insert a key only if it doesn't already exist /// player_stats.entry("health").or_insert(100); /// /// // insert a key using a function that provides a new value only if it /// // doesn't already exist /// player_stats.entry("defence").or_insert_with(random_stat_buff); /// /// // update a key, guarding against the key possibly not being set /// let stat = player_stats.entry("attack").or_insert(100); /// *stat += random_stat_buff(); /// ``` /// /// ## Mutable iterators /// /// This type provides two iterators providing mutable references to the entries: /// - [`IterMut`] is a double-ended iterator following the standard /// [`std::collections::btree_map::IterMut`] implementation. /// - [`EntriesMut`] is a single-ended iterator that allows, in addition, /// insertion and deletion of entries at the current iterator's position in the map. /// An example is given below. /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert("a", 1); /// map.insert("b", 2); /// map.insert("d", 4); /// /// let mut entries = map.entries_mut(); /// entries.next(); /// entries.next(); /// entries.insert("c", 3); // the inserted key must preserve the order of the map. /// /// let entries: Vec<_> = map.into_iter().collect(); /// assert_eq!(entries, vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]); /// ``` /// /// ## Custom allocation /// /// This data structure is built on top of a slab data structure, /// but is agnostic of the actual slab implementation which is taken as parameter (`C`). /// If the `slab` feature is enabled, /// the [`slab::Slab`] implementation is used by default by reexporting /// `BTreeMap>` at the root of the crate. /// Any container implementing "slab-like" functionalities can be used. /// /// ## Extended API /// /// This crate provides the two traits [`BTreeExt`] and [`BTreeExtMut`] that can be imported to /// expose low-level operations on [`BTreeMap`]. /// The extended API allows the caller to directly navigate and access the entries of the tree /// using their [`Address`]. /// These functions are not intended to be directly called by the users, /// but can be used to extend the data structure with new functionalities. /// /// # Correctness /// /// It is a logic error for a key to be modified in such a way that the key's ordering relative /// to any other key, as determined by the [`Ord`] trait, changes while it is in the map. /// This is normally only possible through [`Cell`](`std::cell::Cell`), /// [`RefCell`](`std::cell::RefCell`), global state, I/O, or unsafe code. #[derive(Clone)] pub struct BTreeMap { /// Allocated and free nodes. nodes: C, /// Root node id. root: Option, /// Number of items in the tree. len: usize, k: PhantomData, v: PhantomData, } impl BTreeMap { /// Create a new empty B-tree. #[inline] pub fn new() -> BTreeMap where C: Default, { BTreeMap { nodes: Default::default(), root: None, len: 0, k: PhantomData, v: PhantomData, } } /// Returns `true` if the map contains no elements. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// assert!(a.is_empty()); /// a.insert(1, "a"); /// assert!(!a.is_empty()); /// ``` #[inline] pub fn is_empty(&self) -> bool { self.root.is_none() } /// Returns the number of elements in the map. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// assert_eq!(a.len(), 0); /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` #[inline] pub fn len(&self) -> usize { self.len } } impl>> BTreeMap where C: SimpleCollectionRef, { /// Returns the key-value pair corresponding to the supplied key. /// /// The supplied key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap = BTreeMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); /// assert_eq!(map.get_key_value(&2), None); /// ``` #[inline] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord, { match self.root { Some(id) => self.get_in(key, id), None => None, } } /// Returns the key-value pair corresponding to the supplied key. /// /// The supplied key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Examples /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); /// assert_eq!(map.get_key_value(&2), None); /// ``` #[inline] pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Ord, { match self.address_of(k) { Ok(addr) => { let item = self.item(addr).unwrap(); Some((item.key(), item.value())) } Err(_) => None, } } /// Returns the first key-value pair in the map. /// The key in this pair is the minimum key in the map. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// assert_eq!(map.first_key_value(), None); /// map.insert(1, "b"); /// map.insert(2, "a"); /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); /// ``` #[inline] pub fn first_key_value(&self) -> Option<(&K, &V)> { match self.first_item_address() { Some(addr) => { let item = self.item(addr).unwrap(); Some((item.key(), item.value())) } None => None, } } /// Returns the last key-value pair in the map. /// The key in this pair is the maximum key in the map. /// /// # Examples /// /// Basic usage: /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "b"); /// map.insert(2, "a"); /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); /// ``` #[inline] pub fn last_key_value(&self) -> Option<(&K, &V)> { match self.last_item_address() { Some(addr) => { let item = self.item(addr).unwrap(); Some((item.key(), item.value())) } None => None, } } /// Gets an iterator over the entries of the map, sorted by key. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(3, "c"); /// map.insert(2, "b"); /// map.insert(1, "a"); /// /// for (key, value) in map.iter() { /// println!("{}: {}", key, value); /// } /// /// let (first_key, first_value) = map.iter().next().unwrap(); /// assert_eq!((*first_key, *first_value), (1, "a")); /// ``` #[inline] pub fn iter(&self) -> Iter { Iter::new(self) } /// Gets an iterator over the keys of the map, in sorted order. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(2, "b"); /// a.insert(1, "a"); /// /// let keys: Vec<_> = a.keys().cloned().collect(); /// assert_eq!(keys, [1, 2]); /// ``` #[inline] pub fn keys(&self) -> Keys { Keys { inner: self.iter() } } /// Gets an iterator over the values of the map, in order by key. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, "hello"); /// a.insert(2, "goodbye"); /// /// let values: Vec<&str> = a.values().cloned().collect(); /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[inline] pub fn values(&self) -> Values { Values { inner: self.iter() } } /// Constructs a double-ended iterator over a sub-range of elements in the map. /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will /// yield elements from min (inclusive) to max (exclusive). /// The range may also be entered as `(Bound, Bound)`, so for example /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive /// range from 4 to 10. /// /// # Panics /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// use std::ops::Bound::Included; /// /// let mut map = BTreeMap::new(); /// map.insert(3, "a"); /// map.insert(5, "b"); /// map.insert(8, "c"); /// for (&key, &value) in map.range((Included(&4), Included(&8))) { /// println!("{}: {}", key, value); /// } /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); /// ``` #[inline] pub fn range(&self, range: R) -> Range where T: Ord, K: Borrow, R: RangeBounds, { Range::new(self, range) } /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Example /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap = BTreeMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); /// ``` #[inline] pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Ord, { self.get(key).is_some() } /// Write the tree in the DOT graph descrption language. /// /// Requires the `dot` feature. #[cfg(feature = "dot")] #[inline] pub fn dot_write(&self, f: &mut W) -> std::io::Result<()> where K: std::fmt::Display, V: std::fmt::Display, { write!(f, "digraph tree {{\n\tnode [shape=record];\n")?; if let Some(id) = self.root { self.dot_write_node(f, id)? } write!(f, "}}") } /// Write the given node in the DOT graph descrption language. /// /// Requires the `dot` feature. #[cfg(feature = "dot")] #[inline] fn dot_write_node(&self, f: &mut W, id: usize) -> std::io::Result<()> where K: std::fmt::Display, V: std::fmt::Display, { let name = format!("n{}", id); let node = self.node(id); write!(f, "\t{} [label=\"", name)?; if let Some(parent) = node.parent() { write!(f, "({})|", parent)?; } node.dot_write_label(f)?; writeln!(f, "({})\"];", id)?; for child_id in node.children() { self.dot_write_node(f, child_id)?; let child_name = format!("n{}", child_id); writeln!(f, "\t{} -> {}", name, child_name)?; } Ok(()) } } impl>> BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Clears the map, removing all elements. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, "a"); /// a.clear(); /// assert!(a.is_empty()); /// ``` #[inline] pub fn clear(&mut self) where C: cc_traits::Clear, { self.root = None; self.len = 0; self.nodes.clear() } /// Returns a mutable reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// if let Some(x) = map.get_mut(&1) { /// *x = "b"; /// } /// assert_eq!(map[&1], "b"); /// ``` #[inline] pub fn get_mut(&mut self, key: &K) -> Option<&mut V> where K: Ord, { match self.root { Some(id) => self.get_mut_in(key, id), None => None, } } /// Gets the given key's corresponding entry in the map for in-place manipulation. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut letters = BTreeMap::new(); /// /// for ch in "a short treatise on fungi".chars() { /// let counter = letters.entry(ch).or_insert(0); /// *counter += 1; /// } /// /// assert_eq!(letters[&'s'], 2); /// assert_eq!(letters[&'t'], 3); /// assert_eq!(letters[&'u'], 1); /// assert_eq!(letters.get(&'y'), None); /// ``` #[inline] pub fn entry(&mut self, key: K) -> Entry where K: Ord, { match self.address_of(&key) { Ok(addr) => Entry::Occupied(OccupiedEntry { map: self, addr }), Err(addr) => Entry::Vacant(VacantEntry { map: self, key, addr, }), } } /// Returns the first entry in the map for in-place manipulation. /// The key of this entry is the minimum key in the map. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// if let Some(mut entry) = map.first_entry() { /// if *entry.key() > 0 { /// entry.insert("first"); /// } /// } /// assert_eq!(*map.get(&1).unwrap(), "first"); /// assert_eq!(*map.get(&2).unwrap(), "b"); /// ``` #[inline] pub fn first_entry(&mut self) -> Option> { self.first_item_address() .map(move |addr| OccupiedEntry { map: self, addr }) } /// Returns the last entry in the map for in-place manipulation. /// The key of this entry is the maximum key in the map. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// if let Some(mut entry) = map.last_entry() { /// if *entry.key() > 0 { /// entry.insert("last"); /// } /// } /// assert_eq!(*map.get(&1).unwrap(), "a"); /// assert_eq!(*map.get(&2).unwrap(), "last"); /// ``` #[inline] pub fn last_entry(&mut self) -> Option> { self.last_item_address() .map(move |addr| OccupiedEntry { map: self, addr }) } /// Insert a key-value pair in the tree. #[inline] pub fn insert(&mut self, key: K, value: V) -> Option where K: Ord, { match self.address_of(&key) { Ok(addr) => Some(self.replace_value_at(addr, value)), Err(addr) => { self.insert_exactly_at(addr, Item::new(key, value), None); None } } } /// Replace a key-value pair in the tree. #[inline] pub fn replace(&mut self, key: K, value: V) -> Option<(K, V)> where K: Ord, { match self.address_of(&key) { Ok(addr) => Some(self.replace_at(addr, key, value)), Err(addr) => { self.insert_exactly_at(addr, Item::new(key, value), None); None } } } /// Removes and returns the first element in the map. /// The key of this element is the minimum key that was in the map. /// /// # Example /// /// Draining elements in ascending order, while keeping a usable map each iteration. /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// while let Some((key, _val)) = map.pop_first() { /// assert!(map.iter().all(|(k, _v)| *k > key)); /// } /// assert!(map.is_empty()); /// ``` #[inline] pub fn pop_first(&mut self) -> Option<(K, V)> { self.first_entry().map(|entry| entry.remove_entry()) } /// Removes and returns the last element in the map. /// The key of this element is the maximum key that was in the map. /// /// # Example /// /// Draining elements in descending order, while keeping a usable map each iteration. /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// while let Some((key, _val)) = map.pop_last() { /// assert!(map.iter().all(|(k, _v)| *k < key)); /// } /// assert!(map.is_empty()); /// ``` #[inline] pub fn pop_last(&mut self) -> Option<(K, V)> { self.last_entry().map(|entry| entry.remove_entry()) } /// Removes a key from the map, returning the value at the key if the key /// was previously in the map. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` #[inline] pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord, { match self.address_of(key) { Ok(addr) => { let (item, _) = self.remove_at(addr).unwrap(); Some(item.into_value()) } Err(_) => None, } } /// Removes a key from the map, returning the stored key and value if the key /// was previously in the map. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. /// /// # Example /// /// Basic usage: /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); /// assert_eq!(map.remove_entry(&1), None); /// ``` #[inline] pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord, { match self.address_of(key) { Ok(addr) => { let (item, _) = self.remove_at(addr).unwrap(); Some(item.into_pair()) } Err(_) => None, } } /// Removes and returns the binding in the map, if any, of which key matches the given one. #[inline] pub fn take(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord, { match self.address_of(key) { Ok(addr) => { let (item, _) = self.remove_at(addr).unwrap(); Some(item.into_pair()) } Err(_) => None, } } /// General-purpose update function. /// /// This can be used to insert, compare, replace or remove the value associated to the given /// `key` in the tree. /// The action to perform is specified by the `action` function. /// This function is called once with: /// - `Some(value)` when `value` is aready associated to `key` or /// - `None` when the `key` is not associated to any value. /// /// The `action` function must return a pair (`new_value`, `result`) where /// `new_value` is the new value to be associated to `key` /// (if it is `None` any previous binding is removed) and /// `result` is the value returned by the entire `update` function call. #[inline] pub fn update(&mut self, key: K, action: F) -> T where K: Ord, F: FnOnce(Option) -> (Option, T), { match self.root { Some(id) => self.update_in(id, key, action), None => { let (to_insert, result) = action(None); if let Some(value) = to_insert { let new_root = Node::leaf(None, Item::new(key, value)); self.root = Some(self.allocate_node(new_root)); self.len += 1; } result } } } /// Gets a mutable iterator over the entries of the map, sorted by key. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert("a", 1); /// map.insert("b", 2); /// map.insert("c", 3); /// /// // add 10 to the value if the key isn't "a" /// for (key, value) in map.iter_mut() { /// if key != &"a" { /// *value += 10; /// } /// } /// ``` #[inline] pub fn iter_mut(&mut self) -> IterMut { IterMut::new(self) } /// Gets a mutable iterator over the entries of the map, sorted by key, that allows insertion and deletion of the iterated entries. /// /// # Correctness /// /// It is safe to insert any key-value pair while iterating, /// however this might break the well-formedness /// of the underlying tree, which relies on several invariants. /// To preserve these invariants, /// the inserted key must be *strictly greater* than the previous visited item's key, /// and *strictly less* than the next visited item /// (which you can retrive through [`EntriesMut::peek`] without moving the iterator). /// If this rule is not respected, the data structure will become unusable /// (invalidate the specification of every method of the API). /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert("a", 1); /// map.insert("b", 2); /// map.insert("d", 4); /// /// let mut entries = map.entries_mut(); /// entries.next(); /// entries.next(); /// entries.insert("c", 3); /// /// let entries: Vec<_> = map.into_iter().collect(); /// assert_eq!(entries, vec![("a", 1), ("b", 2), ("c", 3), ("d", 4)]); /// ``` #[inline] pub fn entries_mut(&mut self) -> EntriesMut { EntriesMut::new(self) } /// Constructs a mutable double-ended iterator over a sub-range of elements in the map. /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will /// yield elements from min (inclusive) to max (exclusive). /// The range may also be entered as `(Bound, Bound)`, so for example /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive /// range from 4 to 10. /// /// # Panics /// /// Panics if range `start > end`. /// Panics if range `start == end` and both bounds are `Excluded`. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"] /// .iter() /// .map(|&s| (s, 0)) /// .collect(); /// for (_, balance) in map.range_mut("B".."Cheryl") { /// *balance += 100; /// } /// for (name, balance) in &map { /// println!("{} => {}", name, balance); /// } /// ``` #[inline] pub fn range_mut(&mut self, range: R) -> RangeMut where T: Ord, K: Borrow, R: RangeBounds, { RangeMut::new(self, range) } /// Gets a mutable iterator over the values of the map, in order by key. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, String::from("hello")); /// a.insert(2, String::from("goodbye")); /// /// for value in a.values_mut() { /// value.push_str("!"); /// } /// /// let values: Vec = a.values().cloned().collect(); /// assert_eq!(values, [String::from("hello!"), /// String::from("goodbye!")]); /// ``` #[inline] pub fn values_mut(&mut self) -> ValuesMut { ValuesMut { inner: self.iter_mut(), } } /// Creates an iterator which uses a closure to determine if an element should be removed. /// /// If the closure returns true, the element is removed from the map and yielded. /// If the closure returns false, or panics, the element remains in the map and will not be /// yielded. /// /// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of /// whether you choose to keep or remove it. /// /// If the iterator is only partially consumed or not consumed at all, each of the remaining /// elements will still be subjected to the closure and removed and dropped if it returns true. /// /// It is unspecified how many more elements will be subjected to the closure /// if a panic occurs in the closure, or a panic occurs while dropping an element, /// or if the `DrainFilter` value is leaked. /// /// # Example /// /// Splitting a map into even and odd keys, reusing the original map: /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap = (0..8).map(|x| (x, x)).collect(); /// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect(); /// let odds = map; /// assert_eq!(evens.keys().copied().collect::>(), vec![0, 2, 4, 6]); /// assert_eq!(odds.keys().copied().collect::>(), vec![1, 3, 5, 7]); /// ``` #[inline] pub fn drain_filter(&mut self, pred: F) -> DrainFilter where F: FnMut(&K, &mut V) -> bool, { DrainFilter::new(self, pred) } /// Retains only the elements specified by the predicate. /// /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut map: BTreeMap = (0..8).map(|x| (x, x*10)).collect(); /// // Keep only the elements with even-numbered keys. /// map.retain(|&k, _| k % 2 == 0); /// assert!(map.into_iter().eq(vec![(0, 0), (2, 20), (4, 40), (6, 60)])); /// ``` #[inline] pub fn retain(&mut self, mut f: F) where F: FnMut(&K, &mut V) -> bool, { self.drain_filter(|k, v| !f(k, v)); } /// Moves all elements from `other` into `Self`, leaving `other` empty. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, "a"); /// a.insert(2, "b"); /// a.insert(3, "c"); /// /// let mut b = BTreeMap::new(); /// b.insert(3, "d"); /// b.insert(4, "e"); /// b.insert(5, "f"); /// /// a.append(&mut b); /// /// assert_eq!(a.len(), 5); /// assert_eq!(b.len(), 0); /// /// assert_eq!(a[&1], "a"); /// assert_eq!(a[&2], "b"); /// assert_eq!(a[&3], "d"); /// assert_eq!(a[&4], "e"); /// assert_eq!(a[&5], "f"); /// ``` #[inline] pub fn append(&mut self, other: &mut Self) where K: Ord, C: Default, { // Do we have to append anything at all? if other.is_empty() { return; } // We can just swap `self` and `other` if `self` is empty. if self.is_empty() { std::mem::swap(self, other); return; } let other = std::mem::take(other); for (key, value) in other { self.insert(key, value); } } /// Creates a consuming iterator visiting all the keys, in sorted order. /// The map cannot be used after calling this. /// The iterator element type is `K`. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(2, "b"); /// a.insert(1, "a"); /// /// let keys: Vec = a.into_keys().collect(); /// assert_eq!(keys, [1, 2]); /// ``` #[inline] pub fn into_keys(self) -> IntoKeys { IntoKeys { inner: self.into_iter(), } } /// Creates a consuming iterator visiting all the values, in order by key. /// The map cannot be used after calling this. /// The iterator element type is `V`. /// /// # Example /// /// ``` /// use btree_slab::BTreeMap; /// /// let mut a = BTreeMap::new(); /// a.insert(1, "hello"); /// a.insert(2, "goodbye"); /// /// let values: Vec<&str> = a.into_values().collect(); /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[inline] pub fn into_values(self) -> IntoValues { IntoValues { inner: self.into_iter(), } } /// Try to rotate left the node `id` to benefits the child number `deficient_child_index`. /// /// Returns true if the rotation succeeded, of false if the target child has no right sibling, /// or if this sibling would underflow. #[inline] fn try_rotate_left( &mut self, id: usize, deficient_child_index: usize, addr: &mut Address, ) -> bool { let pivot_offset = deficient_child_index.into(); let right_sibling_index = deficient_child_index + 1; let (right_sibling_id, deficient_child_id) = { let node = self.node(id); if right_sibling_index >= node.child_count() { return false; // no right sibling } ( node.child_id(right_sibling_index), node.child_id(deficient_child_index), ) }; match self.node_mut(right_sibling_id).pop_left() { Ok((mut value, opt_child_id)) => { std::mem::swap( &mut value, self.node_mut(id).item_mut(pivot_offset).unwrap(), ); let left_offset = self .node_mut(deficient_child_id) .push_right(value, opt_child_id); // update opt_child's parent if let Some(child_id) = opt_child_id { self.node_mut(child_id).set_parent(Some(deficient_child_id)) } // update address. if addr.id == right_sibling_id { // addressed item is in the right node. if addr.offset == 0 { // addressed item is moving to pivot. addr.id = id; addr.offset = pivot_offset; } else { // addressed item stays on right. addr.offset.decr(); } } else if addr.id == id { // addressed item is in the parent node. if addr.offset == pivot_offset { // addressed item is the pivot, moving to the left (deficient) node. addr.id = deficient_child_id; addr.offset = left_offset; } } true // rotation succeeded } Err(WouldUnderflow) => false, // the right sibling would underflow. } } /// Try to rotate right the node `id` to benefits the child number `deficient_child_index`. /// /// Returns true if the rotation succeeded, of false if the target child has no left sibling, /// or if this sibling would underflow. #[inline] fn try_rotate_right( &mut self, id: usize, deficient_child_index: usize, addr: &mut Address, ) -> bool { if deficient_child_index > 0 { let left_sibling_index = deficient_child_index - 1; let pivot_offset = left_sibling_index.into(); let (left_sibling_id, deficient_child_id) = { let node = self.node(id); ( node.child_id(left_sibling_index), node.child_id(deficient_child_index), ) }; match self.node_mut(left_sibling_id).pop_right() { Ok((left_offset, mut value, opt_child_id)) => { std::mem::swap( &mut value, self.node_mut(id).item_mut(pivot_offset).unwrap(), ); self.node_mut(deficient_child_id) .push_left(value, opt_child_id); // update opt_child's parent if let Some(child_id) = opt_child_id { self.node_mut(child_id).set_parent(Some(deficient_child_id)) } // update address. if addr.id == deficient_child_id { // addressed item is in the right (deficient) node. addr.offset.incr(); } else if addr.id == left_sibling_id { // addressed item is in the left node. if addr.offset == left_offset { // addressed item is moving to pivot. addr.id = id; addr.offset = pivot_offset; } } else if addr.id == id { // addressed item is in the parent node. if addr.offset == pivot_offset { // addressed item is the pivot, moving to the left (deficient) node. addr.id = deficient_child_id; addr.offset = 0.into(); } } true // rotation succeeded } Err(WouldUnderflow) => false, // the left sibling would underflow. } } else { false // no left sibling. } } /// Merge the child `deficient_child_index` in node `id` with one of its direct sibling. #[inline] fn merge( &mut self, id: usize, deficient_child_index: usize, mut addr: Address, ) -> (Balance, Address) { let (offset, left_id, right_id, separator, balance) = if deficient_child_index > 0 { // merge with left sibling self.node_mut(id) .merge(deficient_child_index - 1, deficient_child_index) } else { // merge with right sibling self.node_mut(id) .merge(deficient_child_index, deficient_child_index + 1) }; // update children's parent. let right_node = self.release_node(right_id); for right_child_id in right_node.children() { self.node_mut(right_child_id).set_parent(Some(left_id)); } // actually merge. let left_offset = self.node_mut(left_id).append(separator, right_node); // update addr. if addr.id == id { match addr.offset.partial_cmp(&offset) { Some(Ordering::Equal) => { addr.id = left_id; addr.offset = left_offset } Some(Ordering::Greater) => addr.offset.decr(), _ => (), } } else if addr.id == right_id { addr.id = left_id; addr.offset = (addr.offset.unwrap() + left_offset.unwrap() + 1).into(); } (balance, addr) } } impl>> Index<&Q> for BTreeMap where K: Borrow, Q: Ord, C: SimpleCollectionRef, { type Output = V; /// Returns a reference to the value corresponding to the supplied key. /// /// # Panics /// /// Panics if the key is not present in the `BTreeMap`. #[inline] fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") } } impl, V, W: PartialEq, C: Slab>, D: Slab>> PartialEq> for BTreeMap where C: SimpleCollectionRef, D: SimpleCollectionRef, { fn eq(&self, other: &BTreeMap) -> bool { if self.len() == other.len() { let mut it1 = self.iter(); let mut it2 = other.iter(); loop { match (it1.next(), it2.next()) { (None, None) => break, (Some((k, v)), Some((l, w))) => { if l != k || w != v { return false; } } _ => return false, } } true } else { false } } } impl Default for BTreeMap { #[inline] fn default() -> Self { BTreeMap::new() } } impl> + Default> FromIterator<(K, V)> for BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn from_iter(iter: T) -> BTreeMap where T: IntoIterator, { let mut map = BTreeMap::new(); for (key, value) in iter { map.insert(key, value); } map } } impl>> Extend<(K, V)> for BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn extend(&mut self, iter: T) where T: IntoIterator, { for (key, value) in iter { self.insert(key, value); } } } impl<'a, K: Ord + Copy, V: Copy, C: SlabMut>> Extend<(&'a K, &'a V)> for BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn extend(&mut self, iter: T) where T: IntoIterator, { self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); } } impl>> Eq for BTreeMap where C: SimpleCollectionRef {} impl, V, W: PartialOrd, C: Slab>, D: Slab>> PartialOrd> for BTreeMap where C: SimpleCollectionRef, D: SimpleCollectionRef, { fn partial_cmp(&self, other: &BTreeMap) -> Option { let mut it1 = self.iter(); let mut it2 = other.iter(); loop { match (it1.next(), it2.next()) { (None, None) => return Some(Ordering::Equal), (_, None) => return Some(Ordering::Greater), (None, _) => return Some(Ordering::Less), (Some((k, v)), Some((l, w))) => match l.partial_cmp(k) { Some(Ordering::Greater) => return Some(Ordering::Less), Some(Ordering::Less) => return Some(Ordering::Greater), Some(Ordering::Equal) => match w.partial_cmp(v) { Some(Ordering::Greater) => return Some(Ordering::Less), Some(Ordering::Less) => return Some(Ordering::Greater), Some(Ordering::Equal) => (), None => return None, }, None => return None, }, } } } } impl>> Ord for BTreeMap where C: SimpleCollectionRef, { fn cmp(&self, other: &BTreeMap) -> Ordering { let mut it1 = self.iter(); let mut it2 = other.iter(); loop { match (it1.next(), it2.next()) { (None, None) => return Ordering::Equal, (_, None) => return Ordering::Greater, (None, _) => return Ordering::Less, (Some((k, v)), Some((l, w))) => match l.cmp(k) { Ordering::Greater => return Ordering::Less, Ordering::Less => return Ordering::Greater, Ordering::Equal => match w.cmp(v) { Ordering::Greater => return Ordering::Less, Ordering::Less => return Ordering::Greater, Ordering::Equal => (), }, }, } } } } impl>> Hash for BTreeMap where C: SimpleCollectionRef, { #[inline] fn hash(&self, h: &mut H) { for (k, v) in self { k.hash(h); v.hash(h); } } } pub struct Iter<'a, K, V, C> { /// The tree reference. btree: &'a BTreeMap, /// Address of the next item. addr: Option
, end: Option
, len: usize, } impl<'a, K, V, C: Slab>> Iter<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn new(btree: &'a BTreeMap) -> Self { let addr = btree.first_item_address(); let len = btree.len(); Iter { btree, addr, end: None, len, } } } impl<'a, K, V, C: Slab>> Iterator for Iter<'a, K, V, C> where C: SimpleCollectionRef, { type Item = (&'a K, &'a V); #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { match self.addr { Some(addr) => { if self.len > 0 { self.len -= 1; let item = self.btree.item(addr).unwrap(); self.addr = self.btree.next_item_address(addr); Some((item.key(), item.value())) } else { None } } None => None, } } } impl<'a, K, V, C: Slab>> FusedIterator for Iter<'a, K, V, C> where C: SimpleCollectionRef {} impl<'a, K, V, C: Slab>> ExactSizeIterator for Iter<'a, K, V, C> where C: SimpleCollectionRef { } impl<'a, K, V, C: Slab>> DoubleEndedIterator for Iter<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<(&'a K, &'a V)> { if self.len > 0 { let addr = match self.end { Some(addr) => self.btree.previous_item_address(addr).unwrap(), None => self.btree.last_item_address().unwrap(), }; self.len -= 1; let item = self.btree.item(addr).unwrap(); self.end = Some(addr); Some((item.key(), item.value())) } else { None } } } impl<'a, K, V, C: Slab>> IntoIterator for &'a BTreeMap where C: SimpleCollectionRef, { type IntoIter = Iter<'a, K, V, C>; type Item = (&'a K, &'a V); #[inline] fn into_iter(self) -> Iter<'a, K, V, C> { self.iter() } } pub struct IterMut<'a, K, V, C> { /// The tree reference. btree: &'a mut BTreeMap, /// Address of the next item. addr: Option
, end: Option
, len: usize, } impl<'a, K, V, C: SlabMut>> IterMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn new(btree: &'a mut BTreeMap) -> Self { let addr = btree.first_item_address(); let len = btree.len(); IterMut { btree, addr, end: None, len, } } #[inline] fn next_item(&mut self) -> Option<&'a mut Item> { match self.addr { Some(addr) => { if self.len > 0 { self.len -= 1; self.addr = self.btree.next_item_address(addr); let item = self.btree.item_mut(addr).unwrap(); Some(unsafe { std::mem::transmute(item) }) // this is safe because only one mutable reference to the same item can be emitted. } else { None } } None => None, } } #[inline] fn next_back_item(&mut self) -> Option<&'a mut Item> { if self.len > 0 { let addr = match self.end { Some(addr) => self.btree.previous_item_address(addr).unwrap(), None => self.btree.last_item_address().unwrap(), }; self.len -= 1; let item = self.btree.item_mut(addr).unwrap(); self.end = Some(addr); Some(unsafe { std::mem::transmute(item) }) // this is safe because only one mutable reference to the same item can be emitted.s } else { None } } } impl<'a, K, V, C: SlabMut>> Iterator for IterMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = (&'a K, &'a mut V); #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.next_item().map(|item| { let (key, value) = item.as_pair_mut(); (key as &'a K, value) }) } } impl<'a, K, V, C: SlabMut>> FusedIterator for IterMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>> ExactSizeIterator for IterMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>> DoubleEndedIterator for IterMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.next_back_item().map(|item| { let (key, value) = item.as_pair_mut(); (key as &'a K, value) }) } } /// Iterator that can mutate the tree in place. pub struct EntriesMut<'a, K, V, C> { /// The tree reference. btree: &'a mut BTreeMap, /// Address of the next item, or last valid address. addr: Address, len: usize, } impl<'a, K, V, C: SlabMut>> EntriesMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Create a new iterator over all the items of the map. #[inline] fn new(btree: &'a mut BTreeMap) -> EntriesMut<'a, K, V, C> { let addr = btree.first_back_address(); let len = btree.len(); EntriesMut { btree, addr, len } } /// Get the next visited item without moving the iterator position. #[inline] pub fn peek(&'a self) -> Option<&'a Item> { self.btree.item(self.addr) } /// Get the next visited item without moving the iterator position. #[inline] pub fn peek_mut(&'a mut self) -> Option<&'a mut Item> { self.btree.item_mut(self.addr) } /// Get the next item and move the iterator to the next position. #[inline] pub fn next_item(&mut self) -> Option<&'a mut Item> { let after_addr = self.btree.next_item_or_back_address(self.addr); match self.btree.item_mut(self.addr) { Some(item) => unsafe { self.len -= 1; self.addr = after_addr.unwrap(); Some(&mut *(item as *mut _)) // this is safe because only one mutable reference to the same item can be emitted. }, None => None, } } /// Insert a new item in the map before the next item. /// /// ## Correctness /// /// It is safe to insert any key-value pair here, however this might break the well-formedness /// of the underlying tree, which relies on several invariants. /// To preserve these invariants, /// the key must be *strictly greater* than the previous visited item's key, /// and *strictly less* than the next visited item /// (which you can retrive through `IterMut::peek` without moving the iterator). /// If this rule is not respected, the data structure will become unusable /// (invalidate the specification of every method of the API). #[inline] pub fn insert(&mut self, key: K, value: V) { let addr = self.btree.insert_at(self.addr, Item::new(key, value)); self.btree.next_item_or_back_address(addr); self.len += 1; } /// Remove the next item and return it. #[inline] pub fn remove(&mut self) -> Option> { match self.btree.remove_at(self.addr) { Some((item, addr)) => { self.len -= 1; self.addr = addr; Some(item) } None => None, } } } impl<'a, K, V, C: SlabMut>> Iterator for EntriesMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = (&'a K, &'a mut V); #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { match self.next_item() { Some(item) => { let (key, value) = item.as_pair_mut(); Some((key, value)) // coerce k from `&mut K` to `&K` } None => None, } } } /// An owning iterator over the entries of a `BTreeMap`. /// /// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] /// (provided by the `IntoIterator` trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter pub struct IntoIter { /// The tree reference. btree: BTreeMap, /// Address of the next item, or the last valid address. addr: Option
, /// Address following the last item. end: Option
, /// Number of remaining items. len: usize, } impl>> IntoIter where C: SimpleCollectionRef, { #[inline] pub fn new(btree: BTreeMap) -> Self { let addr = btree.first_item_address(); let len = btree.len(); IntoIter { btree, addr, end: None, len, } } } impl>> FusedIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> ExactSizeIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> Iterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = (K, V); #[inline] fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } #[inline] fn next(&mut self) -> Option<(K, V)> { match self.addr { Some(addr) => { if self.len > 0 { self.len -= 1; let item = unsafe { // this is safe because the item at `self.addr` exists and is never touched again. std::ptr::read(self.btree.item(addr).unwrap()) }; if self.len > 0 { self.addr = self.btree.next_back_address(addr); // an item address is always followed by a valid address. while let Some(addr) = self.addr { if addr.offset < self.btree.node(addr.id).item_count() { break; // we have found an item address. } else { self.addr = self.btree.next_back_address(addr); // we have gove through every item of the node, we can release it. let node = self.btree.release_node(addr.id); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } } } else { // cleanup. if self.end.is_some() { while self.addr != self.end { let addr = self.addr.unwrap(); self.addr = self.btree.next_back_address(addr); if addr.offset >= self.btree.node(addr.id).item_count() { let node = self.btree.release_node(addr.id); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } } } if let Some(addr) = self.addr { let mut id = Some(addr.id); while let Some(node_id) = id { let node = self.btree.release_node(node_id); id = node.parent(); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } } } Some(item.into_pair()) } else { None } } None => None, } } } impl>> DoubleEndedIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { fn next_back(&mut self) -> Option<(K, V)> { if self.len > 0 { let addr = match self.end { Some(mut addr) => { addr = self.btree.previous_front_address(addr).unwrap(); while addr.offset.is_before() { let id = addr.id; addr = self.btree.previous_front_address(addr).unwrap(); // we have gove through every item of the node, we can release it. let node = self.btree.release_node(id); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } addr } None => self.btree.last_item_address().unwrap(), }; self.len -= 1; let item = unsafe { // this is safe because the item at `self.end` exists and is never touched again. std::ptr::read(self.btree.item(addr).unwrap()) }; self.end = Some(addr); if self.len == 0 { // cleanup. while self.addr != self.end { let addr = self.addr.unwrap(); self.addr = self.btree.next_back_address(addr); if addr.offset >= self.btree.node(addr.id).item_count() { let node = self.btree.release_node(addr.id); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } } if let Some(addr) = self.addr { let mut id = Some(addr.id); while let Some(node_id) = id { let node = self.btree.release_node(node_id); id = node.parent(); std::mem::forget(node); // do not call `drop` on the node since items have been moved. } } } Some(item.into_pair()) } else { None } } } impl>> IntoIterator for BTreeMap where C: SimpleCollectionRef, C: SimpleCollectionMut, { type IntoIter = IntoIter; type Item = (K, V); #[inline] fn into_iter(self) -> IntoIter { IntoIter::new(self) } } pub(crate) struct DrainFilterInner<'a, K, V, C> { /// The tree reference. btree: &'a mut BTreeMap, /// Address of the next item, or last valid address. addr: Address, len: usize, } impl<'a, K: 'a, V: 'a, C: SlabMut>> DrainFilterInner<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] pub fn new(btree: &'a mut BTreeMap) -> Self { let addr = btree.first_back_address(); let len = btree.len(); DrainFilterInner { btree, addr, len } } #[inline] pub fn size_hint(&self) -> (usize, Option) { (0, Some(self.len)) } #[inline] fn next_item(&mut self, pred: &mut F) -> Option> where F: FnMut(&K, &mut V) -> bool, { if self.addr.id == usize::MAX { return None; } loop { match self.btree.item_mut(self.addr) { Some(item) => { let (key, value) = item.as_pair_mut(); self.len -= 1; if (*pred)(key, value) { let (item, next_addr) = self.btree.remove_at(self.addr).unwrap(); self.addr = next_addr; return Some(item); } else { self.addr = self.btree.next_item_or_back_address(self.addr).unwrap(); } } None => return None, } } } #[inline] pub fn next(&mut self, pred: &mut F) -> Option<(K, V)> where F: FnMut(&K, &mut V) -> bool, { self.next_item(pred).map(Item::into_pair) } } pub struct DrainFilter<'a, K, V, C: SlabMut>, F> where F: FnMut(&K, &mut V) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { pred: F, inner: DrainFilterInner<'a, K, V, C>, } impl<'a, K: 'a, V: 'a, C: SlabMut>, F> DrainFilter<'a, K, V, C, F> where F: FnMut(&K, &mut V) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn new(btree: &'a mut BTreeMap, pred: F) -> Self { DrainFilter { pred, inner: DrainFilterInner::new(btree), } } } impl<'a, K, V, C: SlabMut>, F> FusedIterator for DrainFilter<'a, K, V, C, F> where F: FnMut(&K, &mut V) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>, F> Iterator for DrainFilter<'a, K, V, C, F> where F: FnMut(&K, &mut V) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = (K, V); #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next(&mut self.pred) } } impl<'a, K, V, C: SlabMut>, F> Drop for DrainFilter<'a, K, V, C, F> where F: FnMut(&K, &mut V) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn drop(&mut self) { loop { if self.next().is_none() { break; } } } } pub struct Keys<'a, K, V, C> { inner: Iter<'a, K, V, C>, } impl<'a, K, V, C: Slab>> FusedIterator for Keys<'a, K, V, C> where C: SimpleCollectionRef {} impl<'a, K, V, C: Slab>> ExactSizeIterator for Keys<'a, K, V, C> where C: SimpleCollectionRef { } impl<'a, K, V, C: Slab>> Iterator for Keys<'a, K, V, C> where C: SimpleCollectionRef, { type Item = &'a K; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<&'a K> { self.inner.next().map(|(k, _)| k) } } impl<'a, K, V, C: Slab>> DoubleEndedIterator for Keys<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<&'a K> { self.inner.next_back().map(|(k, _)| k) } } impl>> FusedIterator for IntoKeys where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> ExactSizeIterator for IntoKeys where C: SimpleCollectionRef, C: SimpleCollectionMut, { } pub struct IntoKeys { inner: IntoIter, } impl>> Iterator for IntoKeys where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = K; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option { self.inner.next().map(|(k, _)| k) } } impl>> DoubleEndedIterator for IntoKeys where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back().map(|(k, _)| k) } } impl<'a, K, V, C: Slab>> FusedIterator for Values<'a, K, V, C> where C: SimpleCollectionRef { } impl<'a, K, V, C: Slab>> ExactSizeIterator for Values<'a, K, V, C> where C: SimpleCollectionRef { } pub struct Values<'a, K, V, C> { inner: Iter<'a, K, V, C>, } impl<'a, K, V, C: Slab>> Iterator for Values<'a, K, V, C> where C: SimpleCollectionRef, { type Item = &'a V; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<&'a V> { self.inner.next().map(|(_, v)| v) } } impl<'a, K, V, C: Slab>> DoubleEndedIterator for Values<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<&'a V> { self.inner.next_back().map(|(_, v)| v) } } pub struct ValuesMut<'a, K, V, C> { inner: IterMut<'a, K, V, C>, } impl<'a, K, V, C: SlabMut>> FusedIterator for ValuesMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>> ExactSizeIterator for ValuesMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>> Iterator for ValuesMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = &'a mut V; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<&'a mut V> { self.inner.next().map(|(_, v)| v) } } pub struct IntoValues { inner: IntoIter, } impl>> FusedIterator for IntoValues where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> ExactSizeIterator for IntoValues where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> Iterator for IntoValues where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = V; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option { self.inner.next().map(|(_, v)| v) } } impl>> DoubleEndedIterator for IntoValues where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back().map(|(_, v)| v) } } fn is_valid_range(range: &R) -> bool where T: Ord + ?Sized, R: RangeBounds, { match (range.start_bound(), range.end_bound()) { (Bound::Included(start), Bound::Included(end)) => start <= end, (Bound::Included(start), Bound::Excluded(end)) => start <= end, (Bound::Included(_), Bound::Unbounded) => true, (Bound::Excluded(start), Bound::Included(end)) => start <= end, (Bound::Excluded(start), Bound::Excluded(end)) => start < end, (Bound::Excluded(_), Bound::Unbounded) => true, (Bound::Unbounded, _) => true, } } pub struct Range<'a, K, V, C> { /// The tree reference. btree: &'a BTreeMap, /// Address of the next item or last back address. addr: Address, end: Address, } impl<'a, K, V, C: Slab>> Range<'a, K, V, C> where C: SimpleCollectionRef, { fn new(btree: &'a BTreeMap, range: R) -> Self where T: Ord + ?Sized, R: RangeBounds, K: Borrow, { if !is_valid_range(&range) { panic!("Invalid range") } let addr = match range.start_bound() { Bound::Included(start) => match btree.address_of(start) { Ok(addr) => addr, Err(addr) => addr, }, Bound::Excluded(start) => match btree.address_of(start) { Ok(addr) => btree.next_item_or_back_address(addr).unwrap(), Err(addr) => addr, }, Bound::Unbounded => btree.first_back_address(), }; let end = match range.end_bound() { Bound::Included(end) => match btree.address_of(end) { Ok(addr) => btree.next_item_or_back_address(addr).unwrap(), Err(addr) => addr, }, Bound::Excluded(end) => match btree.address_of(end) { Ok(addr) => addr, Err(addr) => addr, }, Bound::Unbounded => btree.first_back_address(), }; Range { btree, addr, end } } } impl<'a, K, V, C: Slab>> Iterator for Range<'a, K, V, C> where C: SimpleCollectionRef, { type Item = (&'a K, &'a V); #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { if self.addr != self.end { let item = self.btree.item(self.addr).unwrap(); self.addr = self.btree.next_item_or_back_address(self.addr).unwrap(); Some((item.key(), item.value())) } else { None } } } impl<'a, K, V, C: Slab>> FusedIterator for Range<'a, K, V, C> where C: SimpleCollectionRef {} impl<'a, K, V, C: Slab>> DoubleEndedIterator for Range<'a, K, V, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<(&'a K, &'a V)> { if self.addr != self.end { let addr = self.btree.previous_item_address(self.addr).unwrap(); let item = self.btree.item(addr).unwrap(); self.end = addr; Some((item.key(), item.value())) } else { None } } } pub struct RangeMut<'a, K, V, C> { /// The tree reference. btree: &'a mut BTreeMap, /// Address of the next item or last back address. addr: Address, end: Address, } impl<'a, K, V, C: SlabMut>> RangeMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { fn new(btree: &'a mut BTreeMap, range: R) -> Self where T: Ord + ?Sized, R: RangeBounds, K: Borrow, { if !is_valid_range(&range) { panic!("Invalid range") } let addr = match range.start_bound() { Bound::Included(start) => match btree.address_of(start) { Ok(addr) => addr, Err(addr) => addr, }, Bound::Excluded(start) => match btree.address_of(start) { Ok(addr) => btree.next_item_or_back_address(addr).unwrap(), Err(addr) => addr, }, Bound::Unbounded => btree.first_back_address(), }; let end = match range.end_bound() { Bound::Included(end) => match btree.address_of(end) { Ok(addr) => btree.next_item_or_back_address(addr).unwrap(), Err(addr) => addr, }, Bound::Excluded(end) => match btree.address_of(end) { Ok(addr) => addr, Err(addr) => addr, }, Bound::Unbounded => btree.first_back_address(), }; RangeMut { btree, addr, end } } #[inline] fn next_item(&mut self) -> Option<&'a mut Item> { if self.addr != self.end { let addr = self.addr; self.addr = self.btree.next_item_or_back_address(addr).unwrap(); let item = self.btree.item_mut(addr).unwrap(); Some(unsafe { std::mem::transmute(item) }) // this is safe because only one mutable reference to the same item can be emitted. } else { None } } #[inline] fn next_back_item(&mut self) -> Option<&'a mut Item> { if self.addr != self.end { let addr = self.btree.previous_item_address(self.addr).unwrap(); let item = self.btree.item_mut(addr).unwrap(); self.end = addr; Some(unsafe { std::mem::transmute(item) }) // this is safe because only one mutable reference to the same item can be emitted.s } else { None } } } impl<'a, K, V, C: SlabMut>> Iterator for RangeMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = (&'a K, &'a mut V); #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.next_item().map(|item| { let (key, value) = item.as_pair_mut(); (key as &'a K, value) }) } } impl<'a, K, V, C: SlabMut>> FusedIterator for RangeMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, K, V, C: SlabMut>> DoubleEndedIterator for RangeMut<'a, K, V, C> where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.next_back_item().map(|item| { let (key, value) = item.as_pair_mut(); (key as &'a K, value) }) } } btree-slab-0.6.1/src/generic/node/addr.rs000064400000000000000000000172431046102023000162670ustar 00000000000000use super::Offset; use std::fmt; /// Item/entry location in a BTreeMap. /// /// Each item in a B-Tree is addressed by a node identifier and an offset in the node. /// We write `@id:offset` the address of the item contained in the node `id` at offset `offset`. /// /// ```text /// ┌────────────────┐ /// │ node 0 ┌──┼─── this item address is `@0:1` /// │┌────────┐ ┌─v─┐│ /// ┌───────── ││ item 0 │ │ 1 ││ ──────────┐ /// │ │└────────┘ └───┘│ │ /// │ └────────────────┘ │ /// │ │ │ /// ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ /// │ node 1 │ │ node 2 │ │ node 3 │ /// │┌───┐ ┌───┐ ┌───┐│ │┌───┐ ┌───┐ ┌───┐│ │┌───┐ ┌───┐ ┌───┐│ /// ││ 0 │ │ 1 │ │ 2 ││ ││ 0 │ │ 1 │ │ 2 ││ ││ 0 │ │ 1 │ │ 2 ││ /// │└─^─┘ └───┘ └───┘│ │└───┘ └───┘ └─^─┘│ │└───┘ └───┘ └───┘│ /// └──┼──────────────┘ └──────────────┼──┘ └─────────────────┘ /// └─ this item address is `@1:0` └─ this item address is `@2:2` /// ``` /// /// ## Validity /// An item adress `addr` is *valid* in a given BTreeMap if it `addr.id` refers to an existing /// node and if `addr.offset` is comprised between `-1` and the number of items in the node (included). /// We say that `addr` is *occupied* if it points to an actual item /// (`addr.offset` at least 0 and less than the number of items in the node). /// /// The following diagram shows all the valid address in a B-Tree. /// ```text /// ┌───────────┐ /// │ node 0 │ /// ┌───┐│┌───┐ ┌───┐│┌───┐ /// ┌────────────────────│-1 │││ 0 │ │ 1 │││ 2 │─────────────────┐ /// │ └───┘│└───┘ └───┘│└───┘ │ /// │ └───────────┘ │ /// │ │ │ /// ┌─────────────────┐ ┌─────────────────┐ ┌───────────┐ /// │ node 1 │ │ node 2 │ │ node 3 │ /// ┌───┐│┌───┐ ┌───┐ ┌───┐│┌───┐ ┌───┐│┌───┐ ┌───┐ ┌───┐│┌───┐ ┌───┐│┌───┐ ┌───┐│┌───┐ /// │-1 │││ 0 │ │ 1 │ │ 2 │││ 3 │ │-1 │││ 0 │ │ 1 │ │ 2 │││ 3 │ │-1 │││ 0 │ │ 1 │││ 2 │ /// └───┘│└───┘ └───┘ └───┘│└───┘ └───┘│└───┘ └───┘ └───┘│└───┘ └───┘│└───┘ └───┘│└───┘ /// └─────────────────┘ └─────────────────┘ └───────────┘ /// ``` /// Note how some valid addresses are outside of nodes bounds. /// Even is thoses addresses do not refers to any items, /// they can be useful to operate on the tree. /// /// ### Back addresses /// /// A "back address" is a valid address whose offset is at least `0`. /// If `addr.offset` is equal to the number of items in the node then it doesn't actually refer /// to an existing item in the node, /// but it can be used to insert a new item with `BTreeExt::insert_at`. /// /// The following diagram shows all the back addresses in a node. /// ```text /// ┌───────────┄┄┄┄┄───────┐ /// │ node i │ /// │┌───┐ ┌───┐ ┌─────┐│┌───┐ where `n` is /// ││ 0 │ │ 1 │ ... │ n-1 │││ n │ the number of items in the node. /// │└───┘ └───┘ └─────┘│└───┘ /// └───────────┄┄┄┄┄───────┘ /// ``` /// Note that an address with offset `-1` is *not* a back address. /// /// ### Front addresses /// /// A "front address" is a valid address whose offset is less that the number of items in the node. /// If `addr.offset` is equal to `-1`, then it doesn't actually refer to an existing item in the node. /// /// The following diagram shows all the front addresses in a node. /// ```text /// ┌───────────┄┄┄┄┄───────┐ /// │ node i │ /// ┌───┐│┌───┐ ┌───┐ ┌─────┐│ where `n` is /// │-1 │││ 0 │ │ 1 │ ... │ n-1 ││ the number of items in the node. /// └───┘│└───┘ └───┘ └─────┘│ /// └───────────┄┄┄┄┄───────┘ /// ``` /// Note that an address with offset `n` is *not* a front address. /// /// ## Safety /// It is not safe to use an address `addr` in which `addr.id` is not the identifier of any node /// currently used by the tree. #[derive(Clone, Copy, PartialEq, Eq)] pub struct Address { /// Identifier of the node. pub id: usize, /// Offset in the node. pub offset: Offset, } impl Address { /// Creates a new address from the identifier of the node and the offset in the node. #[inline] pub fn new(id: usize, offset: Offset) -> Address { Address { id, offset } } /// Address in the empty tree. /// /// This is the unique valid address address in an ampty tree. /// It is only valid in the empty tree. #[inline] pub fn nowhere() -> Address { Address { id: std::usize::MAX, offset: 0.into(), } } /// Checks if the address is nowhere. #[inline] pub fn is_nowhere(&self) -> bool { self.id == std::usize::MAX } } impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "@{}:{}", self.id, self.offset) } } impl fmt::Debug for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "@{}:{}", self.id, self.offset) } } btree-slab-0.6.1/src/generic/node/internal.rs000064400000000000000000000306061046102023000171670ustar 00000000000000use crate::{ generic::{ map::M, node::{Balance, Children, ChildrenWithSeparators, Item, Keyed, Offset, WouldUnderflow}, }, utils::binary_search_min, }; use smallvec::SmallVec; use std::{borrow::Borrow, cmp::Ordering}; /// Underflow threshold. /// /// An internal node is underflowing if it has less items than this constant. const UNDERFLOW: usize = M / 2 - 1; /// Internal node branch. /// /// A branch is an item followed by child node identifier. #[derive(Clone)] pub struct Branch { /// Item. pub item: Item, /// Following child node identifier. pub child: usize, } impl AsRef> for Branch { fn as_ref(&self) -> &Item { &self.item } } impl Keyed for Branch { type Key = K; #[inline] fn key(&self) -> &K { self.item.key() } } impl PartialEq for Branch { fn eq(&self, other: &Branch) -> bool { self.item.key().eq(other.item.key()) } } impl PartialOrd for Branch { fn partial_cmp(&self, other: &Branch) -> Option { Some(self.item.key().cmp(other.item.key())) } } /// Error returned when a direct insertion by key in the internal node failed. pub struct InsertionError { /// Inserted key. pub key: K, /// Inserted value. pub value: V, /// Offset of the child in which the key should be inserted instead. pub child_offset: usize, /// Id of the child in which the key should be inserted instead. pub child_id: usize, } /// Internal node. /// /// An internal node is a node where each item is surrounded by edges to child nodes. #[derive(Clone)] pub struct Internal { parent: usize, first_child: usize, other_children: SmallVec<[Branch; M]>, } impl Internal { /// Creates a binary node (with a single item and two children). #[inline] pub fn binary( parent: Option, left_id: usize, median: Item, right_id: usize, ) -> Internal { let mut other_children = SmallVec::new(); other_children.push(Branch { item: median, child: right_id, }); Internal { parent: parent.unwrap_or(std::usize::MAX), first_child: left_id, other_children, } } /// Returns the current balance of the node. #[inline] pub fn balance(&self) -> Balance { if self.is_overflowing() { Balance::Overflow } else if self.is_underflowing() { Balance::Underflow(self.other_children.is_empty()) } else { Balance::Balanced } } #[inline] pub fn is_overflowing(&self) -> bool { self.item_count() >= M } #[inline] pub fn is_underflowing(&self) -> bool { self.item_count() < UNDERFLOW } #[inline] pub fn parent(&self) -> Option { if self.parent == std::usize::MAX { None } else { Some(self.parent) } } #[inline] pub fn set_parent(&mut self, p: Option) { self.parent = p.unwrap_or(std::usize::MAX); } #[inline] pub fn item_count(&self) -> usize { self.other_children.len() } #[inline] pub fn child_count(&self) -> usize { 1usize + self.item_count() } #[inline] pub fn first_child_id(&self) -> usize { self.first_child } #[inline] pub fn branches(&self) -> &[Branch] { self.other_children.as_ref() } #[inline] pub fn child_index(&self, id: usize) -> Option { if self.first_child == id { Some(0) } else { for i in 0..self.other_children.len() { if self.other_children[i].child == id { return Some(i + 1); } } None } } #[inline] pub fn child_id(&self, index: usize) -> usize { if index == 0 { self.first_child } else { self.other_children[index - 1].child } } #[inline] pub fn child_id_opt(&self, index: usize) -> Option { if index == 0 { Some(self.first_child) } else { self.other_children.get(index - 1).map(|b| b.child) } } #[inline] pub fn separators(&self, index: usize) -> (Option<&K>, Option<&K>) { let min = if index > 0 { Some(self.other_children[index - 1].item.key()) } else { None }; let max = if index < self.other_children.len() { Some(self.other_children[index].item.key()) } else { None }; (min, max) } #[inline] pub fn get(&self, key: &Q) -> Result<&V, usize> where K: Borrow, Q: Ord, { match binary_search_min(&self.other_children, key) { Some(offset) => { let b = &self.other_children[offset]; if b.item.key().borrow() == key { Ok(b.item.value()) } else { Err(b.child) } } None => Err(self.first_child), } } #[inline] pub fn get_mut(&mut self, key: &Q) -> Result<&mut V, usize> where K: Borrow, Q: Ord, { match binary_search_min(&self.other_children, key) { Some(offset) => { let b = &mut self.other_children[offset]; if b.item.key().borrow() == key { Ok(b.item.value_mut()) } else { Err(b.child) } } None => Err(self.first_child), } } /// Find the offset of the item matching the given key. /// /// If the key matches no item in this node, /// this funtion returns the index and id of the child that may match the key. #[inline] pub fn offset_of(&self, key: &Q) -> Result where K: Borrow, Q: Ord, { match binary_search_min(&self.other_children, key) { Some(offset) => { if self.other_children[offset].item.key().borrow() == key { Ok(offset.into()) } else { let id = self.other_children[offset].child; Err((offset + 1, id)) } } None => Err((0, self.first_child)), } } #[inline] pub fn children(&self) -> Children { Children::Internal(Some(self.first_child), self.other_children.as_ref().iter()) } #[inline] pub fn children_with_separators(&self) -> ChildrenWithSeparators { ChildrenWithSeparators::Internal( Some(self.first_child), None, self.other_children.as_ref().iter().peekable(), ) } #[inline] pub fn item(&self, offset: Offset) -> Option<&Item> { match self.other_children.get(offset.unwrap()) { Some(b) => Some(&b.item), None => None, } } #[inline] pub fn item_mut(&mut self, offset: Offset) -> Option<&mut Item> { match self.other_children.get_mut(offset.unwrap()) { Some(b) => Some(&mut b.item), None => None, } } /// Insert by key. /// /// #[inline] pub fn insert_by_key( &mut self, key: K, mut value: V, ) -> Result<(Offset, V), InsertionError> where K: Ord, { match binary_search_min(&self.other_children, &key) { Some(i) => { if self.other_children[i].item.key() == &key { std::mem::swap(&mut value, self.other_children[i].item.value_mut()); Ok((i.into(), value)) } else { Err(InsertionError { key, value, child_offset: i + 1, child_id: self.other_children[i].child, }) } } None => Err(InsertionError { key, value, child_offset: 0, child_id: self.first_child, }), } } // /// Get the offset of the item with the given key. // #[inline] // pub fn key_offset(&self, key: &K) -> Result { // match binary_search_min(&self.other_children, key) { // Some(i) => { // if self.other_children[i].item.key() == key { // Ok(i) // } else { // Err((i+1, self.other_children[i].child)) // } // }, // None => { // Err((0, self.first_child)) // } // } // } /// Insert item at the given offset. #[inline] pub fn insert(&mut self, offset: Offset, item: Item, right_node_id: usize) { self.other_children.insert( offset.unwrap(), Branch { item, child: right_node_id, }, ); } /// Replace the item at the given offset. #[inline] pub fn replace(&mut self, offset: Offset, mut item: Item) -> Item { std::mem::swap(&mut item, &mut self.other_children[offset.unwrap()].item); item } /// Remove the item at the given offset. /// Return the child id on the left of the item, the item, and the child id on the right /// (which is also removed). #[inline] pub fn remove(&mut self, offset: Offset) -> (usize, Item, usize) { let offset = offset.unwrap(); let left_child_id = self.child_id(offset); let b = self.other_children.remove(offset); (left_child_id, b.item, b.child) } #[inline] pub fn split(&mut self) -> (usize, Item, Internal) { assert!(self.is_overflowing()); // implies self.other_children.len() >= 4 // Index of the median-key item in `other_children`. let median_i = (self.other_children.len() - 1) / 2; // Since M is at least 3, `median_i` is at least 1. let right_other_children = self.other_children.drain(median_i + 1..).collect(); let median = self.other_children.pop().unwrap(); let right_node = Internal { parent: self.parent, first_child: median.child, other_children: right_other_children, }; assert!(!self.is_underflowing()); assert!(!right_node.is_underflowing()); (self.other_children.len(), median.item, right_node) } /// Merge the children at the given indexes. /// /// It is supposed that `left_index` is `right_index-1`. /// This method returns the identifier of the left node in the tree, the identifier of the right node, /// the item removed from this node to be merged with the merged children and /// the balance status of this node after the merging operation. #[inline] pub fn merge( &mut self, left_index: usize, right_index: usize, ) -> (usize, usize, usize, Item, Balance) { let left_id = self.child_id(left_index); let right_id = self.child_id(right_index); // We remove the right child (the one of index `right_index`). // Since left_index = right_index-1, it is indexed by `left_index` in `other_children`. let item = self.other_children.remove(left_index).item; (left_index, left_id, right_id, item, self.balance()) } #[inline] pub fn push_left(&mut self, item: Item, child_id: usize) { self.other_children.insert( 0, Branch { item, child: self.first_child, }, ); self.first_child = child_id } #[inline] pub fn pop_left(&mut self) -> Result<(Item, usize), WouldUnderflow> { if self.item_count() <= UNDERFLOW { Err(WouldUnderflow) } else { let child_id = self.first_child; let first = self.other_children.remove(0); self.first_child = first.child; Ok((first.item, child_id)) } } #[inline] pub fn push_right(&mut self, item: Item, child_id: usize) -> Offset { let offset = self.other_children.len(); self.other_children.push(Branch { item, child: child_id, }); offset.into() } #[inline] pub fn pop_right(&mut self) -> Result<(Offset, Item, usize), WouldUnderflow> { if self.item_count() <= UNDERFLOW { Err(WouldUnderflow) } else { let offset = self.other_children.len(); let last = self.other_children.pop().unwrap(); Ok((offset.into(), last.item, last.child)) } } #[inline] pub fn append(&mut self, separator: Item, mut other: Internal) -> Offset { let offset = self.other_children.len(); self.other_children.push(Branch { item: separator, child: other.first_child, }); self.other_children.append(&mut other.other_children); offset.into() } /// Write the label of the internal node in the DOT format. /// /// Requires the `dot` feature. #[cfg(feature = "dot")] #[inline] pub fn dot_write_label(&self, f: &mut W) -> std::io::Result<()> where K: std::fmt::Display, V: std::fmt::Display, { write!(f, " |")?; let mut i = 1; for branch in &self.other_children { write!( f, "{{{}| {}}} |", branch.item.key(), i, branch.item.value() )?; i += 1; } Ok(()) } #[cfg(debug_assertions)] pub fn validate(&self, parent: Option, min: Option<&K>, max: Option<&K>) where K: Ord, { if self.parent() != parent { panic!("wrong parent") } if min.is_some() || max.is_some() { // not root match self.balance() { Balance::Overflow => panic!("internal node is overflowing"), Balance::Underflow(_) => panic!("internal node is underflowing"), _ => (), } } else if self.item_count() == 0 { panic!("root node is empty") } if !self.other_children.windows(2).all(|w| w[0] < w[1]) { panic!("internal node items are not sorted") } if let Some(min) = min { if let Some(b) = self.other_children.first() { if min >= b.item.key() { panic!("internal node item key is greater than right separator") } } } if let Some(max) = max { if let Some(b) = self.other_children.last() { if max <= b.item.key() { panic!("internal node item key is less than left separator") } } } } } btree-slab-0.6.1/src/generic/node/item.rs000064400000000000000000000110131046102023000163000ustar 00000000000000use super::Keyed; use std::{cmp::Ordering, mem::MaybeUninit}; pub struct Item { /// # Safety /// /// This field must always be initialized when the item is accessed and/or dropped. key: MaybeUninit, /// # Safety /// /// This field must always be initialized when the item is accessed and/or dropped. value: MaybeUninit, } impl Clone for Item { fn clone(&self) -> Self { unsafe { Self::new( self.key.assume_init_ref().clone(), self.value.assume_init_ref().clone(), ) } } } impl AsRef> for Item { fn as_ref(&self) -> &Self { self } } impl Item { pub fn new(key: K, value: V) -> Item { Item { key: MaybeUninit::new(key), value: MaybeUninit::new(value), } } #[inline] pub fn key(&self) -> &K { unsafe { self.key.assume_init_ref() } } /// Modifying a key in such a way that its order with regard to other keys changes is a logical error. #[inline] pub fn key_mut(&mut self) -> &mut K { unsafe { self.key.assume_init_mut() } } #[inline] pub fn value(&self) -> &V { unsafe { self.value.assume_init_ref() } } #[inline] pub fn value_mut(&mut self) -> &mut V { unsafe { self.value.assume_init_mut() } } /// Modifying a key in such a way that its order with regard to other keys changes is a logical error. #[inline] pub fn set(&mut self, key: K, value: V) -> (K, V) { let mut old_key = MaybeUninit::new(key); let mut old_value = MaybeUninit::new(value); std::mem::swap(&mut old_key, &mut self.key); std::mem::swap(&mut old_value, &mut self.value); unsafe { (old_key.assume_init(), old_value.assume_init()) } } /// Modifying a key in such a way that its order with regard to other keys changes is a logical error. #[inline] pub fn set_key(&mut self, key: K) -> K { let mut old_key = MaybeUninit::new(key); std::mem::swap(&mut old_key, &mut self.key); unsafe { old_key.assume_init() } } #[inline] pub fn set_value(&mut self, value: V) -> V { let mut old_value = MaybeUninit::new(value); std::mem::swap(&mut old_value, &mut self.value); unsafe { old_value.assume_init() } } #[inline] pub fn maybe_uninit_value_mut(&mut self) -> &mut MaybeUninit { &mut self.value } #[inline] pub fn into_key(self) -> K { let (key, value) = self.into_inner(); unsafe { std::mem::drop(value.assume_init()); key.assume_init() } } #[inline] pub fn into_value(self) -> V { let (key, value) = self.into_inner(); unsafe { std::mem::drop(key.assume_init()); value.assume_init() } } #[inline] pub fn as_pair(&self) -> (&K, &V) { unsafe { (self.key.assume_init_ref(), self.value.assume_init_ref()) } } #[inline] pub fn as_pair_mut(&mut self) -> (&mut K, &mut V) { unsafe { (self.key.assume_init_mut(), self.value.assume_init_mut()) } } #[inline] pub fn into_pair(self) -> (K, V) { let (key, value) = self.into_inner(); unsafe { (key.assume_init(), value.assume_init()) } } /// Drop the key but not the value which is assumed uninitialized. /// /// # Safety /// /// The value must be uninitialized. #[inline] pub unsafe fn forget_value(self) { let (key, _) = self.into_inner(); std::mem::drop(key.assume_init()) } #[inline] pub fn into_inner(mut self) -> (MaybeUninit, MaybeUninit) { let mut key = MaybeUninit::uninit(); let mut value = MaybeUninit::uninit(); std::mem::swap(&mut key, &mut self.key); std::mem::swap(&mut value, &mut self.value); std::mem::forget(self); (key, value) } } impl Drop for Item { fn drop(&mut self) { unsafe { std::ptr::drop_in_place(self.key.assume_init_mut()); std::ptr::drop_in_place(self.value.assume_init_mut()); } } } impl Keyed for Item { type Key = K; #[inline] fn key(&self) -> &K { self.key() } } // impl> PartialEq for Item { // fn eq(&self, other: &T) -> bool { // other.eq(self.key()) // } // } // impl> PartialOrd for Item { // fn partial_cmp(&self, other: &T) -> Option { // match other.partial_cmp(self.key()) { // Some(Ordering::Greater) => Some(Ordering::Less), // Some(Ordering::Less) => Some(Ordering::Greater), // Some(Ordering::Equal) => Some(Ordering::Equal), // None => None // } // } // } impl PartialEq for Item { fn eq(&self, other: &Item) -> bool { self.key().eq(other.key()) } } impl PartialOrd for Item { fn partial_cmp(&self, other: &Item) -> Option { Some(self.key().cmp(other.key())) } } btree-slab-0.6.1/src/generic/node/leaf.rs000064400000000000000000000144761046102023000162710ustar 00000000000000use crate::{ generic::{ map::M, node::{Balance, Item, Offset, WouldUnderflow}, }, utils::binary_search_min, }; use smallvec::SmallVec; use std::borrow::Borrow; #[derive(Clone)] pub struct Leaf { parent: usize, items: SmallVec<[Item; M + 1]>, } impl Leaf { #[inline] pub fn new(parent: Option, item: Item) -> Leaf { let mut items = SmallVec::new(); items.push(item); Leaf { parent: parent.unwrap_or(std::usize::MAX), items, } } #[inline] pub fn parent(&self) -> Option { if self.parent == std::usize::MAX { None } else { Some(self.parent) } } #[inline] pub fn set_parent(&mut self, p: Option) { self.parent = p.unwrap_or(std::usize::MAX); } #[inline] pub fn item_count(&self) -> usize { self.items.len() } #[inline] pub fn items(&self) -> &[Item] { self.items.as_ref() } #[inline] pub fn iter(&self) -> std::slice::Iter> { self.items.as_ref().iter() } #[inline] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord, { match binary_search_min(&self.items, key) { Some(i) => { let item = &self.items[i]; if item.key().borrow() == key { Some(item.value()) } else { None } } _ => None, } } #[inline] pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord, { match binary_search_min(&self.items, key) { Some(i) => { let item = &mut self.items[i]; if item.key().borrow() == key { Some(item.value_mut()) } else { None } } _ => None, } } /// Find the offset of the item matching the given key. #[inline] pub fn offset_of(&self, key: &Q) -> Result where K: Borrow, Q: Ord, { match binary_search_min(&self.items, key) { Some(i) => { if self.items[i].key().borrow() == key { Ok(i.into()) } else { Err((i + 1).into()) } } None => Err(0.into()), } } #[inline] pub fn item(&self, offset: Offset) -> Option<&Item> { match offset.value() { Some(offset) => self.items.get(offset), None => None, } } #[inline] pub fn item_mut(&mut self, offset: Offset) -> Option<&mut Item> { match offset.value() { Some(offset) => self.items.get_mut(offset), None => None, } } #[inline] pub fn insert_by_key(&mut self, key: K, mut value: V) -> (Offset, Option) where K: Ord, { match binary_search_min(&self.items, &key) { Some(i) => { if self.items[i].key() == &key { std::mem::swap(&mut value, self.items[i].value_mut()); (i.into(), Some(value)) } else { self.items.insert(i + 1, Item::new(key, value)); ((i + 1).into(), None) } } None => { self.items.insert(0, Item::new(key, value)); (0.into(), None) } } } #[inline] pub fn split(&mut self) -> (usize, Item, Leaf) { assert!(self.is_overflowing()); let median_i = (self.items.len() - 1) / 2; let right_items = self.items.drain(median_i + 1..).collect(); let median = self.items.pop().unwrap(); let right_leaf = Leaf { parent: self.parent, items: right_items, }; assert!(!self.is_underflowing()); assert!(!right_leaf.is_underflowing()); (self.items.len(), median, right_leaf) } #[inline] pub fn append(&mut self, separator: Item, mut other: Leaf) -> Offset { let offset = self.items.len(); self.items.push(separator); self.items.append(&mut other.items); offset.into() } #[inline] pub fn push_left(&mut self, item: Item) { self.items.insert(0, item) } #[inline] pub fn pop_left(&mut self) -> Result, WouldUnderflow> { if self.item_count() < M / 2 { Err(WouldUnderflow) } else { Ok(self.items.remove(0)) } } #[inline] pub fn push_right(&mut self, item: Item) -> Offset { let offset = self.items.len(); self.items.push(item); offset.into() } #[inline] pub fn pop_right(&mut self) -> Result<(Offset, Item), WouldUnderflow> { if self.item_count() < M / 2 { Err(WouldUnderflow) } else { let offset = self.items.len(); let item = self.items.pop().unwrap(); Ok((offset.into(), item)) } } #[inline] pub fn balance(&self) -> Balance { if self.is_overflowing() { Balance::Overflow } else if self.is_underflowing() { Balance::Underflow(self.items.is_empty()) } else { Balance::Balanced } } #[inline] pub fn is_overflowing(&self) -> bool { self.item_count() > M } #[inline] pub fn is_underflowing(&self) -> bool { self.item_count() < M / 2 - 1 } /// It is assumed that the leaf will not overflow. #[inline] pub fn insert(&mut self, offset: Offset, item: Item) { match offset.value() { Some(offset) => self.items.insert(offset, item), None => panic!("Offset out of bounds"), } } /// Remove the item at the given offset. /// Return the new balance of the leaf. #[inline] pub fn remove(&mut self, offset: Offset) -> Item { match offset.value() { Some(offset) => self.items.remove(offset), None => panic!("Offset out of bounds"), } } #[inline] pub fn remove_last(&mut self) -> Item { self.items.pop().unwrap() } /// Write the label of the leaf in the DOT language. /// /// Requires the `dot` feature. #[cfg(feature = "dot")] #[inline] pub fn dot_write_label(&self, f: &mut W) -> std::io::Result<()> where K: std::fmt::Display, V: std::fmt::Display, { for item in &self.items { write!(f, "{{{}|{}}}|", item.key(), item.value())?; } Ok(()) } #[cfg(debug_assertions)] pub fn validate(&self, parent: Option, min: Option<&K>, max: Option<&K>) where K: Ord, { if self.parent() != parent { panic!("wrong parent") } if min.is_some() || max.is_some() { // not root match self.balance() { Balance::Overflow => panic!("leaf is overflowing"), Balance::Underflow(_) => panic!("leaf is underflowing"), _ => (), } } if !self.items.windows(2).all(|w| w[0] < w[1]) { panic!("leaf items are not sorted") } if let Some(min) = min { if let Some(item) = self.items.first() { if min >= item.key() { panic!("leaf item key is greater than right separator") } } } if let Some(max) = max { if let Some(item) = self.items.last() { if max <= item.key() { panic!("leaf item key is less than left separator") } } } } } btree-slab-0.6.1/src/generic/node.rs000064400000000000000000000323251046102023000153530ustar 00000000000000use std::{borrow::Borrow, cmp::Ordering, fmt}; mod addr; pub mod internal; mod item; mod leaf; pub use addr::Address; pub use internal::Internal as InternalNode; pub use item::Item; pub use leaf::Leaf as LeafNode; /// Type identifier by a key. /// /// This is implemented by [`Item`] and [`internal::Branch`]. pub trait Keyed { type Key; fn key(&self) -> &Self::Key; } /// Offset in a node. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct Offset(usize); impl Offset { pub fn before() -> Offset { Offset(usize::MAX) } pub fn is_before(&self) -> bool { self.0 == usize::MAX } pub fn value(&self) -> Option { if self.0 == usize::MAX { None } else { Some(self.0) } } pub fn unwrap(self) -> usize { if self.0 == usize::MAX { panic!("Offset out of bounds") } else { self.0 } } pub fn incr(&mut self) { if self.0 == usize::MAX { self.0 = 0 } else { self.0 += 1 } } pub fn decr(&mut self) { if self.0 == 0 { self.0 = usize::MAX } else { self.0 -= 1 } } } impl PartialOrd for Offset { fn partial_cmp(&self, offset: &Offset) -> Option { if self.0 == usize::MAX || offset.0 == usize::MAX { if self.0 == usize::MAX && offset.0 == usize::MAX { Some(Ordering::Equal) } else if self.0 == usize::MAX { Some(Ordering::Less) } else { Some(Ordering::Greater) } } else { self.0.partial_cmp(&offset.0) } } } impl Ord for Offset { fn cmp(&self, offset: &Offset) -> Ordering { if self.0 == usize::MAX || offset.0 == usize::MAX { if self.0 == usize::MAX && offset.0 == usize::MAX { Ordering::Equal } else if self.0 == usize::MAX { Ordering::Less } else { Ordering::Greater } } else { self.0.cmp(&offset.0) } } } impl PartialEq for Offset { fn eq(&self, offset: &usize) -> bool { self.0 != usize::MAX && self.0 == *offset } } impl PartialOrd for Offset { fn partial_cmp(&self, offset: &usize) -> Option { if self.0 == usize::MAX { Some(Ordering::Less) } else { self.0.partial_cmp(offset) } } } impl From for Offset { fn from(offset: usize) -> Offset { Offset(offset) } } impl fmt::Display for Offset { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.0 == usize::MAX { write!(f, "-1") } else { self.0.fmt(f) } } } impl fmt::Debug for Offset { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.0 == usize::MAX { write!(f, "-1") } else { self.0.fmt(f) } } } /// Node balance. #[derive(Debug)] pub enum Balance { /// The node is balanced. Balanced, /// The node is overflowing. Overflow, /// The node is underflowing. /// /// The boolean is `true` if the node is empty. Underflow(bool), } /// Error returned when an operation on the node would result in an underflow. pub struct WouldUnderflow; /// Type of the value returned by `Node::pop_right`. /// /// It includes the offset of the popped item, the item itself and the index of /// the right child of the item if it is removed from an internal node. pub type PoppedItem = (Offset, Item, Option); /// B-tree node. #[derive(Clone)] pub enum Node { /// Internal node. Internal(InternalNode), /// Leaf node. Leaf(LeafNode), } impl Node { #[inline] pub fn binary( parent: Option, left_id: usize, median: Item, right_id: usize, ) -> Node { Node::Internal(InternalNode::binary(parent, left_id, median, right_id)) } #[inline] pub fn leaf(parent: Option, item: Item) -> Node { Node::Leaf(LeafNode::new(parent, item)) } #[inline] pub fn balance(&self) -> Balance { match self { Node::Internal(node) => node.balance(), Node::Leaf(leaf) => leaf.balance(), } } #[inline] pub fn is_underflowing(&self) -> bool { match self { Node::Internal(node) => node.is_underflowing(), Node::Leaf(leaf) => leaf.is_underflowing(), } } #[inline] pub fn is_overflowing(&self) -> bool { match self { Node::Internal(node) => node.is_overflowing(), Node::Leaf(leaf) => leaf.is_overflowing(), } } #[inline] pub fn parent(&self) -> Option { match self { Node::Internal(node) => node.parent(), Node::Leaf(leaf) => leaf.parent(), } } #[inline] pub fn set_parent(&mut self, p: Option) { match self { Node::Internal(node) => node.set_parent(p), Node::Leaf(leaf) => leaf.set_parent(p), } } #[inline] pub fn item_count(&self) -> usize { match self { Node::Internal(node) => node.item_count(), Node::Leaf(leaf) => leaf.item_count(), } } #[inline] pub fn child_count(&self) -> usize { match self { Node::Internal(node) => node.child_count(), Node::Leaf(_) => 0, } } #[inline] pub fn child_index(&self, id: usize) -> Option { match self { Node::Internal(node) => node.child_index(id), _ => None, } } #[inline] pub fn child_id(&self, index: usize) -> usize { match self { Node::Internal(node) => node.child_id(index), _ => panic!("only internal nodes can be indexed"), } } #[inline] pub fn child_id_opt(&self, index: usize) -> Option { match self { Node::Internal(node) => node.child_id_opt(index), Node::Leaf(_) => None, } } #[inline] pub fn get(&self, key: &Q) -> Result, usize> where K: Borrow, Q: Ord, { match self { Node::Leaf(leaf) => Ok(leaf.get(key)), Node::Internal(node) => match node.get(key) { Ok(value) => Ok(Some(value)), Err(e) => Err(e), }, } } #[inline] pub fn get_mut(&mut self, key: &Q) -> Result, usize> where K: Borrow, Q: Ord, { match self { Node::Leaf(leaf) => Ok(leaf.get_mut(key)), Node::Internal(node) => match node.get_mut(key) { Ok(value) => Ok(Some(value)), Err(e) => Err(e), }, } } /// Find the offset of the item matching the given key. /// /// If the key matches no item in this node, /// this funtion returns the index and id of the child that may match the key, /// or `Err(None)` if it is a leaf. #[inline] pub fn offset_of(&self, key: &Q) -> Result)> where K: Borrow, Q: Ord, { match self { Node::Internal(node) => match node.offset_of(key) { Ok(i) => Ok(i), Err((index, child_id)) => Err((index, Some(child_id))), }, Node::Leaf(leaf) => match leaf.offset_of(key) { Ok(i) => Ok(i), Err(index) => Err((index.unwrap(), None)), }, } } #[inline] pub fn item(&self, offset: Offset) -> Option<&Item> { match self { Node::Internal(node) => node.item(offset), Node::Leaf(leaf) => leaf.item(offset), } } #[inline] pub fn item_mut(&mut self, offset: Offset) -> Option<&mut Item> { match self { Node::Internal(node) => node.item_mut(offset), Node::Leaf(leaf) => leaf.item_mut(offset), } } /// Insert by key. /// /// It is assumed that the node is not free. /// If it is a leaf node, there must be a free space in it for the inserted value. #[inline] pub fn insert_by_key( &mut self, key: K, value: V, ) -> Result<(Offset, Option), internal::InsertionError> where K: Ord, { match self { Node::Internal(node) => match node.insert_by_key(key, value) { Ok((offset, value)) => Ok((offset, Some(value))), Err(e) => Err(e), }, Node::Leaf(leaf) => Ok(leaf.insert_by_key(key, value)), } } /// Split the node. /// Return the length of the node after split, the median item and the right node. #[inline] pub fn split(&mut self) -> (usize, Item, Node) { match self { Node::Internal(node) => { let (len, item, right_node) = node.split(); (len, item, Node::Internal(right_node)) } Node::Leaf(leaf) => { let (len, item, right_leaf) = leaf.split(); (len, item, Node::Leaf(right_leaf)) } } } #[inline] pub fn merge( &mut self, left_index: usize, right_index: usize, ) -> (usize, usize, usize, Item, Balance) { match self { Node::Internal(node) => node.merge(left_index, right_index), _ => panic!("only internal nodes can merge children"), } } /// Return the offset of the separator. #[inline] pub fn append(&mut self, separator: Item, other: Node) -> Offset { match (self, other) { (Node::Internal(node), Node::Internal(other)) => node.append(separator, other), (Node::Leaf(leaf), Node::Leaf(other)) => leaf.append(separator, other), _ => panic!("incompatibles nodes"), } } #[inline] pub fn push_left(&mut self, item: Item, opt_child_id: Option) { match self { Node::Internal(node) => node.push_left(item, opt_child_id.unwrap()), Node::Leaf(leaf) => leaf.push_left(item), } } #[inline] pub fn pop_left(&mut self) -> Result<(Item, Option), WouldUnderflow> { match self { Node::Internal(node) => { let (item, child_id) = node.pop_left()?; Ok((item, Some(child_id))) } Node::Leaf(leaf) => Ok((leaf.pop_left()?, None)), } } #[inline] pub fn push_right(&mut self, item: Item, opt_child_id: Option) -> Offset { match self { Node::Internal(node) => node.push_right(item, opt_child_id.unwrap()), Node::Leaf(leaf) => leaf.push_right(item), } } #[inline] pub fn pop_right(&mut self) -> Result, WouldUnderflow> { match self { Node::Internal(node) => { let (offset, item, child_id) = node.pop_right()?; Ok((offset, item, Some(child_id))) } Node::Leaf(leaf) => { let (offset, item) = leaf.pop_right()?; Ok((offset, item, None)) } } } #[inline] pub fn leaf_remove(&mut self, offset: Offset) -> Option, usize>> { match self { Node::Internal(node) => { if offset < node.item_count() { let left_child_index = offset.unwrap(); Some(Err(node.child_id(left_child_index))) } else { None } } Node::Leaf(leaf) => { if offset < leaf.item_count() { Some(Ok(leaf.remove(offset))) } else { None } } } } #[inline] pub fn remove_rightmost_leaf(&mut self) -> Result, usize> { match self { Node::Internal(node) => { let child_index = node.child_count() - 1; let child_id = node.child_id(child_index); Err(child_id) } Node::Leaf(leaf) => Ok(leaf.remove_last()), } } /// Put an item in a node. /// /// It is assumed that the node will not overflow. #[inline] pub fn insert(&mut self, offset: Offset, item: Item, opt_right_child_id: Option) { match self { Node::Internal(node) => node.insert(offset, item, opt_right_child_id.unwrap()), Node::Leaf(leaf) => leaf.insert(offset, item), } } #[inline] pub fn replace(&mut self, offset: Offset, item: Item) -> Item { match self { Node::Internal(node) => node.replace(offset, item), _ => panic!("can only replace in internal nodes"), } } #[inline] pub fn separators(&self, i: usize) -> (Option<&K>, Option<&K>) { match self { Node::Leaf(_) => (None, None), Node::Internal(node) => node.separators(i), } } #[inline] pub fn children(&self) -> Children { match self { Node::Leaf(_) => Children::Leaf, Node::Internal(node) => node.children(), } } #[inline] pub fn children_with_separators(&self) -> ChildrenWithSeparators { match self { Node::Leaf(_) => ChildrenWithSeparators::Leaf, Node::Internal(node) => node.children_with_separators(), } } /// Write the label of the node in the DOT format. /// /// Requires the `dot` feature. #[cfg(feature = "dot")] #[inline] pub fn dot_write_label(&self, f: &mut W) -> std::io::Result<()> where K: std::fmt::Display, V: std::fmt::Display, { match self { Node::Leaf(leaf) => leaf.dot_write_label(f), Node::Internal(node) => node.dot_write_label(f), } } #[cfg(debug_assertions)] pub fn validate(&self, parent: Option, min: Option<&K>, max: Option<&K>) where K: Ord, { match self { Node::Leaf(leaf) => leaf.validate(parent, min, max), Node::Internal(node) => node.validate(parent, min, max), } } } pub enum Children<'a, K, V> { Leaf, Internal(Option, std::slice::Iter<'a, internal::Branch>), } impl<'a, K, V> Iterator for Children<'a, K, V> { type Item = usize; #[inline] fn next(&mut self) -> Option { match self { Children::Leaf => None, Children::Internal(first, rest) => match first.take() { Some(child) => Some(child), None => rest.next().map(|branch| branch.child), }, } } } pub enum ChildrenWithSeparators<'a, K, V> { Leaf, Internal( Option, Option<&'a Item>, std::iter::Peekable>>, ), } impl<'a, K, V> Iterator for ChildrenWithSeparators<'a, K, V> { type Item = (Option<&'a Item>, usize, Option<&'a Item>); #[inline] fn next(&mut self) -> Option { match self { ChildrenWithSeparators::Leaf => None, ChildrenWithSeparators::Internal(first, left_sep, rest) => match first.take() { Some(child) => { let right_sep = rest.peek().map(|right| &right.item); *left_sep = right_sep; Some((None, child, right_sep)) } None => match rest.next() { Some(branch) => { let right_sep = rest.peek().map(|right| &right.item); let result = Some((*left_sep, branch.child, right_sep)); *left_sep = right_sep; result } None => None, }, }, } } } btree-slab-0.6.1/src/generic/set.rs000064400000000000000000000671121046102023000152230ustar 00000000000000use crate::generic::{map, node::Node, BTreeMap}; use cc_traits::{SimpleCollectionMut, SimpleCollectionRef, Slab, SlabMut}; use std::{ borrow::Borrow, cmp::Ordering, hash::{Hash, Hasher}, iter::{DoubleEndedIterator, ExactSizeIterator, FromIterator, FusedIterator, Peekable}, ops::RangeBounds, }; /// A set based on a B-Tree. /// /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance benefits and drawbacks. /// /// It is a logic error for an item to be modified in such a way that the item's ordering relative /// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. /// /// [`Ord`]: core::cmp::Ord /// [`Cell`]: core::cell::Cell /// [`RefCell`]: core::cell::RefCell pub struct BTreeSet { map: BTreeMap, } impl BTreeSet { /// Makes a new, empty `BTreeSet`. /// /// # Example /// /// ``` /// # #![allow(unused_mut)] /// use btree_slab::BTreeSet; /// /// let mut set: BTreeSet = BTreeSet::new(); /// ``` #[inline] pub fn new() -> Self where C: Default, { Self::default() } /// Returns the number of elements in the set. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut v = BTreeSet::new(); /// assert_eq!(v.len(), 0); /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` #[inline] pub fn len(&self) -> usize { self.map.len() } /// Returns `true` if the set contains no elements. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut v = BTreeSet::new(); /// assert!(v.is_empty()); /// v.insert(1); /// assert!(!v.is_empty()); /// ``` #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } } impl Default for BTreeSet { fn default() -> Self { BTreeSet { map: BTreeMap::default(), } } } impl>> BTreeSet where C: SimpleCollectionRef, { /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. /// /// # Examples /// /// ``` /// use btree_slab::BTreeSet; /// /// let set: BTreeSet = [1, 2, 3].iter().cloned().collect(); /// let mut set_iter = set.iter(); /// assert_eq!(set_iter.next(), Some(&1)); /// assert_eq!(set_iter.next(), Some(&2)); /// assert_eq!(set_iter.next(), Some(&3)); /// assert_eq!(set_iter.next(), None); /// ``` /// /// Values returned by the iterator are returned in ascending order: /// /// ``` /// use btree_slab::BTreeSet; /// /// let set: BTreeSet = [3, 1, 2].iter().cloned().collect(); /// let mut set_iter = set.iter(); /// assert_eq!(set_iter.next(), Some(&1)); /// assert_eq!(set_iter.next(), Some(&2)); /// assert_eq!(set_iter.next(), Some(&3)); /// assert_eq!(set_iter.next(), None); /// ``` #[inline] pub fn iter(&self) -> Iter { Iter { inner: self.map.keys(), } } } impl>> BTreeSet where C: SimpleCollectionRef, { /// Returns `true` if the set contains a value. /// /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` #[inline] pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: Ord, { self.map.contains_key(value) } /// Returns a reference to the value in the set, if any, that is equal to the given value. /// /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` #[inline] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: Ord, { match self.map.get_key_value(value) { Some((t, ())) => Some(t), None => None, } } /// Constructs a double-ended iterator over a sub-range of elements in the set. /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will /// yield elements from min (inclusive) to max (exclusive). /// The range may also be entered as `(Bound, Bound)`, so for example /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive /// range from 4 to 10. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// use std::ops::Bound::Included; /// /// let mut set = BTreeSet::new(); /// set.insert(3); /// set.insert(5); /// set.insert(8); /// for &elem in set.range((Included(&4), Included(&8))) { /// println!("{}", elem); /// } /// assert_eq!(Some(&5), set.range(4..).next()); /// ``` #[inline] pub fn range(&self, range: R) -> Range where K: Ord, T: Borrow, R: RangeBounds, { Range { inner: self.map.range(range), } } /// Visits the values representing the union, /// i.e., all the values in `self` or `other`, without duplicates, /// in ascending order. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut a = BTreeSet::new(); /// a.insert(1); /// /// let mut b = BTreeSet::new(); /// b.insert(2); /// /// let union: Vec<_> = a.union(&b).cloned().collect(); /// assert_eq!(union, [1, 2]); /// ``` #[inline] pub fn union<'a, D: Slab>>( &'a self, other: &'a BTreeSet, ) -> Union<'a, T, C, D> where D: SimpleCollectionRef, { Union { it1: self.iter().peekable(), it2: other.iter().peekable(), } } /// Visits the values representing the intersection, /// i.e., the values that are both in `self` and `other`, /// in ascending order. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut a = BTreeSet::new(); /// a.insert(1); /// a.insert(2); /// /// let mut b = BTreeSet::new(); /// b.insert(2); /// b.insert(3); /// /// let intersection: Vec<_> = a.intersection(&b).cloned().collect(); /// assert_eq!(intersection, [2]); /// ``` #[inline] pub fn intersection<'a, D: Slab>>( &'a self, other: &'a BTreeSet, ) -> Intersection<'a, T, C, D> where D: SimpleCollectionRef, { Intersection { it1: self.iter(), it2: other.iter().peekable(), } } /// Visits the values representing the difference, /// i.e., the values that are in `self` but not in `other`, /// in ascending order. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut a = BTreeSet::new(); /// a.insert(1); /// a.insert(2); /// /// let mut b = BTreeSet::new(); /// b.insert(2); /// b.insert(3); /// /// let diff: Vec<_> = a.difference(&b).cloned().collect(); /// assert_eq!(diff, [1]); /// ``` #[inline] pub fn difference<'a, D: Slab>>( &'a self, other: &'a BTreeSet, ) -> Difference<'a, T, C, D> where D: SimpleCollectionRef, { Difference { it1: self.iter(), it2: other.iter().peekable(), } } /// Visits the values representing the symmetric difference, /// i.e., the values that are in `self` or in `other` but not in both, /// in ascending order. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut a = BTreeSet::new(); /// a.insert(1); /// a.insert(2); /// /// let mut b = BTreeSet::new(); /// b.insert(2); /// b.insert(3); /// /// let sym_diff: Vec<_> = a.symmetric_difference(&b).cloned().collect(); /// assert_eq!(sym_diff, [1, 3]); /// ``` #[inline] pub fn symmetric_difference<'a, D: Slab>>( &'a self, other: &'a BTreeSet, ) -> SymmetricDifference<'a, T, C, D> where D: SimpleCollectionRef, { SymmetricDifference { it1: self.iter().peekable(), it2: other.iter().peekable(), } } /// Returns `true` if `self` has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); /// let mut b = BTreeSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); /// b.insert(4); /// assert_eq!(a.is_disjoint(&b), true); /// b.insert(1); /// assert_eq!(a.is_disjoint(&b), false); /// ``` #[inline] pub fn is_disjoint>>(&self, other: &BTreeSet) -> bool where D: SimpleCollectionRef, { self.intersection(other).next().is_none() } /// Returns `true` if the set is a subset of another, /// i.e., `other` contains at least all the values in `self`. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); /// let mut set = BTreeSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); /// set.insert(2); /// assert_eq!(set.is_subset(&sup), true); /// set.insert(4); /// assert_eq!(set.is_subset(&sup), false); /// ``` #[inline] pub fn is_subset>>(&self, other: &BTreeSet) -> bool where D: SimpleCollectionRef, { self.difference(other).next().is_none() } /// Returns `true` if the set is a superset of another, /// i.e., `self` contains at least all the values in `other`. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect(); /// let mut set = BTreeSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); /// /// set.insert(0); /// set.insert(1); /// assert_eq!(set.is_superset(&sub), false); /// /// set.insert(2); /// assert_eq!(set.is_superset(&sub), true); /// ``` #[inline] pub fn is_superset>>(&self, other: &BTreeSet) -> bool where D: SimpleCollectionRef, { other.is_subset(self) } /// Returns a reference to the first value in the set, if any. /// This value is always the minimum of all values in the set. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut map = BTreeSet::new(); /// assert_eq!(map.first(), None); /// map.insert(1); /// assert_eq!(map.first(), Some(&1)); /// map.insert(2); /// assert_eq!(map.first(), Some(&1)); /// ``` #[inline] pub fn first(&self) -> Option<&T> { self.map.first_key_value().map(|(k, _)| k) } /// Returns a reference to the last value in the set, if any. /// This value is always the maximum of all values in the set. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut map = BTreeSet::new(); /// assert_eq!(map.first(), None); /// map.insert(1); /// assert_eq!(map.last(), Some(&1)); /// map.insert(2); /// assert_eq!(map.last(), Some(&2)); /// ``` #[inline] pub fn last(&self) -> Option<&T> { self.map.last_key_value().map(|(k, _)| k) } } impl>> BTreeSet where C: SimpleCollectionRef, C: SimpleCollectionMut, { /// Clears the set, removing all values. /// /// # Examples /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut v = BTreeSet::new(); /// v.insert(1); /// v.clear(); /// assert!(v.is_empty()); /// ``` #[inline] pub fn clear(&mut self) where C: cc_traits::Clear, { self.map.clear() } /// Adds a value to the set. /// /// If the set did not have this value present, `true` is returned. /// /// If the set did have this value present, `false` is returned, and the /// entry is not updated. See the [module-level documentation] for more. /// /// [module-level documentation]: index.html#insert-and-complex-keys /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set = BTreeSet::new(); /// /// assert_eq!(set.insert(2), true); /// assert_eq!(set.insert(2), false); /// assert_eq!(set.len(), 1); /// ``` #[inline] pub fn insert(&mut self, element: T) -> bool where T: Ord, { self.map.insert(element, ()).is_none() } /// Removes a value from the set. Returns whether the value was /// present in the set. /// /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set = BTreeSet::new(); /// /// set.insert(2); /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` #[inline] pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: Ord, { self.map.remove(value).is_some() } /// Removes and returns the value in the set, if any, that is equal to the given one. /// /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. /// /// # Examples /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` #[inline] pub fn take(&mut self, value: &Q) -> Option where T: Borrow, Q: Ord, { self.map.take(value).map(|(t, _)| t) } /// Adds a value to the set, replacing the existing value, if any, that is equal to the given /// one. Returns the replaced value. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set = BTreeSet::new(); /// set.insert(Vec::::new()); /// /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); /// set.replace(Vec::with_capacity(10)); /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); /// ``` #[inline] pub fn replace(&mut self, value: T) -> Option { self.map.replace(value, ()).map(|(t, ())| t) } /// Removes the first value from the set and returns it, if any. /// The first value is always the minimum value in the set. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set = BTreeSet::new(); /// /// set.insert(1); /// while let Some(n) = set.pop_first() { /// assert_eq!(n, 1); /// } /// assert!(set.is_empty()); /// ``` #[inline] pub fn pop_first(&mut self) -> Option { self.map.pop_first().map(|kv| kv.0) } /// Removes the last value from the set and returns it, if any. /// The last value is always the maximum value in the set. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set = BTreeSet::new(); /// /// set.insert(1); /// while let Some(n) = set.pop_last() { /// assert_eq!(n, 1); /// } /// assert!(set.is_empty()); /// ``` #[inline] pub fn pop_last(&mut self) -> Option { self.map.pop_last().map(|kv| kv.0) } /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let xs = [1, 2, 3, 4, 5, 6]; /// let mut set: BTreeSet = xs.iter().cloned().collect(); /// // Keep only the even numbers. /// set.retain(|&k| k % 2 == 0); /// assert!(set.iter().eq([2, 4, 6].iter())); /// ``` #[inline] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, { self.drain_filter(|v| !f(v)); } /// Moves all elements from `other` into `Self`, leaving `other` empty. /// /// # Example /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut a = BTreeSet::new(); /// a.insert(1); /// a.insert(2); /// a.insert(3); /// /// let mut b = BTreeSet::new(); /// b.insert(3); /// b.insert(4); /// b.insert(5); /// /// a.append(&mut b); /// /// assert_eq!(a.len(), 5); /// assert_eq!(b.len(), 0); /// /// assert!(a.contains(&1)); /// assert!(a.contains(&2)); /// assert!(a.contains(&3)); /// assert!(a.contains(&4)); /// assert!(a.contains(&5)); /// ``` #[inline] pub fn append(&mut self, other: &mut Self) where C: Default, { self.map.append(&mut other.map); } /// Creates an iterator which uses a closure to determine if a value should be removed. /// /// If the closure returns true, then the value is removed and yielded. /// If the closure returns false, the value will remain in the list and will not be yielded /// by the iterator. /// /// If the iterator is only partially consumed or not consumed at all, each of the remaining /// values will still be subjected to the closure and removed and dropped if it returns true. /// /// It is unspecified how many more values will be subjected to the closure /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the /// `DrainFilter` itself is leaked. /// /// # Example /// /// Splitting a set into even and odd values, reusing the original set: /// /// ``` /// use btree_slab::BTreeSet; /// /// let mut set: BTreeSet = (0..8).collect(); /// let evens: BTreeSet<_> = set.drain_filter(|v| v % 2 == 0).collect(); /// let odds = set; /// assert_eq!(evens.into_iter().collect::>(), vec![0, 2, 4, 6]); /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 7]); /// ``` #[inline] pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, C, F> where F: 'a + FnMut(&T) -> bool, { DrainFilter::new(self, pred) } } impl Clone for BTreeSet { #[inline] fn clone(&self) -> Self { BTreeSet { map: self.map.clone(), } } #[inline] fn clone_from(&mut self, other: &Self) { self.map.clone_from(&other.map); } } impl> + Default> FromIterator for BTreeSet where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn from_iter(iter: I) -> Self where I: IntoIterator, { let mut set = BTreeSet::new(); set.extend(iter); set } } impl>> IntoIterator for BTreeSet where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = T; type IntoIter = IntoIter; #[inline] fn into_iter(self) -> IntoIter { IntoIter { inner: self.map.into_keys(), } } } impl<'a, T, C: SlabMut>> IntoIterator for &'a BTreeSet where C: SimpleCollectionRef, { type Item = &'a T; type IntoIter = Iter<'a, T, C>; #[inline] fn into_iter(self) -> Iter<'a, T, C> { self.iter() } } impl>> Extend for BTreeSet where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn extend(&mut self, iter: I) where I: IntoIterator, { for t in iter { self.insert(t); } } } impl<'a, T: 'a + Ord + Copy, C: SlabMut>> Extend<&'a T> for BTreeSet where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn extend(&mut self, iter: I) where I: IntoIterator, { self.extend(iter.into_iter().copied()) } } impl, C: Slab>, D: Slab>> PartialEq> for BTreeSet where C: SimpleCollectionRef, D: SimpleCollectionRef, { #[inline] fn eq(&self, other: &BTreeSet) -> bool { self.map.eq(&other.map) } } impl>> Eq for BTreeSet where C: SimpleCollectionRef {} impl, C: Slab>, D: Slab>> PartialOrd> for BTreeSet where C: SimpleCollectionRef, D: SimpleCollectionRef, { #[inline] fn partial_cmp(&self, other: &BTreeSet) -> Option { self.map.partial_cmp(&other.map) } } impl>> Ord for BTreeSet where C: SimpleCollectionRef, { #[inline] fn cmp(&self, other: &BTreeSet) -> Ordering { self.map.cmp(&other.map) } } impl>> Hash for BTreeSet where C: SimpleCollectionRef, { #[inline] fn hash(&self, h: &mut H) { self.map.hash(h) } } pub struct Iter<'a, T, C> { inner: map::Keys<'a, T, (), C>, } impl<'a, T, C: Slab>> Iterator for Iter<'a, T, C> where C: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<&'a T> { self.inner.next() } } impl<'a, T, C: Slab>> DoubleEndedIterator for Iter<'a, T, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<&'a T> { self.inner.next_back() } } impl<'a, T, C: Slab>> FusedIterator for Iter<'a, T, C> where C: SimpleCollectionRef {} impl<'a, T, C: Slab>> ExactSizeIterator for Iter<'a, T, C> where C: SimpleCollectionRef {} pub struct IntoIter { inner: map::IntoKeys, } impl>> Iterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = T; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option { self.inner.next() } } impl>> DoubleEndedIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } } impl>> FusedIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl>> ExactSizeIterator for IntoIter where C: SimpleCollectionRef, C: SimpleCollectionMut, { } pub struct Union<'a, T, C: Slab>, D: Slab>> where C: SimpleCollectionRef, D: SimpleCollectionRef, { it1: Peekable>, it2: Peekable>, } impl<'a, T: Ord, C: Slab>, D: Slab>> Iterator for Union<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { let len1 = self.it1.len(); let len2 = self.it2.len(); (std::cmp::min(len1, len2), Some(std::cmp::max(len1, len2))) } #[inline] fn next(&mut self) -> Option<&'a T> { match (self.it1.peek(), self.it2.peek()) { (Some(v1), Some(v2)) => match v1.cmp(v2) { Ordering::Equal => { self.it1.next(); self.it2.next() } Ordering::Less => self.it1.next(), Ordering::Greater => self.it2.next(), }, (Some(_), None) => self.it1.next(), (None, Some(_)) => self.it2.next(), (None, None) => None, } } } impl<'a, T: Ord, C: Slab>, D: Slab>> FusedIterator for Union<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { } pub struct Intersection<'a, T, C, D: Slab>> where D: SimpleCollectionRef, { it1: Iter<'a, T, C>, it2: Peekable>, } impl<'a, T: Ord, C: Slab>, D: Slab>> Iterator for Intersection<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { let len1 = self.it1.len(); let len2 = self.it2.len(); (0, Some(std::cmp::min(len1, len2))) } #[inline] fn next(&mut self) -> Option<&'a T> { loop { match self.it1.next() { Some(value) => { let keep = loop { match self.it2.peek() { Some(other) => match value.cmp(other) { Ordering::Equal => break true, Ordering::Greater => { self.it2.next(); } Ordering::Less => break false, }, None => break false, } }; if keep { break Some(value); } } None => break None, } } } } impl<'a, T: Ord, C: Slab>, D: Slab>> FusedIterator for Intersection<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { } pub struct Difference<'a, T, C, D: Slab>> where D: SimpleCollectionRef, { it1: Iter<'a, T, C>, it2: Peekable>, } impl<'a, T: Ord, C: Slab>, D: Slab>> Iterator for Difference<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { let len1 = self.it1.len(); let len2 = self.it2.len(); (len1.saturating_sub(len2), Some(self.it1.len())) } #[inline] fn next(&mut self) -> Option<&'a T> { loop { match self.it1.next() { Some(value) => { let keep = loop { match self.it2.peek() { Some(other) => match value.cmp(other) { Ordering::Equal => break false, Ordering::Greater => { self.it2.next(); } Ordering::Less => break true, }, None => break true, } }; if keep { break Some(value); } } None => break None, } } } } impl<'a, T: Ord, C: Slab>, D: Slab>> FusedIterator for Difference<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { } pub struct SymmetricDifference<'a, T, C: Slab>, D: Slab>> where C: SimpleCollectionRef, D: SimpleCollectionRef, { it1: Peekable>, it2: Peekable>, } impl<'a, T: Ord, C: Slab>, D: Slab>> Iterator for SymmetricDifference<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { let len1 = self.it1.len(); let len2 = self.it2.len(); (0, len1.checked_add(len2)) } #[inline] fn next(&mut self) -> Option<&'a T> { loop { match (self.it1.peek(), self.it2.peek()) { (Some(v1), Some(v2)) => match v1.cmp(v2) { Ordering::Equal => { self.it1.next(); self.it2.next(); } Ordering::Less => break self.it1.next(), Ordering::Greater => break self.it2.next(), }, (Some(_), None) => break self.it1.next(), (None, Some(_)) => break self.it2.next(), (None, None) => break None, } } } } impl<'a, T: Ord, C: Slab>, D: Slab>> FusedIterator for SymmetricDifference<'a, T, C, D> where C: SimpleCollectionRef, D: SimpleCollectionRef, { } pub struct DrainFilter<'a, T, C: SlabMut>, F> where F: FnMut(&T) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { pred: F, inner: map::DrainFilterInner<'a, T, (), C>, } impl<'a, T: 'a, C: SlabMut>, F> DrainFilter<'a, T, C, F> where F: FnMut(&T) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { #[inline] pub fn new(set: &'a mut BTreeSet, pred: F) -> Self { DrainFilter { pred, inner: map::DrainFilterInner::new(&mut set.map), } } } impl<'a, T, C: SlabMut>, F> FusedIterator for DrainFilter<'a, T, C, F> where F: FnMut(&T) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { } impl<'a, T, C: SlabMut>, F> Iterator for DrainFilter<'a, T, C, F> where F: FnMut(&T) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { type Item = T; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option { let pred = &mut self.pred; self.inner.next(&mut |t, _| (*pred)(t)).map(|(t, ())| t) } } impl<'a, T, C: SlabMut>, F> Drop for DrainFilter<'a, T, C, F> where F: FnMut(&T) -> bool, C: SimpleCollectionRef, C: SimpleCollectionMut, { fn drop(&mut self) { loop { if self.next().is_none() { break; } } } } pub struct Range<'a, T, C> { inner: map::Range<'a, T, (), C>, } impl<'a, T, C: Slab>> Iterator for Range<'a, T, C> where C: SimpleCollectionRef, { type Item = &'a T; #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn next(&mut self) -> Option<&'a T> { self.inner.next().map(|(k, ())| k) } } impl<'a, T, C: Slab>> DoubleEndedIterator for Range<'a, T, C> where C: SimpleCollectionRef, { #[inline] fn next_back(&mut self) -> Option<&'a T> { self.inner.next_back().map(|(k, ())| k) } } impl<'a, T, C: Slab>> FusedIterator for Range<'a, T, C> where C: SimpleCollectionRef {} btree-slab-0.6.1/src/generic.rs000064400000000000000000000003311046102023000144160ustar 00000000000000//! Generic B-Tree types. //! //! Types defined in this modules are independant of the actual storage type. pub mod node; pub use node::Node; pub mod map; pub use map::BTreeMap; pub mod set; pub use set::BTreeSet; btree-slab-0.6.1/src/lib.rs000064400000000000000000000074261046102023000135640ustar 00000000000000//! This crate provides an alternative implementation to the standard `BTreeMap` //! and `BTreeSet` data structures based on a slab data-structure. In principle, //! this implementation is more flexible and more memory efficient. It is more //! flexible by providing an extended set of low-level operations on B-Trees //! through the `BTreeExt` trait which can be used to further extend the //! functionalities of the `BTreeMap` collection. //! In addition, the underlying node allocation scheme is abstracted by a type //! parameter that can be instantiated by any data structure implementing //! slab-like operations. //! By default, the `Slab` type (from the `slab` crate) is used, which means //! that every node of the tree are allocated in a contiguous memory region, //! reducing the number of allocations needed. //! In theory, another type could be used to store the entire B-Tree on the stack. //! //! ## Usage //! //! From the user point of view, the collection provided by this crate can be //! used just like the standard `BTreeMap` and `BTreeSet` collections. //! ``` //! use btree_slab::BTreeMap; //! //! // type inference lets us omit an explicit type signature (which //! // would be `BTreeMap<&str, &str>` in this example). //! let mut movie_reviews = BTreeMap::new(); //! //! // review some movies. //! movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); //! movie_reviews.insert("Pulp Fiction", "Masterpiece."); //! movie_reviews.insert("The Godfather", "Very enjoyable."); //! movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); //! //! // check for a specific one. //! if !movie_reviews.contains_key("Les Misérables") { //! println!("We've got {} reviews, but Les Misérables ain't one.", //! movie_reviews.len()); //! } //! //! // oops, this review has a lot of spelling mistakes, let's delete it. //! movie_reviews.remove("The Blues Brothers"); //! //! // look up the values associated with some keys. //! let to_find = ["Up!", "Office Space"]; //! for movie in &to_find { //! match movie_reviews.get(movie) { //! Some(review) => println!("{}: {}", movie, review), //! None => println!("{} is unreviewed.", movie) //! } //! } //! //! // Look up the value for a key (will panic if the key is not found). //! println!("Movie review: {}", movie_reviews["Office Space"]); //! //! // iterate over everything. //! for (movie, review) in &movie_reviews { //! println!("{}: \"{}\"", movie, review); //! } //! ``` //! //! ### Custom node allocation //! //! One can use `btree_slab::generic::BTreeMap` to //! use a custom slab type to handle nodes allocation. //! //! ```rust //! use slab::Slab; //! use btree_slab::generic::{Node, BTreeMap}; //! //! # type K = u32; //! # type V = u32; //! let mut map: BTreeMap>> = BTreeMap::new(); //! ``` //! //! In this example, //! the `Slab>` type is a slab-like data structure responsible for the nodes allocation. //! It must implement all the traits defining the `cc_traits::Slab` trait alias. //! //! ## Extended API & Addressing //! //! In this implementation of B-Trees, each node of a tree is addressed //! by the `Address` type. //! The extended API, visible through the `BTreeExt` trait, //! allows the caller to explore, access and modify the //! internal structure of the tree using this addressing system. //! This can be used to further extend the functionalities of the `BTreeMap` //! collection, for example in the //! [`btree-range-map`](https://crates.io/crates/btree-range-map) crate. use slab::Slab; pub mod generic; pub mod utils; /// B-Tree map based on `Slab`. pub type BTreeMap = generic::BTreeMap>>; /// B-Tree set based on `Slab`. pub type BTreeSet = generic::BTreeSet>>; btree-slab-0.6.1/src/utils.rs000064400000000000000000000016241046102023000141500ustar 00000000000000use crate::generic::node::Keyed; use std::borrow::Borrow; /// Search in `sorted_slice` for the item with the nearest key smaller or equal to the given one. /// /// `sorted_slice` is assumed to be sorted. #[inline] pub fn binary_search_min(sorted_slice: &[T], key: &Q) -> Option where T::Key: Borrow, Q: Ord, { if sorted_slice.is_empty() || sorted_slice[0].key().borrow() > key { None } else { let mut i = 0; let mut j = sorted_slice.len() - 1; if sorted_slice[j].key().borrow() <= key { return Some(j); } // invariants: // sorted_slice[i].key <= key // sorted_slice[j].key > key // j > i while j - i > 1 { let k = (i + j) / 2; if sorted_slice[k].key().borrow() > key { j = k; // sorted_slice[k].key > key --> sorted_slice[j] > key } else { i = k; // sorted_slice[k].key <= key --> sorted_slice[i] <= key } } Some(i) } } btree-slab-0.6.1/tests/basic.rs000064400000000000000000000137201046102023000144440ustar 00000000000000use btree_slab::{ generic::{ map::{BTreeExt, BTreeExtMut}, node::Item, }, BTreeMap, }; use rand::{rngs::SmallRng, seq::SliceRandom, SeedableRng}; const SEED: &'static [u8; 32] = b"testseedtestseedtestseedtestseed"; #[test] pub fn insert() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &ITEMS { if let Some(_) = btree.insert(*key, *value) { println!("duplicate: {}", key); } btree.validate(); } assert!(btree.len() == 100); } #[test] pub fn remove() { let mut btree: BTreeMap = BTreeMap::new(); let mut items = ITEMS; for (key, value) in &items { btree.insert(*key, *value); } let mut rng = SmallRng::from_seed(*SEED); items.shuffle(&mut rng); for (key, _) in &items { btree.remove(&key); btree.validate(); } assert!(btree.is_empty()) } #[test] pub fn item_addresses() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &ITEMS { btree.insert(*key, *value); } for (key, _) in &ITEMS { let addr = btree.address_of(key).ok().unwrap(); match btree.previous_item_address(addr) { Some(before_addr) => { assert!(before_addr != addr); let addr_again = btree.next_item_address(before_addr).unwrap(); assert_eq!(addr_again, addr) } None => (), } match btree.next_item_address(addr) { Some(after_addr) => { assert!(after_addr != addr); let addr_again = btree.previous_item_address(after_addr).unwrap(); assert_eq!(addr_again, addr) } None => (), } } } // #[test] // pub fn valid_addresses() { // let mut btree: BTreeMap = BTreeMap::new(); // for (key, value) in &ITEMS { // btree.insert(*key, *value); // } // for (key, _) in &ITEMS { // let addr = btree.address_of(key).ok().unwrap(); // match btree.previous_front_address(addr) { // Some(before_addr) => { // assert!(before_addr != addr); // let addr_again = btree.next_back_address(before_addr).unwrap(); // assert_eq!(addr_again, addr) // }, // None => () // } // let after_addr = btree.next_back_address(addr).unwrap(); // there is always a valid address after an item address. // assert!(after_addr != addr); // let addr_again = btree.previous_front_address(after_addr).unwrap(); // assert_eq!(addr_again, addr) // } // } #[test] pub fn insert_addresses() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &ITEMS { let addr = btree.address_of(key).err().unwrap(); let new_addr = btree.insert_exactly_at(addr, Item::new(*key, *value), None); assert_eq!(btree.item(new_addr).unwrap().value(), value); } } #[test] pub fn remove_addresses() { let items = ITEMS; for k in 1..items.len() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &items { btree.insert(*key, *value); if btree.len() == k { break; } } for (key, value) in &items { match btree.address_of(key) { Ok(addr) => { let (_, addr) = btree.remove_at(addr).unwrap(); btree.insert_at(addr, Item::new(*key, *value)); btree.validate(); } Err(_) => break, } } } } #[test] pub fn update() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &ITEMS { if key % 2 == 0 { btree.insert(*key, *value); } } for (key, value) in &ITEMS { btree.update(*key, |current_value| match current_value { Some(current_value) => { if current_value % 2 == 0 { (None, ()) } else { (Some(10000 - *value), ()) } } None => (Some(*value), ()), }); btree.validate(); } for (key, value) in &ITEMS { let shoud_be_present = *key % 2 == 1 || *value % 2 == 1; match btree.get(key) { Some(current_value) => { if !shoud_be_present { panic!("binding {}:{} should not be present", *key, *value); } if *key % 2 == 0 && *value % 2 == 1 { assert_eq!(*current_value, 10000 - *value) } else { assert_eq!(*current_value, *value) } } None => { if shoud_be_present { panic!("binding {}:{} should be present", *key, *value); } } } } } #[test] pub fn drain_all() { let mut btree: BTreeMap = BTreeMap::new(); for (key, value) in &ITEMS { btree.insert(*key, *value); } let mut drained = btree.drain_filter(|_, _| true).collect::>(); assert!(btree.is_empty()); while let Some((key, value)) = btree.pop_first() { drained.push((key, value)); } assert_eq!(drained.len(), ITEMS.len()); for (key, value) in &ITEMS { assert!(drained.contains(&(*key, *value))); } } const ITEMS: [(usize, usize); 100] = [ (4223, 5948), (8175, 4629), (1411, 7458), (9208, 4040), (1246, 2287), (6568, 7583), (5426, 491), (7850, 8789), (2034, 9388), (1408, 7331), (7346, 5820), (9712, 4253), (5430, 7253), (1662, 5278), (9322, 777), (9256, 8116), (7971, 8071), (648, 3082), (7510, 2207), (8394, 7839), (57, 8834), (7770, 5437), (6388, 6755), (9177, 9904), (6487, 5143), (2231, 688), (7389, 4472), (577, 1930), (9130, 3222), (2230, 8268), (1211, 2354), (9237, 3643), (2912, 8471), (8783, 4977), (4325, 9566), (9355, 528), (9814, 9342), (1641, 6027), (3009, 8304), (4199, 2688), (7011, 9579), (8391, 8562), (1097, 5448), (1224, 5844), (5309, 2846), (7493, 8845), (3682, 48), (9165, 2755), (9959, 7420), (8158, 2616), (3210, 7795), (4418, 7790), (5592, 4184), (4111, 885), (742, 952), (2486, 6088), (6797, 271), (8829, 3005), (6444, 5818), (6566, 8783), (913, 2886), (2325, 1260), (4382, 3045), (5451, 1473), (9376, 8133), (9036, 4924), (5202, 7364), (9190, 5619), (8190, 2892), (9493, 500), (3043, 8315), (9220, 6396), (6400, 5692), (2709, 8547), (1218, 7403), (581, 117), (2577, 9373), (9349, 3186), (9021, 4874), (4207, 1781), (5201, 5305), (7889, 1996), (6327, 6377), (8120, 2338), (8213, 9072), (865, 6524), (5858, 5331), (1904, 3594), (9950, 8859), (518, 6551), (2674, 7081), (9848, 618), (5120, 5595), (259, 9662), (3077, 863), (4519, 7217), (3931, 6743), (2575, 6810), (1553, 5964), (4493, 3677), ]; btree-slab-0.6.1/tests/iter.rs000064400000000000000000000062001046102023000143210ustar 00000000000000use btree_slab::BTreeMap; use std::{cell::Cell, rc::Rc}; #[test] pub fn iter() { let mut map = BTreeMap::new(); for i in 0..10 { map.insert(i, i); } let mut i = 0; for (key, _) in &map { assert_eq!(*key, i); i += 1; } assert_eq!(i, 10) } #[test] pub fn into_iter() { struct Element { /// Drop counter. counter: Rc>, value: i32, } impl Element { pub fn new(counter: &Rc>, value: i32) -> Self { Element { counter: counter.clone(), value, } } pub fn inner(&self) -> i32 { self.value } } impl Drop for Element { fn drop(&mut self) { let c = self.counter.get(); self.counter.set(c + 1); } } let counter = Rc::new(Cell::new(0)); let mut map = BTreeMap::new(); for i in 0..100 { map.insert(i, Element::new(&counter, i)); } for (key, value) in map { assert_eq!(key, value.inner()); } assert_eq!(counter.get(), 100); } #[test] pub fn into_iter_rev() { struct Element { /// Drop counter. counter: Rc>, value: i32, } impl Element { pub fn new(counter: &Rc>, value: i32) -> Self { Element { counter: counter.clone(), value, } } pub fn inner(&self) -> i32 { self.value } } impl Drop for Element { fn drop(&mut self) { let c = self.counter.get(); self.counter.set(c + 1); } } let counter = Rc::new(Cell::new(0)); let mut map = BTreeMap::new(); for i in 0..100 { map.insert(i, Element::new(&counter, i)); } for (key, value) in map.into_iter().rev() { assert_eq!(key, value.inner()); } assert_eq!(counter.get(), 100); } #[test] pub fn into_iter_both_ends1() { struct Element { /// Drop counter. counter: Rc>, value: i32, } impl Element { pub fn new(counter: &Rc>, value: i32) -> Self { Element { counter: counter.clone(), value, } } pub fn inner(&self) -> i32 { self.value } } impl Drop for Element { fn drop(&mut self) { let c = self.counter.get(); self.counter.set(c + 1); } } let counter = Rc::new(Cell::new(0)); let mut map = BTreeMap::new(); for i in 0..100 { map.insert(i, Element::new(&counter, i)); } let mut it = map.into_iter(); while let Some((key, value)) = it.next() { assert_eq!(key, value.inner()); let (key, value) = it.next_back().unwrap(); assert_eq!(key, value.inner()); } assert_eq!(counter.get(), 100); } #[test] pub fn into_iter_both_ends2() { struct Element { /// Drop counter. counter: Rc>, value: i32, } impl Element { pub fn new(counter: &Rc>, value: i32) -> Self { Element { counter: counter.clone(), value, } } pub fn inner(&self) -> i32 { self.value } } impl Drop for Element { fn drop(&mut self) { let c = self.counter.get(); self.counter.set(c + 1); } } let counter = Rc::new(Cell::new(0)); let mut map = BTreeMap::new(); for i in 0..100 { map.insert(i, Element::new(&counter, i)); } let mut it = map.into_iter(); while let Some((key, value)) = it.next_back() { assert_eq!(key, value.inner()); let (key, value) = it.next().unwrap(); assert_eq!(key, value.inner()); } assert_eq!(counter.get(), 100); }