├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .rustfmt.toml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── RELEASES.md ├── benches ├── bench.rs └── faststring.rs ├── src ├── arbitrary.rs ├── borsh.rs ├── lib.rs ├── macros.rs ├── map.rs ├── map │ ├── entry.rs │ ├── iter.rs │ ├── mutable.rs │ ├── raw_entry_v1.rs │ ├── rayon.rs │ ├── serde_seq.rs │ ├── slice.rs │ └── tests.rs ├── serde.rs ├── set.rs └── set │ ├── iter.rs │ ├── mutable.rs │ ├── rayon.rs │ ├── slice.rs │ └── tests.rs ├── test-nostd ├── Cargo.toml └── src │ └── lib.rs ├── test-serde ├── Cargo.toml └── src │ └── lib.rs └── tests ├── equivalent_trait.rs ├── macros_full_path.rs ├── quick.rs └── tests.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [ main ] 4 | pull_request: 5 | branches: [ main ] 6 | merge_group: 7 | 8 | name: CI 9 | 10 | env: 11 | CARGO_TERM_COLOR: always 12 | CARGO_INCREMENTAL: 0 13 | 14 | jobs: 15 | tests: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | include: 20 | - rust: 1.63.0 # MSRV 21 | features: 22 | - rust: stable 23 | features: arbitrary 24 | - rust: stable 25 | features: quickcheck 26 | - rust: stable 27 | features: rayon 28 | - rust: stable 29 | features: serde 30 | - rust: stable 31 | features: borsh 32 | - rust: stable 33 | features: std 34 | - rust: beta 35 | features: 36 | - rust: nightly 37 | bench: test build benchmarks 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | - uses: actions/cache@v4 42 | if: matrix.rust == '1.63.0' 43 | with: 44 | path: ~/.cargo/registry/index 45 | key: cargo-git-index 46 | - name: Lock MSRV-compatible dependencies 47 | if: matrix.rust == '1.63.0' 48 | env: 49 | CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback 50 | # Note that this uses the runner's pre-installed stable cargo 51 | run: cargo generate-lockfile 52 | - uses: dtolnay/rust-toolchain@master 53 | with: 54 | toolchain: ${{ matrix.rust }} 55 | - name: Tests 56 | run: | 57 | cargo build --verbose --features "${{ matrix.features }}" 58 | cargo doc --verbose --features "${{ matrix.features }}" 59 | cargo test --verbose --features "${{ matrix.features }}" 60 | cargo test --release --verbose --features "${{ matrix.features }}" 61 | - name: Tests (serde) 62 | if: matrix.features == 'serde' 63 | run: | 64 | cargo test --verbose -p test-serde 65 | - name: Test run benchmarks 66 | if: matrix.bench != '' 67 | run: cargo test -v --benches 68 | 69 | nostd_build: 70 | runs-on: ubuntu-latest 71 | strategy: 72 | matrix: 73 | include: 74 | - rust: 1.63.0 75 | target: thumbv6m-none-eabi 76 | - rust: stable 77 | target: thumbv6m-none-eabi 78 | 79 | steps: 80 | - uses: actions/checkout@v4 81 | - uses: actions/cache@v4 82 | if: matrix.rust == '1.63.0' 83 | with: 84 | path: ~/.cargo/registry/index 85 | key: cargo-git-index 86 | - name: Lock MSRV-compatible dependencies 87 | if: matrix.rust == '1.63.0' 88 | env: 89 | CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback 90 | # Note that this uses the runner's pre-installed stable cargo 91 | run: cargo generate-lockfile 92 | - uses: dtolnay/rust-toolchain@master 93 | with: 94 | toolchain: ${{ matrix.rust }} 95 | target: ${{ matrix.target }} 96 | - name: Tests 97 | run: | 98 | cargo build -vv --target=${{ matrix.target }} --no-default-features 99 | cargo build -v -p test-nostd --target=${{ matrix.target }} 100 | 101 | clippy: 102 | runs-on: ubuntu-latest 103 | steps: 104 | - uses: actions/checkout@v4 105 | - uses: dtolnay/rust-toolchain@beta 106 | with: 107 | components: clippy 108 | - run: cargo clippy --all-features 109 | 110 | miri: 111 | runs-on: ubuntu-latest 112 | steps: 113 | - uses: actions/checkout@v4 114 | - uses: dtolnay/rust-toolchain@nightly 115 | with: 116 | components: miri, rust-src 117 | - uses: taiki-e/install-action@v2 118 | with: 119 | tool: cargo-nextest 120 | - run: cargo miri nextest run 121 | - run: cargo miri test --doc 122 | 123 | minimal-versions: 124 | name: Check MSRV and minimal-versions 125 | runs-on: ubuntu-latest 126 | steps: 127 | - uses: actions/checkout@v4 128 | - uses: actions/cache@v4 129 | with: 130 | path: ~/.cargo/registry/index 131 | key: cargo-git-index 132 | - uses: dtolnay/rust-toolchain@nightly 133 | - uses: dtolnay/rust-toolchain@1.63.0 # MSRV 134 | - uses: taiki-e/install-action@v2 135 | with: 136 | tool: cargo-hack 137 | - name: Lock minimal direct dependencies 138 | run: cargo +nightly hack generate-lockfile --remove-dev-deps -Z direct-minimal-versions 139 | env: 140 | CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback 141 | - name: Build (nightly) 142 | run: cargo +nightly build --verbose --all-features 143 | - name: Build (MSRV) 144 | run: cargo build --verbose --features arbitrary,quickcheck,serde,rayon 145 | 146 | # One job that "summarizes" the success state of this pipeline. This can then be added to branch 147 | # protection, rather than having to add each job separately. 148 | success: 149 | name: Success 150 | runs-on: ubuntu-latest 151 | needs: [tests, nostd_build, clippy, miri, minimal-versions] 152 | # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency 153 | # failed" as success. So we have to do some contortions to ensure the job fails if any of its 154 | # dependencies fails. 155 | if: always() # make sure this is never "skipped" 156 | steps: 157 | # Manually check the status of all dependencies. `if: failure()` does not work. 158 | - name: check if any dependency failed 159 | run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' 160 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ordermap" 3 | edition = "2021" 4 | version = "0.5.7" 5 | documentation = "https://docs.rs/ordermap/" 6 | repository = "https://github.com/indexmap-rs/ordermap" 7 | license = "Apache-2.0 OR MIT" 8 | description = "A hash table with consistent order and fast iteration." 9 | keywords = ["hashmap", "no_std"] 10 | categories = ["data-structures", "no-std"] 11 | rust-version = "1.63" 12 | 13 | [lib] 14 | bench = false 15 | 16 | [dependencies] 17 | indexmap = { version = "2.9.0", default-features = false } 18 | 19 | arbitrary = { version = "1.0", optional = true, default-features = false } 20 | quickcheck = { version = "1.0", optional = true, default-features = false } 21 | serde = { version = "1.0", optional = true, default-features = false } 22 | borsh = { version = "1.5.6", optional = true, default-features = false } 23 | rayon = { version = "1.9", optional = true } 24 | 25 | [dev-dependencies] 26 | itertools = "0.14" 27 | rand = {version = "0.9", features = ["small_rng"] } 28 | quickcheck = { version = "1.0", default-features = false } 29 | fnv = "1.0" 30 | lazy_static = "1.3" 31 | serde_derive = "1.0" 32 | 33 | [features] 34 | default = ["std"] 35 | std = ["indexmap/std"] 36 | 37 | arbitrary = ["dep:arbitrary", "indexmap/arbitrary"] 38 | quickcheck = ["dep:quickcheck", "indexmap/quickcheck"] 39 | rayon = ["dep:rayon", "indexmap/rayon"] 40 | serde = ["dep:serde", "indexmap/serde"] 41 | borsh = ["dep:borsh", "borsh/indexmap"] 42 | 43 | [profile.bench] 44 | debug = true 45 | 46 | [package.metadata.release] 47 | allow-branch = ["main"] 48 | sign-tag = true 49 | tag-name = "{{version}}" 50 | 51 | [package.metadata.docs.rs] 52 | features = ["arbitrary", "quickcheck", "serde", "borsh", "rayon"] 53 | rustdoc-args = ["--cfg", "docsrs"] 54 | 55 | [workspace] 56 | members = ["test-nostd", "test-serde"] 57 | 58 | [lints.clippy] 59 | style = "allow" 60 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016--2017 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ordermap 2 | 3 | [![build status](https://github.com/indexmap-rs/ordermap/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/indexmap-rs/ordermap/actions) 4 | [![crates.io](https://img.shields.io/crates/v/ordermap.svg)](https://crates.io/crates/ordermap) 5 | [![docs](https://docs.rs/ordermap/badge.svg)](https://docs.rs/ordermap) 6 | [![rustc](https://img.shields.io/badge/rust-1.63%2B-orange.svg)](https://img.shields.io/badge/rust-1.63%2B-orange.svg) 7 | 8 | A pure-Rust hash table which preserves (in a limited sense) insertion order. 9 | 10 | This crate implements compact map and set data-structures, 11 | where the iteration order of the keys is independent from their hash or 12 | value. It preserves insertion order in most mutating operations, and it 13 | allows lookup of entries by either hash table key or numerical index. 14 | 15 | Note: this crate was originally what became the `indexmap` crate, and 16 | it was deprecated for a while in favor of that, but then `ordermap` 17 | returned as a wrapper over `indexmap` with stronger ordering properties. 18 | 19 | # Background 20 | 21 | This was inspired by Python 3.6's new dict implementation (which remembers 22 | the insertion order and is fast to iterate, and is compact in memory). 23 | 24 | Some of those features were translated to Rust, and some were not. The results 25 | were `ordermap` and `indexmap`, hash tables that have following properties: 26 | 27 | - Order is **independent of hash function** and hash values of keys. 28 | - Fast to iterate. 29 | - Indexed in compact space. 30 | - Preserves insertion order **as long** as you don't call `.swap_remove()` 31 | or other methods that explicitly change order. 32 | - In `ordermap`, the regular `.remove()` **does** preserve insertion order, 33 | equivalent to what `indexmap` calls `.shift_remove()`. 34 | - Uses hashbrown for the inner table, just like Rust's libstd `HashMap` does. 35 | 36 | Since its reintroduction in 0.5, `ordermap` has also used its entry order for 37 | `PartialEq` and `Eq`, whereas `indexmap` considers the same entries in *any* order 38 | to be equal for drop-in compatibility with `HashMap` semantics. Using the order 39 | is faster, and also allows `ordermap` to implement `PartialOrd`, `Ord`, and `Hash`. 40 | 41 | ## Performance 42 | 43 | `OrderMap` derives a couple of performance facts directly from how it is constructed, 44 | which is roughly: 45 | 46 | > A raw hash table of key-value indices, and a vector of key-value pairs. 47 | 48 | - As a wrapper, `OrderMap` should maintain the same performance as `IndexMap` 49 | for most operations, with the main difference being the removal strategy. 50 | - Iteration is very fast since it is on the dense key-values. 51 | - Lookup is fast-ish because the initial 7-bit hash lookup uses SIMD, and indices are 52 | densely stored. Lookup also is slow-ish since the actual key-value pairs are stored 53 | separately. (Visible when cpu caches size is limiting.) 54 | - In practice, `OrderMap` has been tested out as the hashmap in rustc in [PR45282] and 55 | the performance was roughly on par across the whole workload. 56 | - If you want the properties of `OrderMap`, or its strongest performance points 57 | fits your workload, it might be the best hash table implementation. 58 | 59 | [PR45282]: https://github.com/rust-lang/rust/pull/45282 60 | 61 | # Recent Changes 62 | 63 | See [RELEASES.md](https://github.com/indexmap-rs/ordermap/blob/main/RELEASES.md). 64 | -------------------------------------------------------------------------------- /RELEASES.md: -------------------------------------------------------------------------------- 1 | # Releases 2 | 3 | ## 0.5.7 (2025-04-04) 4 | 5 | - Added a `get_disjoint_mut` method to `OrderMap`, matching Rust 1.86's 6 | `HashMap` method. 7 | - Added a `get_disjoint_indices_mut` method to `OrderMap`, matching Rust 1.86's 8 | `get_disjoint_mut` method on slices. 9 | - Updated the `indexmap` dependency to version 2.9.0. 10 | 11 | ## 0.5.6 (2025-03-10) 12 | 13 | - Added `ordermap_with_default!` and `orderset_with_default!` to be used with 14 | alternative hashers, especially when using the crate without `std`. 15 | - Updated the `indexmap` dependency to version 2.8.0. 16 | 17 | ## 0.5.5 (2025-01-19) 18 | 19 | - Added `#[track_caller]` to functions that may panic. 20 | - Updated the `indexmap` dependency to version 2.7.1. 21 | 22 | ## 0.5.4 (2024-11-30) 23 | 24 | - Added methods `Entry::insert_entry` and `VacantEntry::insert_entry`, returning 25 | an `OccupiedEntry` after insertion. 26 | - Updated the `indexmap` dependency to version 2.7.0, indirectly updating to 27 | `hashbrown` version 0.15 as well. 28 | 29 | ## 0.5.3 (2024-08-30) 30 | 31 | - Added an `insert_before` method to `OrderMap` and `OrderSet`, as an 32 | alternative to `shift_insert` with different behavior on existing entries. 33 | - Added `first_entry` and `last_entry` methods to `OrderMap`. 34 | - Added `From` implementations between `IndexedEntry` and `OccupiedEntry`. 35 | 36 | ## 0.5.2 (2024-08-13) 37 | 38 | - Added methods `OrderMap::append` and `OrderSet::append`, moving all items from 39 | one map or set into another, and leaving the original capacity for reuse. 40 | 41 | ## 0.5.1 (2024-08-01) 42 | 43 | - Added trait `MutableEntryKey` for opt-in mutable access to map entry keys. 44 | - Added method `MutableKeys::iter_mut2` for opt-in mutable iteration of map 45 | keys and values. 46 | 47 | ## 0.5.0 (2024-06-25) 48 | 49 | - Reinstated `ordermap` as a crate that wraps `indexmap` with stronger 50 | ordering semantics. It **does** consider order for `PartialEq` and `Eq`, 51 | also adding implementations of `PartialOrd`, `Ord`, and `Hash`. Methods 52 | like `remove` use the semantics of indexmap's `shift_remove`. 53 | 54 | ## 0.4.2 (2018-11-17) 55 | 56 | - Inserted more deprecation information in the documentation. 57 | Note: the crate ordermap has been renamed with no change in functionality 58 | to indexmap; please use it under its new name. 59 | 60 | ## 0.4.1 (2018-02-14) 61 | 62 | - Renamed crate to `indexmap`; the `ordermap` crate is now deprecated 63 | and the types `OrderMap/Set` now have a deprecation notice. 64 | 65 | ## 0.4.0 (2018-02-02) 66 | 67 | - This is the last release series for this `ordermap` under that name, 68 | because the crate is **going to be renamed** to `indexmap` (with types 69 | `IndexMap`, `IndexSet`) and no change in functionality! 70 | - The map and its associated structs moved into the `map` submodule of the 71 | crate, so that the map and set are symmetric 72 | 73 | + The iterators, `Entry` and other structs are now under `ordermap::map::` 74 | 75 | - Internally refactored `OrderMap` so that all the main algorithms 76 | (insertion, lookup, removal etc) that don't use the `S` parameter (the 77 | hasher) are compiled without depending on `S`, which reduces generics bloat. 78 | 79 | - `Entry` no longer has a type parameter `S`, which is just like 80 | the standard `HashMap`'s entry. 81 | 82 | - Minimum Rust version requirement increased to Rust 1.18 83 | 84 | ## 0.3.5 (2018-01-14) 85 | 86 | - Documentation improvements 87 | 88 | ## 0.3.4 (2018-01-04) 89 | 90 | - The `.retain()` methods for `OrderMap` and `OrderSet` now 91 | traverse the elements in order, and the retained elements **keep their order** 92 | - Added new methods `.sort_by()`, `.sort_keys()` to `OrderMap` and 93 | `.sort_by()`, `.sort()` to `OrderSet`. These methods allow you to 94 | sort the maps in place efficiently. 95 | 96 | ## 0.3.3 (2017-12-28) 97 | 98 | - Document insertion behaviour better by @lucab 99 | - Updated dependences (no feature changes) by @ignatenkobrain 100 | 101 | ## 0.3.2 (2017-11-25) 102 | 103 | - Add `OrderSet` by @cuviper! 104 | - `OrderMap::drain` is now (too) a double ended iterator. 105 | 106 | ## 0.3.1 (2017-11-19) 107 | 108 | - In all ordermap iterators, forward the `collect` method to the underlying 109 | iterator as well. 110 | - Add crates.io categories. 111 | 112 | ## 0.3.0 (2017-10-07) 113 | 114 | - The methods `get_pair`, `get_pair_index` were both replaced by 115 | `get_full` (and the same for the mutable case). 116 | - Method `swap_remove_pair` replaced by `swap_remove_full`. 117 | - Add trait `MutableKeys` for opt-in mutable key access. Mutable key access 118 | is only possible through the methods of this extension trait. 119 | - Add new trait `Equivalent` for key equivalence. This extends the 120 | `Borrow` trait mechanism for `OrderMap::get` in a backwards compatible 121 | way, just some minor type inference related issues may become apparent. 122 | See [#10] for more information. 123 | - Implement `Extend<(&K, &V)>` by @xfix. 124 | 125 | [#10]: https://github.com/indexmap-rs/indexmap/pull/10 126 | 127 | ## 0.2.13 (2017-09-30) 128 | 129 | - Fix deserialization to support custom hashers by @Techcable. 130 | - Add methods `.index()` on the entry types by @garro95. 131 | 132 | ## 0.2.12 (2017-09-11) 133 | 134 | - Add methods `.with_hasher()`, `.hasher()`. 135 | 136 | ## 0.2.11 (2017-08-29) 137 | 138 | - Support `ExactSizeIterator` for the iterators. By @Binero. 139 | - Use `Box<[Pos]>` internally, saving a word in the `OrderMap` struct. 140 | - Serde support, with crate feature `"serde-1"`. By @xfix. 141 | 142 | ## 0.2.10 (2017-04-29) 143 | 144 | - Add iterator `.drain(..)` by @stevej. 145 | 146 | ## 0.2.9 (2017-03-26) 147 | 148 | - Add method `.is_empty()` by @overvenus. 149 | - Implement `PartialEq, Eq` by @overvenus. 150 | - Add method `.sorted_by()`. 151 | 152 | ## 0.2.8 (2017-03-01) 153 | 154 | - Add iterators `.values()` and `.values_mut()`. 155 | - Fix compatibility with 32-bit platforms. 156 | 157 | ## 0.2.7 (2016-11-02) 158 | 159 | - Add `.retain()`. 160 | 161 | ## 0.2.6 (2016-11-02) 162 | 163 | - Add `OccupiedEntry::remove_entry` and other minor entry methods, 164 | so that it now has all the features of `HashMap`'s entries. 165 | 166 | ## 0.2.5 (2016-10-31) 167 | 168 | - Improved `.pop()` slightly. 169 | 170 | ## 0.2.4 (2016-10-22) 171 | 172 | - Improved performance of `.insert()` ([#3]) by @pczarn. 173 | 174 | [#3]: https://github.com/indexmap-rs/indexmap/pull/3 175 | 176 | ## 0.2.3 (2016-10-11) 177 | 178 | - Generalize `Entry` for now, so that it works on hashmaps with non-default 179 | hasher. However, there's a lingering compat issue since libstd `HashMap` 180 | does not parameterize its entries by the hasher (`S` typarm). 181 | - Special case some iterator methods like `.nth()`. 182 | 183 | ## 0.2.2 (2016-10-02) 184 | 185 | - Disable the verbose `Debug` impl by default. 186 | 187 | ## 0.2.1 (2016-10-02) 188 | 189 | - Fix doc links and clarify docs. 190 | 191 | ## 0.2.0 (2016-10-01) 192 | 193 | - Add more `HashMap` methods & compat with its API. 194 | - Experimental support for `.entry()` (the simplest parts of the API). 195 | - Add `.reserve()` (placeholder impl). 196 | - Add `.remove()` as synonym for `.swap_remove()`. 197 | - Changed `.insert()` to swap value if the entry already exists, and 198 | return `Option`. 199 | - Experimental support as an *indexed* hash map! Added methods 200 | `.get_index()`, `.get_index_mut()`, `.swap_remove_index()`, 201 | `.get_pair_index()`, `.get_pair_index_mut()`. 202 | 203 | ## 0.1.2 (2016-09-19) 204 | 205 | - Implement the 32/32 split idea for `Pos` which improves cache utilization 206 | and lookup performance. 207 | 208 | ## 0.1.1 (2016-09-16) 209 | 210 | - Initial release. 211 | -------------------------------------------------------------------------------- /benches/bench.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | #[macro_use] 5 | extern crate lazy_static; 6 | 7 | use fnv::FnvHasher; 8 | use std::hash::BuildHasherDefault; 9 | use std::hash::Hash; 10 | type FnvBuilder = BuildHasherDefault; 11 | 12 | use test::black_box; 13 | use test::Bencher; 14 | 15 | use ordermap::OrderMap; 16 | 17 | use std::collections::HashMap; 18 | 19 | use rand::rngs::SmallRng; 20 | use rand::seq::SliceRandom; 21 | use rand::SeedableRng; 22 | 23 | /// Use a consistently seeded Rng for benchmark stability 24 | fn small_rng() -> SmallRng { 25 | let seed = u64::from_le_bytes(*b"ordermap"); 26 | SmallRng::seed_from_u64(seed) 27 | } 28 | 29 | #[bench] 30 | fn new_hashmap(b: &mut Bencher) { 31 | b.iter(|| HashMap::::new()); 32 | } 33 | 34 | #[bench] 35 | fn new_ordermap(b: &mut Bencher) { 36 | b.iter(|| OrderMap::::new()); 37 | } 38 | 39 | #[bench] 40 | fn with_capacity_10e5_hashmap(b: &mut Bencher) { 41 | b.iter(|| HashMap::::with_capacity(10_000)); 42 | } 43 | 44 | #[bench] 45 | fn with_capacity_10e5_ordermap(b: &mut Bencher) { 46 | b.iter(|| OrderMap::::with_capacity(10_000)); 47 | } 48 | 49 | #[bench] 50 | fn insert_hashmap_10_000(b: &mut Bencher) { 51 | let c = 10_000; 52 | b.iter(|| { 53 | let mut map = HashMap::with_capacity(c); 54 | for x in 0..c { 55 | map.insert(x, ()); 56 | } 57 | map 58 | }); 59 | } 60 | 61 | #[bench] 62 | fn insert_ordermap_10_000(b: &mut Bencher) { 63 | let c = 10_000; 64 | b.iter(|| { 65 | let mut map = OrderMap::with_capacity(c); 66 | for x in 0..c { 67 | map.insert(x, ()); 68 | } 69 | map 70 | }); 71 | } 72 | 73 | #[bench] 74 | fn insert_hashmap_string_10_000(b: &mut Bencher) { 75 | let c = 10_000; 76 | b.iter(|| { 77 | let mut map = HashMap::with_capacity(c); 78 | for x in 0..c { 79 | map.insert(x.to_string(), ()); 80 | } 81 | map 82 | }); 83 | } 84 | 85 | #[bench] 86 | fn insert_ordermap_string_10_000(b: &mut Bencher) { 87 | let c = 10_000; 88 | b.iter(|| { 89 | let mut map = OrderMap::with_capacity(c); 90 | for x in 0..c { 91 | map.insert(x.to_string(), ()); 92 | } 93 | map 94 | }); 95 | } 96 | 97 | #[bench] 98 | fn insert_hashmap_str_10_000(b: &mut Bencher) { 99 | let c = 10_000; 100 | let ss = Vec::from_iter((0..c).map(|x| x.to_string())); 101 | b.iter(|| { 102 | let mut map = HashMap::with_capacity(c); 103 | for key in &ss { 104 | map.insert(&key[..], ()); 105 | } 106 | map 107 | }); 108 | } 109 | 110 | #[bench] 111 | fn insert_ordermap_str_10_000(b: &mut Bencher) { 112 | let c = 10_000; 113 | let ss = Vec::from_iter((0..c).map(|x| x.to_string())); 114 | b.iter(|| { 115 | let mut map = OrderMap::with_capacity(c); 116 | for key in &ss { 117 | map.insert(&key[..], ()); 118 | } 119 | map 120 | }); 121 | } 122 | 123 | #[bench] 124 | fn insert_hashmap_int_bigvalue_10_000(b: &mut Bencher) { 125 | let c = 10_000; 126 | let value = [0u64; 10]; 127 | b.iter(|| { 128 | let mut map = HashMap::with_capacity(c); 129 | for i in 0..c { 130 | map.insert(i, value); 131 | } 132 | map 133 | }); 134 | } 135 | 136 | #[bench] 137 | fn insert_ordermap_int_bigvalue_10_000(b: &mut Bencher) { 138 | let c = 10_000; 139 | let value = [0u64; 10]; 140 | b.iter(|| { 141 | let mut map = OrderMap::with_capacity(c); 142 | for i in 0..c { 143 | map.insert(i, value); 144 | } 145 | map 146 | }); 147 | } 148 | 149 | #[bench] 150 | fn insert_hashmap_100_000(b: &mut Bencher) { 151 | let c = 100_000; 152 | b.iter(|| { 153 | let mut map = HashMap::with_capacity(c); 154 | for x in 0..c { 155 | map.insert(x, ()); 156 | } 157 | map 158 | }); 159 | } 160 | 161 | #[bench] 162 | fn insert_ordermap_100_000(b: &mut Bencher) { 163 | let c = 100_000; 164 | b.iter(|| { 165 | let mut map = OrderMap::with_capacity(c); 166 | for x in 0..c { 167 | map.insert(x, ()); 168 | } 169 | map 170 | }); 171 | } 172 | 173 | #[bench] 174 | fn insert_hashmap_150(b: &mut Bencher) { 175 | let c = 150; 176 | b.iter(|| { 177 | let mut map = HashMap::with_capacity(c); 178 | for x in 0..c { 179 | map.insert(x, ()); 180 | } 181 | map 182 | }); 183 | } 184 | 185 | #[bench] 186 | fn insert_ordermap_150(b: &mut Bencher) { 187 | let c = 150; 188 | b.iter(|| { 189 | let mut map = OrderMap::with_capacity(c); 190 | for x in 0..c { 191 | map.insert(x, ()); 192 | } 193 | map 194 | }); 195 | } 196 | 197 | #[bench] 198 | fn entry_hashmap_150(b: &mut Bencher) { 199 | let c = 150; 200 | b.iter(|| { 201 | let mut map = HashMap::with_capacity(c); 202 | for x in 0..c { 203 | map.entry(x).or_insert(()); 204 | } 205 | map 206 | }); 207 | } 208 | 209 | #[bench] 210 | fn entry_ordermap_150(b: &mut Bencher) { 211 | let c = 150; 212 | b.iter(|| { 213 | let mut map = OrderMap::with_capacity(c); 214 | for x in 0..c { 215 | map.entry(x).or_insert(()); 216 | } 217 | map 218 | }); 219 | } 220 | 221 | #[bench] 222 | fn iter_sum_hashmap_10_000(b: &mut Bencher) { 223 | let c = 10_000; 224 | let mut map = HashMap::with_capacity(c); 225 | let len = c - c / 10; 226 | for x in 0..len { 227 | map.insert(x, ()); 228 | } 229 | assert_eq!(map.len(), len); 230 | b.iter(|| map.keys().sum::()); 231 | } 232 | 233 | #[bench] 234 | fn iter_sum_ordermap_10_000(b: &mut Bencher) { 235 | let c = 10_000; 236 | let mut map = OrderMap::with_capacity(c); 237 | let len = c - c / 10; 238 | for x in 0..len { 239 | map.insert(x, ()); 240 | } 241 | assert_eq!(map.len(), len); 242 | b.iter(|| map.keys().sum::()); 243 | } 244 | 245 | #[bench] 246 | fn iter_black_box_hashmap_10_000(b: &mut Bencher) { 247 | let c = 10_000; 248 | let mut map = HashMap::with_capacity(c); 249 | let len = c - c / 10; 250 | for x in 0..len { 251 | map.insert(x, ()); 252 | } 253 | assert_eq!(map.len(), len); 254 | b.iter(|| { 255 | for &key in map.keys() { 256 | black_box(key); 257 | } 258 | }); 259 | } 260 | 261 | #[bench] 262 | fn iter_black_box_ordermap_10_000(b: &mut Bencher) { 263 | let c = 10_000; 264 | let mut map = OrderMap::with_capacity(c); 265 | let len = c - c / 10; 266 | for x in 0..len { 267 | map.insert(x, ()); 268 | } 269 | assert_eq!(map.len(), len); 270 | b.iter(|| { 271 | for &key in map.keys() { 272 | black_box(key); 273 | } 274 | }); 275 | } 276 | 277 | fn shuffled_keys(iter: I) -> Vec 278 | where 279 | I: IntoIterator, 280 | { 281 | let mut v = Vec::from_iter(iter); 282 | let mut rng = small_rng(); 283 | v.shuffle(&mut rng); 284 | v 285 | } 286 | 287 | #[bench] 288 | fn lookup_hashmap_10_000_exist(b: &mut Bencher) { 289 | let c = 10_000; 290 | let mut map = HashMap::with_capacity(c); 291 | let keys = shuffled_keys(0..c); 292 | for &key in &keys { 293 | map.insert(key, 1); 294 | } 295 | b.iter(|| { 296 | let mut found = 0; 297 | for key in 5000..c { 298 | found += map.get(&key).is_some() as i32; 299 | } 300 | found 301 | }); 302 | } 303 | 304 | #[bench] 305 | fn lookup_hashmap_10_000_noexist(b: &mut Bencher) { 306 | let c = 10_000; 307 | let mut map = HashMap::with_capacity(c); 308 | let keys = shuffled_keys(0..c); 309 | for &key in &keys { 310 | map.insert(key, 1); 311 | } 312 | b.iter(|| { 313 | let mut found = 0; 314 | for key in c..15000 { 315 | found += map.get(&key).is_some() as i32; 316 | } 317 | found 318 | }); 319 | } 320 | 321 | #[bench] 322 | fn lookup_ordermap_10_000_exist(b: &mut Bencher) { 323 | let c = 10_000; 324 | let mut map = OrderMap::with_capacity(c); 325 | let keys = shuffled_keys(0..c); 326 | for &key in &keys { 327 | map.insert(key, 1); 328 | } 329 | b.iter(|| { 330 | let mut found = 0; 331 | for key in 5000..c { 332 | found += map.get(&key).is_some() as i32; 333 | } 334 | found 335 | }); 336 | } 337 | 338 | #[bench] 339 | fn lookup_ordermap_10_000_noexist(b: &mut Bencher) { 340 | let c = 10_000; 341 | let mut map = OrderMap::with_capacity(c); 342 | let keys = shuffled_keys(0..c); 343 | for &key in &keys { 344 | map.insert(key, 1); 345 | } 346 | b.iter(|| { 347 | let mut found = 0; 348 | for key in c..15000 { 349 | found += map.get(&key).is_some() as i32; 350 | } 351 | found 352 | }); 353 | } 354 | 355 | // number of items to look up 356 | const LOOKUP_MAP_SIZE: u32 = 100_000_u32; 357 | const LOOKUP_SAMPLE_SIZE: u32 = 5000; 358 | const SORT_MAP_SIZE: usize = 10_000; 359 | 360 | // use lazy_static so that comparison benchmarks use the exact same inputs 361 | lazy_static! { 362 | static ref KEYS: Vec = shuffled_keys(0..LOOKUP_MAP_SIZE); 363 | } 364 | 365 | lazy_static! { 366 | static ref HMAP_100K: HashMap = { 367 | let c = LOOKUP_MAP_SIZE; 368 | let mut map = HashMap::with_capacity(c as usize); 369 | let keys = &*KEYS; 370 | for &key in keys { 371 | map.insert(key, key); 372 | } 373 | map 374 | }; 375 | } 376 | 377 | lazy_static! { 378 | static ref IMAP_100K: OrderMap = { 379 | let c = LOOKUP_MAP_SIZE; 380 | let mut map = OrderMap::with_capacity(c as usize); 381 | let keys = &*KEYS; 382 | for &key in keys { 383 | map.insert(key, key); 384 | } 385 | map 386 | }; 387 | } 388 | 389 | lazy_static! { 390 | static ref IMAP_SORT_U32: OrderMap = { 391 | let mut map = OrderMap::with_capacity(SORT_MAP_SIZE); 392 | for &key in &KEYS[..SORT_MAP_SIZE] { 393 | map.insert(key, key); 394 | } 395 | map 396 | }; 397 | } 398 | lazy_static! { 399 | static ref IMAP_SORT_S: OrderMap = { 400 | let mut map = OrderMap::with_capacity(SORT_MAP_SIZE); 401 | for &key in &KEYS[..SORT_MAP_SIZE] { 402 | map.insert(format!("{:^16x}", &key), String::new()); 403 | } 404 | map 405 | }; 406 | } 407 | 408 | #[bench] 409 | fn lookup_hashmap_100_000_multi(b: &mut Bencher) { 410 | let map = &*HMAP_100K; 411 | b.iter(|| { 412 | let mut found = 0; 413 | for key in 0..LOOKUP_SAMPLE_SIZE { 414 | found += map.get(&key).is_some() as u32; 415 | } 416 | found 417 | }); 418 | } 419 | 420 | #[bench] 421 | fn lookup_ordermap_100_000_multi(b: &mut Bencher) { 422 | let map = &*IMAP_100K; 423 | b.iter(|| { 424 | let mut found = 0; 425 | for key in 0..LOOKUP_SAMPLE_SIZE { 426 | found += map.get(&key).is_some() as u32; 427 | } 428 | found 429 | }); 430 | } 431 | 432 | // inorder: Test looking up keys in the same order as they were inserted 433 | #[bench] 434 | fn lookup_hashmap_100_000_inorder_multi(b: &mut Bencher) { 435 | let map = &*HMAP_100K; 436 | let keys = &*KEYS; 437 | b.iter(|| { 438 | let mut found = 0; 439 | for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] { 440 | found += map.get(key).is_some() as u32; 441 | } 442 | found 443 | }); 444 | } 445 | 446 | #[bench] 447 | fn lookup_ordermap_100_000_inorder_multi(b: &mut Bencher) { 448 | let map = &*IMAP_100K; 449 | let keys = &*KEYS; 450 | b.iter(|| { 451 | let mut found = 0; 452 | for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] { 453 | found += map.get(key).is_some() as u32; 454 | } 455 | found 456 | }); 457 | } 458 | 459 | #[bench] 460 | fn lookup_hashmap_100_000_single(b: &mut Bencher) { 461 | let map = &*HMAP_100K; 462 | let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle(); 463 | b.iter(|| { 464 | let key = iter.next().unwrap(); 465 | map.get(&key).is_some() 466 | }); 467 | } 468 | 469 | #[bench] 470 | fn lookup_ordermap_100_000_single(b: &mut Bencher) { 471 | let map = &*IMAP_100K; 472 | let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle(); 473 | b.iter(|| { 474 | let key = iter.next().unwrap(); 475 | map.get(&key).is_some() 476 | }); 477 | } 478 | 479 | const GROW_SIZE: usize = 100_000; 480 | type GrowKey = u32; 481 | 482 | // Test grow/resize without preallocation 483 | #[bench] 484 | fn grow_fnv_hashmap_100_000(b: &mut Bencher) { 485 | b.iter(|| { 486 | let mut map: HashMap<_, _, FnvBuilder> = HashMap::default(); 487 | for x in 0..GROW_SIZE { 488 | map.insert(x as GrowKey, x as GrowKey); 489 | } 490 | map 491 | }); 492 | } 493 | 494 | #[bench] 495 | fn grow_fnv_ordermap_100_000(b: &mut Bencher) { 496 | b.iter(|| { 497 | let mut map: OrderMap<_, _, FnvBuilder> = OrderMap::default(); 498 | for x in 0..GROW_SIZE { 499 | map.insert(x as GrowKey, x as GrowKey); 500 | } 501 | map 502 | }); 503 | } 504 | 505 | const MERGE: u64 = 10_000; 506 | #[bench] 507 | fn hashmap_merge_simple(b: &mut Bencher) { 508 | let first_map: HashMap = (0..MERGE).map(|i| (i, ())).collect(); 509 | let second_map: HashMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); 510 | b.iter(|| { 511 | let mut merged = first_map.clone(); 512 | merged.extend(second_map.iter().map(|(&k, &v)| (k, v))); 513 | merged 514 | }); 515 | } 516 | 517 | #[bench] 518 | fn hashmap_merge_shuffle(b: &mut Bencher) { 519 | let first_map: HashMap = (0..MERGE).map(|i| (i, ())).collect(); 520 | let second_map: HashMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); 521 | let mut v = Vec::new(); 522 | let mut rng = small_rng(); 523 | b.iter(|| { 524 | let mut merged = first_map.clone(); 525 | v.extend(second_map.iter().map(|(&k, &v)| (k, v))); 526 | v.shuffle(&mut rng); 527 | merged.extend(v.drain(..)); 528 | 529 | merged 530 | }); 531 | } 532 | 533 | #[bench] 534 | fn ordermap_merge_simple(b: &mut Bencher) { 535 | let first_map: OrderMap = (0..MERGE).map(|i| (i, ())).collect(); 536 | let second_map: OrderMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); 537 | b.iter(|| { 538 | let mut merged = first_map.clone(); 539 | merged.extend(second_map.iter().map(|(&k, &v)| (k, v))); 540 | merged 541 | }); 542 | } 543 | 544 | #[bench] 545 | fn ordermap_merge_shuffle(b: &mut Bencher) { 546 | let first_map: OrderMap = (0..MERGE).map(|i| (i, ())).collect(); 547 | let second_map: OrderMap = (MERGE..MERGE * 2).map(|i| (i, ())).collect(); 548 | let mut v = Vec::new(); 549 | let mut rng = small_rng(); 550 | b.iter(|| { 551 | let mut merged = first_map.clone(); 552 | v.extend(second_map.iter().map(|(&k, &v)| (k, v))); 553 | v.shuffle(&mut rng); 554 | merged.extend(v.drain(..)); 555 | 556 | merged 557 | }); 558 | } 559 | 560 | #[bench] 561 | fn swap_remove_ordermap_100_000(b: &mut Bencher) { 562 | let map = IMAP_100K.clone(); 563 | let mut keys = Vec::from_iter(map.keys().copied()); 564 | let mut rng = small_rng(); 565 | keys.shuffle(&mut rng); 566 | 567 | b.iter(|| { 568 | let mut map = map.clone(); 569 | for key in &keys { 570 | map.swap_remove(key); 571 | } 572 | assert_eq!(map.len(), 0); 573 | map 574 | }); 575 | } 576 | 577 | #[bench] 578 | fn remove_ordermap_100_000_few(b: &mut Bencher) { 579 | let map = IMAP_100K.clone(); 580 | let mut keys = Vec::from_iter(map.keys().copied()); 581 | let mut rng = small_rng(); 582 | keys.shuffle(&mut rng); 583 | keys.truncate(50); 584 | 585 | b.iter(|| { 586 | let mut map = map.clone(); 587 | for key in &keys { 588 | map.remove(key); 589 | } 590 | assert_eq!(map.len(), IMAP_100K.len() - keys.len()); 591 | map 592 | }); 593 | } 594 | 595 | #[bench] 596 | fn remove_ordermap_2_000_full(b: &mut Bencher) { 597 | let mut keys = KEYS[..2_000].to_vec(); 598 | let mut map = OrderMap::with_capacity(keys.len()); 599 | for &key in &keys { 600 | map.insert(key, key); 601 | } 602 | let mut rng = small_rng(); 603 | keys.shuffle(&mut rng); 604 | 605 | b.iter(|| { 606 | let mut map = map.clone(); 607 | for key in &keys { 608 | map.remove(key); 609 | } 610 | assert_eq!(map.len(), 0); 611 | map 612 | }); 613 | } 614 | 615 | #[bench] 616 | fn pop_ordermap_100_000(b: &mut Bencher) { 617 | let map = IMAP_100K.clone(); 618 | 619 | b.iter(|| { 620 | let mut map = map.clone(); 621 | while !map.is_empty() { 622 | map.pop(); 623 | } 624 | assert_eq!(map.len(), 0); 625 | map 626 | }); 627 | } 628 | 629 | #[bench] 630 | fn few_retain_ordermap_100_000(b: &mut Bencher) { 631 | let map = IMAP_100K.clone(); 632 | 633 | b.iter(|| { 634 | let mut map = map.clone(); 635 | map.retain(|k, _| *k % 7 == 0); 636 | map 637 | }); 638 | } 639 | 640 | #[bench] 641 | fn few_retain_hashmap_100_000(b: &mut Bencher) { 642 | let map = HMAP_100K.clone(); 643 | 644 | b.iter(|| { 645 | let mut map = map.clone(); 646 | map.retain(|k, _| *k % 7 == 0); 647 | map 648 | }); 649 | } 650 | 651 | #[bench] 652 | fn half_retain_ordermap_100_000(b: &mut Bencher) { 653 | let map = IMAP_100K.clone(); 654 | 655 | b.iter(|| { 656 | let mut map = map.clone(); 657 | map.retain(|k, _| *k % 2 == 0); 658 | map 659 | }); 660 | } 661 | 662 | #[bench] 663 | fn half_retain_hashmap_100_000(b: &mut Bencher) { 664 | let map = HMAP_100K.clone(); 665 | 666 | b.iter(|| { 667 | let mut map = map.clone(); 668 | map.retain(|k, _| *k % 2 == 0); 669 | map 670 | }); 671 | } 672 | 673 | #[bench] 674 | fn many_retain_ordermap_100_000(b: &mut Bencher) { 675 | let map = IMAP_100K.clone(); 676 | 677 | b.iter(|| { 678 | let mut map = map.clone(); 679 | map.retain(|k, _| *k % 100 != 0); 680 | map 681 | }); 682 | } 683 | 684 | #[bench] 685 | fn many_retain_hashmap_100_000(b: &mut Bencher) { 686 | let map = HMAP_100K.clone(); 687 | 688 | b.iter(|| { 689 | let mut map = map.clone(); 690 | map.retain(|k, _| *k % 100 != 0); 691 | map 692 | }); 693 | } 694 | 695 | // simple sort impl for comparison 696 | pub fn simple_sort(m: &mut OrderMap) { 697 | let mut ordered: Vec<_> = m.drain(..).collect(); 698 | ordered.sort_by(|left, right| left.0.cmp(&right.0)); 699 | m.extend(ordered); 700 | } 701 | 702 | #[bench] 703 | fn ordermap_sort_s(b: &mut Bencher) { 704 | let map = IMAP_SORT_S.clone(); 705 | 706 | // there's a map clone there, but it's still useful to profile this 707 | b.iter(|| { 708 | let mut map = map.clone(); 709 | map.sort_keys(); 710 | map 711 | }); 712 | } 713 | 714 | #[bench] 715 | fn ordermap_simple_sort_s(b: &mut Bencher) { 716 | let map = IMAP_SORT_S.clone(); 717 | 718 | // there's a map clone there, but it's still useful to profile this 719 | b.iter(|| { 720 | let mut map = map.clone(); 721 | simple_sort(&mut map); 722 | map 723 | }); 724 | } 725 | 726 | #[bench] 727 | fn ordermap_sort_u32(b: &mut Bencher) { 728 | let map = IMAP_SORT_U32.clone(); 729 | 730 | // there's a map clone there, but it's still useful to profile this 731 | b.iter(|| { 732 | let mut map = map.clone(); 733 | map.sort_keys(); 734 | map 735 | }); 736 | } 737 | 738 | #[bench] 739 | fn ordermap_simple_sort_u32(b: &mut Bencher) { 740 | let map = IMAP_SORT_U32.clone(); 741 | 742 | // there's a map clone there, but it's still useful to profile this 743 | b.iter(|| { 744 | let mut map = map.clone(); 745 | simple_sort(&mut map); 746 | map 747 | }); 748 | } 749 | 750 | // measure the fixed overhead of cloning in sort benchmarks 751 | #[bench] 752 | fn ordermap_clone_for_sort_s(b: &mut Bencher) { 753 | let map = IMAP_SORT_S.clone(); 754 | 755 | b.iter(|| map.clone()); 756 | } 757 | 758 | #[bench] 759 | fn ordermap_clone_for_sort_u32(b: &mut Bencher) { 760 | let map = IMAP_SORT_U32.clone(); 761 | 762 | b.iter(|| map.clone()); 763 | } 764 | -------------------------------------------------------------------------------- /benches/faststring.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | 7 | use ordermap::OrderMap; 8 | 9 | use std::collections::HashMap; 10 | 11 | use rand::rngs::SmallRng; 12 | use rand::seq::SliceRandom; 13 | use rand::SeedableRng; 14 | 15 | use std::hash::{Hash, Hasher}; 16 | 17 | use std::borrow::Borrow; 18 | use std::ops::Deref; 19 | 20 | /// Use a consistently seeded Rng for benchmark stability 21 | fn small_rng() -> SmallRng { 22 | let seed = u64::from_le_bytes(*b"ordermap"); 23 | SmallRng::seed_from_u64(seed) 24 | } 25 | 26 | #[derive(PartialEq, Eq, Copy, Clone)] 27 | #[repr(transparent)] 28 | pub struct OneShot(pub T); 29 | 30 | impl Hash for OneShot { 31 | fn hash(&self, h: &mut H) { 32 | h.write(self.0.as_bytes()) 33 | } 34 | } 35 | 36 | impl<'a, S> From<&'a S> for &'a OneShot 37 | where 38 | S: AsRef, 39 | { 40 | fn from(s: &'a S) -> Self { 41 | let s: &str = s.as_ref(); 42 | unsafe { &*(s as *const str as *const OneShot) } 43 | } 44 | } 45 | 46 | impl Hash for OneShot { 47 | fn hash(&self, h: &mut H) { 48 | h.write(self.0.as_bytes()) 49 | } 50 | } 51 | 52 | impl Borrow> for OneShot { 53 | fn borrow(&self) -> &OneShot { 54 | <&OneShot>::from(&self.0) 55 | } 56 | } 57 | 58 | impl Deref for OneShot { 59 | type Target = T; 60 | fn deref(&self) -> &T { 61 | &self.0 62 | } 63 | } 64 | 65 | fn shuffled_keys(iter: I) -> Vec 66 | where 67 | I: IntoIterator, 68 | { 69 | let mut v = Vec::from_iter(iter); 70 | let mut rng = small_rng(); 71 | v.shuffle(&mut rng); 72 | v 73 | } 74 | 75 | #[bench] 76 | fn insert_hashmap_string_10_000(b: &mut Bencher) { 77 | let c = 10_000; 78 | b.iter(|| { 79 | let mut map = HashMap::with_capacity(c); 80 | for x in 0..c { 81 | map.insert(x.to_string(), ()); 82 | } 83 | map 84 | }); 85 | } 86 | 87 | #[bench] 88 | fn insert_hashmap_string_oneshot_10_000(b: &mut Bencher) { 89 | let c = 10_000; 90 | b.iter(|| { 91 | let mut map = HashMap::with_capacity(c); 92 | for x in 0..c { 93 | map.insert(OneShot(x.to_string()), ()); 94 | } 95 | map 96 | }); 97 | } 98 | 99 | #[bench] 100 | fn insert_ordermap_string_10_000(b: &mut Bencher) { 101 | let c = 10_000; 102 | b.iter(|| { 103 | let mut map = OrderMap::with_capacity(c); 104 | for x in 0..c { 105 | map.insert(x.to_string(), ()); 106 | } 107 | map 108 | }); 109 | } 110 | 111 | #[bench] 112 | fn lookup_hashmap_10_000_exist_string(b: &mut Bencher) { 113 | let c = 10_000; 114 | let mut map = HashMap::with_capacity(c); 115 | let keys = shuffled_keys(0..c); 116 | for &key in &keys { 117 | map.insert(key.to_string(), 1); 118 | } 119 | let lookups = (5000..c).map(|x| x.to_string()).collect::>(); 120 | b.iter(|| { 121 | let mut found = 0; 122 | for key in &lookups { 123 | found += map.get(key).is_some() as i32; 124 | } 125 | found 126 | }); 127 | } 128 | 129 | #[bench] 130 | fn lookup_hashmap_10_000_exist_string_oneshot(b: &mut Bencher) { 131 | let c = 10_000; 132 | let mut map = HashMap::with_capacity(c); 133 | let keys = shuffled_keys(0..c); 134 | for &key in &keys { 135 | map.insert(OneShot(key.to_string()), 1); 136 | } 137 | let lookups = (5000..c) 138 | .map(|x| OneShot(x.to_string())) 139 | .collect::>(); 140 | b.iter(|| { 141 | let mut found = 0; 142 | for key in &lookups { 143 | found += map.get(key).is_some() as i32; 144 | } 145 | found 146 | }); 147 | } 148 | 149 | #[bench] 150 | fn lookup_ordermap_10_000_exist_string(b: &mut Bencher) { 151 | let c = 10_000; 152 | let mut map = OrderMap::with_capacity(c); 153 | let keys = shuffled_keys(0..c); 154 | for &key in &keys { 155 | map.insert(key.to_string(), 1); 156 | } 157 | let lookups = (5000..c).map(|x| x.to_string()).collect::>(); 158 | b.iter(|| { 159 | let mut found = 0; 160 | for key in &lookups { 161 | found += map.get(key).is_some() as i32; 162 | } 163 | found 164 | }); 165 | } 166 | 167 | #[bench] 168 | fn lookup_ordermap_10_000_exist_string_oneshot(b: &mut Bencher) { 169 | let c = 10_000; 170 | let mut map = OrderMap::with_capacity(c); 171 | let keys = shuffled_keys(0..c); 172 | for &key in &keys { 173 | map.insert(OneShot(key.to_string()), 1); 174 | } 175 | let lookups = (5000..c) 176 | .map(|x| OneShot(x.to_string())) 177 | .collect::>(); 178 | b.iter(|| { 179 | let mut found = 0; 180 | for key in &lookups { 181 | found += map.get(key).is_some() as i32; 182 | } 183 | found 184 | }); 185 | } 186 | -------------------------------------------------------------------------------- /src/arbitrary.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "arbitrary")] 2 | #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))] 3 | mod impl_arbitrary { 4 | use crate::{OrderMap, OrderSet}; 5 | use arbitrary::{Arbitrary, Result, Unstructured}; 6 | use core::hash::{BuildHasher, Hash}; 7 | use indexmap::{IndexMap, IndexSet}; 8 | 9 | impl<'a, K, V, S> Arbitrary<'a> for OrderMap 10 | where 11 | K: Arbitrary<'a> + Hash + Eq, 12 | V: Arbitrary<'a>, 13 | S: BuildHasher + Default, 14 | { 15 | fn arbitrary(u: &mut Unstructured<'a>) -> Result { 16 | IndexMap::arbitrary(u).map(|inner| Self { inner }) 17 | } 18 | 19 | fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { 20 | IndexMap::arbitrary_take_rest(u).map(|inner| Self { inner }) 21 | } 22 | } 23 | 24 | impl<'a, T, S> Arbitrary<'a> for OrderSet 25 | where 26 | T: Arbitrary<'a> + Hash + Eq, 27 | S: BuildHasher + Default, 28 | { 29 | fn arbitrary(u: &mut Unstructured<'a>) -> Result { 30 | IndexSet::arbitrary(u).map(|inner| Self { inner }) 31 | } 32 | 33 | fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { 34 | IndexSet::arbitrary_take_rest(u).map(|inner| Self { inner }) 35 | } 36 | } 37 | } 38 | 39 | #[cfg(feature = "quickcheck")] 40 | #[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))] 41 | mod impl_quickcheck { 42 | use crate::{OrderMap, OrderSet}; 43 | use alloc::boxed::Box; 44 | use core::hash::{BuildHasher, Hash}; 45 | use indexmap::{IndexMap, IndexSet}; 46 | use quickcheck::{Arbitrary, Gen}; 47 | 48 | impl Arbitrary for OrderMap 49 | where 50 | K: Arbitrary + Hash + Eq, 51 | V: Arbitrary, 52 | S: BuildHasher + Default + Clone + 'static, 53 | { 54 | fn arbitrary(g: &mut Gen) -> Self { 55 | Self { 56 | inner: IndexMap::arbitrary(g), 57 | } 58 | } 59 | 60 | fn shrink(&self) -> Box> { 61 | Box::new(self.inner.shrink().map(|inner| Self { inner })) 62 | } 63 | } 64 | 65 | impl Arbitrary for OrderSet 66 | where 67 | T: Arbitrary + Hash + Eq, 68 | S: BuildHasher + Default + Clone + 'static, 69 | { 70 | fn arbitrary(g: &mut Gen) -> Self { 71 | Self { 72 | inner: IndexSet::arbitrary(g), 73 | } 74 | } 75 | 76 | fn shrink(&self) -> Box> { 77 | Box::new(self.inner.shrink().map(|inner| Self { inner })) 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/borsh.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, doc(cfg(feature = "borsh")))] 2 | 3 | use crate::{OrderMap, OrderSet}; 4 | use borsh::io::{Read, Result, Write}; 5 | use borsh::{BorshDeserialize, BorshSerialize}; 6 | use core::hash::BuildHasher; 7 | use core::hash::Hash; 8 | 9 | impl BorshSerialize for OrderMap 10 | where 11 | K: BorshSerialize, 12 | V: BorshSerialize, 13 | { 14 | #[inline] 15 | fn serialize(&self, writer: &mut W) -> Result<()> { 16 | self.inner.serialize(writer) 17 | } 18 | } 19 | 20 | impl BorshDeserialize for OrderMap 21 | where 22 | K: BorshDeserialize + Eq + Hash, 23 | V: BorshDeserialize, 24 | S: BuildHasher + Default, 25 | { 26 | #[inline] 27 | fn deserialize_reader(reader: &mut R) -> Result { 28 | Ok(Self { 29 | inner: <_>::deserialize_reader(reader)?, 30 | }) 31 | } 32 | } 33 | 34 | impl BorshSerialize for OrderSet 35 | where 36 | T: BorshSerialize, 37 | { 38 | #[inline] 39 | fn serialize(&self, writer: &mut W) -> Result<()> { 40 | self.inner.serialize(writer) 41 | } 42 | } 43 | 44 | impl BorshDeserialize for OrderSet 45 | where 46 | T: BorshDeserialize + Eq + Hash, 47 | S: BuildHasher + Default, 48 | { 49 | #[inline] 50 | fn deserialize_reader(reader: &mut R) -> Result { 51 | Ok(Self { 52 | inner: <_>::deserialize_reader(reader)?, 53 | }) 54 | } 55 | } 56 | 57 | #[cfg(test)] 58 | mod borsh_tests { 59 | use super::*; 60 | 61 | #[test] 62 | fn map_borsh_roundtrip() { 63 | let original_map: OrderMap = { 64 | let mut map = OrderMap::new(); 65 | map.insert(1, 2); 66 | map.insert(3, 4); 67 | map.insert(5, 6); 68 | map 69 | }; 70 | let serialized_map = borsh::to_vec(&original_map).unwrap(); 71 | let deserialized_map: OrderMap = 72 | BorshDeserialize::try_from_slice(&serialized_map).unwrap(); 73 | assert_eq!(original_map, deserialized_map); 74 | } 75 | 76 | #[test] 77 | fn set_borsh_roundtrip() { 78 | let original_map: OrderSet = [1, 2, 3, 4, 5, 6].into_iter().collect(); 79 | let serialized_map = borsh::to_vec(&original_map).unwrap(); 80 | let deserialized_map: OrderSet = 81 | BorshDeserialize::try_from_slice(&serialized_map).unwrap(); 82 | assert_eq!(original_map, deserialized_map); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![forbid(unsafe_code)] 2 | #![warn(rust_2018_idioms)] 3 | #![no_std] 4 | 5 | //! [`OrderMap`] is a hash table where the iteration order of the key-value 6 | //! pairs is independent of the hash values of the keys. 7 | //! 8 | //! [`OrderSet`] is a corresponding hash set using the same implementation and 9 | //! with similar properties. 10 | //! 11 | //! ### Highlights 12 | //! 13 | //! [`OrderMap`] and [`OrderSet`] are drop-in compatible with the std `HashMap` 14 | //! and `HashSet`, but they also have some features of note: 15 | //! 16 | //! - The ordering semantics (see their documentation for details) 17 | //! - Sorting methods and the [`.pop()`][OrderMap::pop] methods. 18 | //! - The [`Equivalent`] trait, which offers more flexible equality definitions 19 | //! between borrowed and owned versions of keys. 20 | //! - The [`MutableKeys`][map::MutableKeys] trait, which gives opt-in mutable 21 | //! access to map keys, and [`MutableValues`][set::MutableValues] for sets. 22 | //! 23 | //! ### Feature Flags 24 | //! 25 | //! To reduce the amount of compiled code in the crate by default, certain 26 | //! features are gated behind [feature flags]. These allow you to opt in to (or 27 | //! out of) functionality. Below is a list of the features available in this 28 | //! crate. 29 | //! 30 | //! * `std`: Enables features which require the Rust standard library. For more 31 | //! information see the section on [`no_std`]. 32 | //! * `rayon`: Enables parallel iteration and other parallel methods. 33 | //! * `serde`: Adds implementations for [`Serialize`] and [`Deserialize`] 34 | //! to [`OrderMap`] and [`OrderSet`]. Alternative implementations for 35 | //! (de)serializing [`OrderMap`] as an ordered sequence are available in the 36 | //! [`map::serde_seq`] module. 37 | //! * `borsh`: Adds implementations for [`BorshSerialize`] and [`BorshDeserialize`] 38 | //! to [`OrderMap`] and [`OrderSet`]. 39 | //! * `arbitrary`: Adds implementations for the [`arbitrary::Arbitrary`] trait 40 | //! to [`OrderMap`] and [`OrderSet`]. 41 | //! * `quickcheck`: Adds implementations for the [`quickcheck::Arbitrary`] trait 42 | //! to [`OrderMap`] and [`OrderSet`]. 43 | //! 44 | //! _Note: only the `std` feature is enabled by default._ 45 | //! 46 | //! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section 47 | //! [`no_std`]: #no-standard-library-targets 48 | //! [`Serialize`]: `::serde::Serialize` 49 | //! [`Deserialize`]: `::serde::Deserialize` 50 | //! [`BorshSerialize`]: `::borsh::BorshSerialize` 51 | //! [`BorshDeserialize`]: `::borsh::BorshDeserialize` 52 | //! [`arbitrary::Arbitrary`]: `::arbitrary::Arbitrary` 53 | //! [`quickcheck::Arbitrary`]: `::quickcheck::Arbitrary` 54 | //! 55 | //! ### Alternate Hashers 56 | //! 57 | //! [`OrderMap`] and [`OrderSet`] have a default hasher type 58 | //! [`S = RandomState`][std::collections::hash_map::RandomState], 59 | //! just like the standard `HashMap` and `HashSet`, which is resistant to 60 | //! HashDoS attacks but not the most performant. Type aliases can make it easier 61 | //! to use alternate hashers: 62 | //! 63 | //! ``` 64 | //! use fnv::FnvBuildHasher; 65 | //! use ordermap::{OrderMap, OrderSet}; 66 | //! 67 | //! type FnvOrderMap = OrderMap; 68 | //! type FnvOrderSet = OrderSet; 69 | //! 70 | //! let std: OrderSet = (0..100).collect(); 71 | //! let fnv: FnvOrderSet = (0..100).collect(); 72 | //! assert_eq!(std, fnv); 73 | //! ``` 74 | //! 75 | //! ### Rust Version 76 | //! 77 | //! This version of ordermap requires Rust 1.63 or later. 78 | //! 79 | //! The ordermap 0.x release series will use a carefully considered version 80 | //! upgrade policy, where in a later 0.x version, we will raise the minimum 81 | //! required Rust version. 82 | //! 83 | //! ## No Standard Library Targets 84 | //! 85 | //! This crate supports being built without `std`, requiring `alloc` instead. 86 | //! This is chosen by disabling the default "std" cargo feature, by adding 87 | //! `default-features = false` to your dependency specification. 88 | //! 89 | //! - Creating maps and sets using [`new`][OrderMap::new] and 90 | //! [`with_capacity`][OrderMap::with_capacity] is unavailable without `std`. 91 | //! Use methods [`OrderMap::default`], [`with_hasher`][OrderMap::with_hasher], 92 | //! [`with_capacity_and_hasher`][OrderMap::with_capacity_and_hasher] instead. 93 | //! A no-std compatible hasher will be needed as well, for example 94 | //! from the crate `twox-hash`. 95 | //! - Macros [`ordermap!`] and [`orderset!`] are unavailable without `std`. Use 96 | //! the macros [`ordermap_with_default!`] and [`orderset_with_default!`] instead. 97 | 98 | #![cfg_attr(docsrs, feature(doc_cfg))] 99 | 100 | extern crate alloc; 101 | 102 | #[cfg(feature = "std")] 103 | #[cfg_attr(test, macro_use)] 104 | extern crate std; 105 | 106 | mod arbitrary; 107 | #[macro_use] 108 | mod macros; 109 | #[cfg(feature = "borsh")] 110 | mod borsh; 111 | #[cfg(feature = "serde")] 112 | mod serde; 113 | 114 | pub mod map; 115 | pub mod set; 116 | 117 | pub use crate::map::OrderMap; 118 | pub use crate::set::OrderSet; 119 | pub use indexmap::{Equivalent, GetDisjointMutError, TryReserveError}; 120 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Create an [`OrderMap`][crate::OrderMap] from a list of key-value pairs 2 | /// and a [`BuildHasherDefault`][core::hash::BuildHasherDefault]-wrapped custom hasher. 3 | /// 4 | /// ## Example 5 | /// 6 | /// ``` 7 | /// use ordermap::ordermap_with_default; 8 | /// use fnv::FnvHasher; 9 | /// 10 | /// let map = ordermap_with_default!{ 11 | /// FnvHasher; 12 | /// "a" => 1, 13 | /// "b" => 2, 14 | /// }; 15 | /// assert_eq!(map["a"], 1); 16 | /// assert_eq!(map["b"], 2); 17 | /// assert_eq!(map.get("c"), None); 18 | /// 19 | /// // "a" is the first key 20 | /// assert_eq!(map.keys().next(), Some(&"a")); 21 | /// ``` 22 | #[macro_export] 23 | macro_rules! ordermap_with_default { 24 | ($H:ty; $($key:expr => $value:expr,)+) => { $crate::ordermap_with_default!($H; $($key => $value),+) }; 25 | ($H:ty; $($key:expr => $value:expr),*) => {{ 26 | let builder = ::core::hash::BuildHasherDefault::<$H>::default(); 27 | const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); 28 | #[allow(unused_mut)] 29 | // Specify your custom `H` (must implement Default + Hasher) as the hasher: 30 | let mut map = $crate::OrderMap::with_capacity_and_hasher(CAP, builder); 31 | $( 32 | map.insert($key, $value); 33 | )* 34 | map 35 | }}; 36 | } 37 | 38 | #[cfg(feature = "std")] 39 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 40 | #[macro_export] 41 | /// Create an [`OrderMap`][crate::OrderMap] from a list of key-value pairs 42 | /// 43 | /// ## Example 44 | /// 45 | /// ``` 46 | /// use ordermap::ordermap; 47 | /// 48 | /// let map = ordermap!{ 49 | /// "a" => 1, 50 | /// "b" => 2, 51 | /// }; 52 | /// assert_eq!(map["a"], 1); 53 | /// assert_eq!(map["b"], 2); 54 | /// assert_eq!(map.get("c"), None); 55 | /// 56 | /// // "a" is the first key 57 | /// assert_eq!(map.keys().next(), Some(&"a")); 58 | /// ``` 59 | macro_rules! ordermap { 60 | ($($key:expr => $value:expr,)+) => { $crate::ordermap!($($key => $value),+) }; 61 | ($($key:expr => $value:expr),*) => { 62 | { 63 | // Note: `stringify!($key)` is just here to consume the repetition, 64 | // but we throw away that string literal during constant evaluation. 65 | const CAP: usize = <[()]>::len(&[$({ stringify!($key); }),*]); 66 | let mut map = $crate::OrderMap::with_capacity(CAP); 67 | $( 68 | map.insert($key, $value); 69 | )* 70 | map 71 | } 72 | }; 73 | } 74 | 75 | /// Create an [`OrderSet`][crate::OrderSet] from a list of values 76 | /// and a [`BuildHasherDefault`][core::hash::BuildHasherDefault]-wrapped custom hasher. 77 | /// 78 | /// ## Example 79 | /// 80 | /// ``` 81 | /// use ordermap::orderset_with_default; 82 | /// use fnv::FnvHasher; 83 | /// 84 | /// let set = orderset_with_default!{ 85 | /// FnvHasher; 86 | /// "a", 87 | /// "b", 88 | /// }; 89 | /// assert!(set.contains("a")); 90 | /// assert!(set.contains("b")); 91 | /// assert!(!set.contains("c")); 92 | /// 93 | /// // "a" is the first value 94 | /// assert_eq!(set.iter().next(), Some(&"a")); 95 | /// ``` 96 | #[macro_export] 97 | macro_rules! orderset_with_default { 98 | ($H:ty; $($value:expr,)+) => { $crate::orderset_with_default!($H; $($value),+) }; 99 | ($H:ty; $($value:expr),*) => {{ 100 | let builder = ::core::hash::BuildHasherDefault::<$H>::default(); 101 | const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); 102 | #[allow(unused_mut)] 103 | // Specify your custom `H` (must implement Default + Hash) as the hasher: 104 | let mut set = $crate::OrderSet::with_capacity_and_hasher(CAP, builder); 105 | $( 106 | set.insert($value); 107 | )* 108 | set 109 | }}; 110 | } 111 | 112 | #[cfg(feature = "std")] 113 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 114 | #[macro_export] 115 | /// Create an [`OrderSet`][crate::OrderSet] from a list of values 116 | /// 117 | /// ## Example 118 | /// 119 | /// ``` 120 | /// use ordermap::orderset; 121 | /// 122 | /// let set = orderset!{ 123 | /// "a", 124 | /// "b", 125 | /// }; 126 | /// assert!(set.contains("a")); 127 | /// assert!(set.contains("b")); 128 | /// assert!(!set.contains("c")); 129 | /// 130 | /// // "a" is the first value 131 | /// assert_eq!(set.iter().next(), Some(&"a")); 132 | /// ``` 133 | macro_rules! orderset { 134 | ($($value:expr,)+) => { $crate::orderset!($($value),+) }; 135 | ($($value:expr),*) => { 136 | { 137 | // Note: `stringify!($value)` is just here to consume the repetition, 138 | // but we throw away that string literal during constant evaluation. 139 | const CAP: usize = <[()]>::len(&[$({ stringify!($value); }),*]); 140 | let mut set = $crate::OrderSet::with_capacity(CAP); 141 | $( 142 | set.insert($value); 143 | )* 144 | set 145 | } 146 | }; 147 | } 148 | -------------------------------------------------------------------------------- /src/map/entry.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use indexmap::map as ix; 3 | 4 | #[cfg(doc)] 5 | use alloc::vec::Vec; 6 | 7 | /// Entry for an existing key-value pair in an [`OrderMap`][crate::OrderMap] 8 | /// or a vacant location to insert one. 9 | pub enum Entry<'a, K, V> { 10 | /// Existing slot with equivalent key. 11 | Occupied(OccupiedEntry<'a, K, V>), 12 | /// Vacant slot (no equivalent key in the map). 13 | Vacant(VacantEntry<'a, K, V>), 14 | } 15 | 16 | impl<'a, K, V> Entry<'a, K, V> { 17 | pub(super) fn new(entry: ix::Entry<'a, K, V>) -> Self { 18 | match entry { 19 | ix::Entry::Occupied(inner) => Self::Occupied(OccupiedEntry { inner }), 20 | ix::Entry::Vacant(inner) => Self::Vacant(VacantEntry { inner }), 21 | } 22 | } 23 | 24 | /// Return the index where the key-value pair exists or will be inserted. 25 | pub fn index(&self) -> usize { 26 | match *self { 27 | Entry::Occupied(ref entry) => entry.index(), 28 | Entry::Vacant(ref entry) => entry.index(), 29 | } 30 | } 31 | 32 | /// Sets the value of the entry (after inserting if vacant), and returns an `OccupiedEntry`. 33 | /// 34 | /// Computes in **O(1)** time (amortized average). 35 | pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { 36 | match self { 37 | Entry::Occupied(mut entry) => { 38 | entry.insert(value); 39 | entry 40 | } 41 | Entry::Vacant(entry) => entry.insert_entry(value), 42 | } 43 | } 44 | 45 | /// Inserts the given default value in the entry if it is vacant and returns a mutable 46 | /// reference to it. Otherwise a mutable reference to an already existent value is returned. 47 | /// 48 | /// Computes in **O(1)** time (amortized average). 49 | pub fn or_insert(self, default: V) -> &'a mut V { 50 | match self { 51 | Entry::Occupied(entry) => entry.into_mut(), 52 | Entry::Vacant(entry) => entry.insert(default), 53 | } 54 | } 55 | 56 | /// Inserts the result of the `call` function in the entry if it is vacant and returns a mutable 57 | /// reference to it. Otherwise a mutable reference to an already existent value is returned. 58 | /// 59 | /// Computes in **O(1)** time (amortized average). 60 | pub fn or_insert_with(self, call: F) -> &'a mut V 61 | where 62 | F: FnOnce() -> V, 63 | { 64 | match self { 65 | Entry::Occupied(entry) => entry.into_mut(), 66 | Entry::Vacant(entry) => entry.insert(call()), 67 | } 68 | } 69 | 70 | /// Inserts the result of the `call` function with a reference to the entry's key if it is 71 | /// vacant, and returns a mutable reference to the new value. Otherwise a mutable reference to 72 | /// an already existent value is returned. 73 | /// 74 | /// Computes in **O(1)** time (amortized average). 75 | pub fn or_insert_with_key(self, call: F) -> &'a mut V 76 | where 77 | F: FnOnce(&K) -> V, 78 | { 79 | match self { 80 | Entry::Occupied(entry) => entry.into_mut(), 81 | Entry::Vacant(entry) => { 82 | let value = call(&entry.key()); 83 | entry.insert(value) 84 | } 85 | } 86 | } 87 | 88 | /// Gets a reference to the entry's key, either within the map if occupied, 89 | /// or else the new key that was used to find the entry. 90 | pub fn key(&self) -> &K { 91 | match *self { 92 | Entry::Occupied(ref entry) => entry.key(), 93 | Entry::Vacant(ref entry) => entry.key(), 94 | } 95 | } 96 | 97 | /// Modifies the entry if it is occupied. 98 | pub fn and_modify(mut self, f: F) -> Self 99 | where 100 | F: FnOnce(&mut V), 101 | { 102 | if let Entry::Occupied(entry) = &mut self { 103 | f(entry.get_mut()); 104 | } 105 | self 106 | } 107 | 108 | /// Inserts a default-constructed value in the entry if it is vacant and returns a mutable 109 | /// reference to it. Otherwise a mutable reference to an already existent value is returned. 110 | /// 111 | /// Computes in **O(1)** time (amortized average). 112 | pub fn or_default(self) -> &'a mut V 113 | where 114 | V: Default, 115 | { 116 | match self { 117 | Entry::Occupied(entry) => entry.into_mut(), 118 | Entry::Vacant(entry) => entry.insert(V::default()), 119 | } 120 | } 121 | } 122 | 123 | impl fmt::Debug for Entry<'_, K, V> { 124 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 125 | let mut tuple = f.debug_tuple("Entry"); 126 | match self { 127 | Entry::Vacant(v) => tuple.field(v), 128 | Entry::Occupied(o) => tuple.field(o), 129 | }; 130 | tuple.finish() 131 | } 132 | } 133 | 134 | /// A view into an occupied entry in an [`OrderMap`][crate::OrderMap]. 135 | /// It is part of the [`Entry`] enum. 136 | pub struct OccupiedEntry<'a, K, V> { 137 | pub(crate) inner: ix::OccupiedEntry<'a, K, V>, 138 | } 139 | 140 | impl<'a, K, V> OccupiedEntry<'a, K, V> { 141 | /// Return the index of the key-value pair 142 | #[inline] 143 | pub fn index(&self) -> usize { 144 | self.inner.index() 145 | } 146 | 147 | /// Gets a reference to the entry's key in the map. 148 | /// 149 | /// Note that this is not the key that was used to find the entry. There may be an observable 150 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like 151 | /// extra fields or the memory address of an allocation. 152 | pub fn key(&self) -> &K { 153 | self.inner.key() 154 | } 155 | 156 | /// Gets a reference to the entry's value in the map. 157 | pub fn get(&self) -> &V { 158 | self.inner.get() 159 | } 160 | 161 | /// Gets a mutable reference to the entry's value in the map. 162 | /// 163 | /// If you need a reference which may outlive the destruction of the 164 | /// [`Entry`] value, see [`into_mut`][Self::into_mut]. 165 | pub fn get_mut(&mut self) -> &mut V { 166 | self.inner.get_mut() 167 | } 168 | 169 | /// Converts into a mutable reference to the entry's value in the map, 170 | /// with a lifetime bound to the map itself. 171 | pub fn into_mut(self) -> &'a mut V { 172 | self.inner.into_mut() 173 | } 174 | 175 | /// Sets the value of the entry to `value`, and returns the entry's old value. 176 | pub fn insert(&mut self, value: V) -> V { 177 | self.inner.insert(value) 178 | } 179 | 180 | /// Remove the key, value pair stored in the map for this entry, and return the value. 181 | /// 182 | /// **NOTE:** This is equivalent to indexmap's 183 | /// [`OccupiedEntry::shift_remove`][ix::OccupiedEntry::shift_remove], and 184 | /// like [`Vec::remove`], the pair is removed by shifting all of the 185 | /// elements that follow it, preserving their relative order. 186 | /// **This perturbs the index of all of those elements!** 187 | /// 188 | /// Computes in **O(n)** time (average). 189 | pub fn remove(self) -> V { 190 | self.inner.shift_remove() 191 | } 192 | 193 | /// Remove and return the key, value pair stored in the map for this entry 194 | /// 195 | /// **NOTE:** This is equivalent to indexmap's 196 | /// [`OccupiedEntry::shift_remove_entry`][ix::OccupiedEntry::shift_remove_entry], and 197 | /// like [`Vec::remove`], the pair is removed by shifting all of the 198 | /// elements that follow it, preserving their relative order. 199 | /// **This perturbs the index of all of those elements!** 200 | /// 201 | /// Computes in **O(n)** time (average). 202 | pub fn remove_entry(self) -> (K, V) { 203 | self.inner.shift_remove_entry() 204 | } 205 | 206 | /// Remove the key, value pair stored in the map for this entry, and return the value. 207 | /// 208 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 209 | /// the last element of the map and popping it off. 210 | /// **This perturbs the position of what used to be the last element!** 211 | /// 212 | /// Computes in **O(1)** time (average). 213 | pub fn swap_remove(self) -> V { 214 | self.inner.swap_remove() 215 | } 216 | 217 | /// Remove and return the key, value pair stored in the map for this entry 218 | /// 219 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 220 | /// the last element of the map and popping it off. 221 | /// **This perturbs the position of what used to be the last element!** 222 | /// 223 | /// Computes in **O(1)** time (average). 224 | pub fn swap_remove_entry(self) -> (K, V) { 225 | self.inner.swap_remove_entry() 226 | } 227 | 228 | /// Moves the position of the entry to a new index 229 | /// by shifting all other entries in-between. 230 | /// 231 | /// This is equivalent to [`OrderMap::move_index`][`crate::OrderMap::move_index`] 232 | /// coming `from` the current [`.index()`][Self::index]. 233 | /// 234 | /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up. 235 | /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down. 236 | /// 237 | /// ***Panics*** if `to` is out of bounds. 238 | /// 239 | /// Computes in **O(n)** time (average). 240 | #[track_caller] 241 | pub fn move_index(self, to: usize) { 242 | self.inner.move_index(to); 243 | } 244 | 245 | /// Swaps the position of entry with another. 246 | /// 247 | /// This is equivalent to [`OrderMap::swap_indices`][`crate::OrderMap::swap_indices`] 248 | /// with the current [`.index()`][Self::index] as one of the two being swapped. 249 | /// 250 | /// ***Panics*** if the `other` index is out of bounds. 251 | /// 252 | /// Computes in **O(1)** time (average). 253 | pub fn swap_indices(self, other: usize) { 254 | self.inner.swap_indices(other); 255 | } 256 | } 257 | 258 | impl fmt::Debug for OccupiedEntry<'_, K, V> { 259 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 260 | f.debug_struct("OccupiedEntry") 261 | .field("key", self.key()) 262 | .field("value", self.get()) 263 | .finish() 264 | } 265 | } 266 | 267 | impl<'a, K, V> From> for OccupiedEntry<'a, K, V> { 268 | fn from(entry: IndexedEntry<'a, K, V>) -> Self { 269 | Self { 270 | inner: entry.inner.into(), 271 | } 272 | } 273 | } 274 | 275 | /// A view into a vacant entry in an [`OrderMap`][crate::OrderMap]. 276 | /// It is part of the [`Entry`] enum. 277 | pub struct VacantEntry<'a, K, V> { 278 | pub(crate) inner: ix::VacantEntry<'a, K, V>, 279 | } 280 | 281 | impl<'a, K, V> VacantEntry<'a, K, V> { 282 | /// Return the index where a key-value pair may be inserted. 283 | pub fn index(&self) -> usize { 284 | self.inner.index() 285 | } 286 | 287 | /// Gets a reference to the key that was used to find the entry. 288 | pub fn key(&self) -> &K { 289 | self.inner.key() 290 | } 291 | 292 | /// Takes ownership of the key, leaving the entry vacant. 293 | pub fn into_key(self) -> K { 294 | self.inner.into_key() 295 | } 296 | 297 | /// Inserts the entry's key and the given value into the map, and returns a mutable reference 298 | /// to the value. 299 | pub fn insert(self, value: V) -> &'a mut V { 300 | self.inner.insert(value) 301 | } 302 | 303 | /// Inserts the entry's key and the given value into the map, and returns an `OccupiedEntry`. 304 | /// 305 | /// Computes in **O(1)** time (amortized average). 306 | pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { 307 | OccupiedEntry { 308 | inner: self.inner.insert_entry(value), 309 | } 310 | } 311 | 312 | /// Inserts the entry's key and the given value into the map at its ordered 313 | /// position among sorted keys, and returns the new index and a mutable 314 | /// reference to the value. 315 | /// 316 | /// If the existing keys are **not** already sorted, then the insertion 317 | /// index is unspecified (like [`slice::binary_search`]), but the key-value 318 | /// pair is inserted at that position regardless. 319 | /// 320 | /// Computes in **O(n)** time (average). 321 | pub fn insert_sorted(self, value: V) -> (usize, &'a mut V) 322 | where 323 | K: Ord, 324 | { 325 | self.inner.insert_sorted(value) 326 | } 327 | 328 | /// Inserts the entry's key and the given value into the map at the given index, 329 | /// shifting others to the right, and returns a mutable reference to the value. 330 | /// 331 | /// ***Panics*** if `index` is out of bounds. 332 | /// 333 | /// Computes in **O(n)** time (average). 334 | pub fn shift_insert(self, index: usize, value: V) -> &'a mut V { 335 | self.inner.shift_insert(index, value) 336 | } 337 | } 338 | 339 | impl fmt::Debug for VacantEntry<'_, K, V> { 340 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 341 | f.debug_tuple("VacantEntry").field(self.key()).finish() 342 | } 343 | } 344 | 345 | /// A view into an occupied entry in an [`OrderMap`][crate::OrderMap] obtained by index. 346 | /// 347 | /// This `struct` is created from the [`get_index_entry`][crate::OrderMap::get_index_entry] method. 348 | pub struct IndexedEntry<'a, K, V> { 349 | pub(crate) inner: ix::IndexedEntry<'a, K, V>, 350 | } 351 | 352 | impl<'a, K, V> IndexedEntry<'a, K, V> { 353 | pub(super) fn new(inner: ix::IndexedEntry<'a, K, V>) -> Self { 354 | Self { inner } 355 | } 356 | 357 | /// Return the index of the key-value pair 358 | #[inline] 359 | pub fn index(&self) -> usize { 360 | self.inner.index() 361 | } 362 | 363 | /// Gets a reference to the entry's key in the map. 364 | pub fn key(&self) -> &K { 365 | self.inner.key() 366 | } 367 | 368 | /// Gets a reference to the entry's value in the map. 369 | pub fn get(&self) -> &V { 370 | self.inner.get() 371 | } 372 | 373 | /// Gets a mutable reference to the entry's value in the map. 374 | /// 375 | /// If you need a reference which may outlive the destruction of the 376 | /// `IndexedEntry` value, see [`into_mut`][Self::into_mut]. 377 | pub fn get_mut(&mut self) -> &mut V { 378 | self.inner.get_mut() 379 | } 380 | 381 | /// Sets the value of the entry to `value`, and returns the entry's old value. 382 | pub fn insert(&mut self, value: V) -> V { 383 | self.inner.insert(value) 384 | } 385 | 386 | /// Converts into a mutable reference to the entry's value in the map, 387 | /// with a lifetime bound to the map itself. 388 | pub fn into_mut(self) -> &'a mut V { 389 | self.inner.into_mut() 390 | } 391 | 392 | /// Remove and return the key, value pair stored in the map for this entry 393 | /// 394 | /// **NOTE:** This is equivalent to indexmap's 395 | /// [`IndexedEntry::shift_remove_entry`][ix::IndexedEntry::shift_remove_entry], and 396 | /// like [`Vec::remove`], the pair is removed by shifting all of the 397 | /// elements that follow it, preserving their relative order. 398 | /// **This perturbs the index of all of those elements!** 399 | /// 400 | /// Computes in **O(n)** time (average). 401 | pub fn remove_entry(self) -> (K, V) { 402 | self.inner.shift_remove_entry() 403 | } 404 | 405 | /// Remove the key, value pair stored in the map for this entry, and return the value. 406 | /// 407 | /// **NOTE:** This is equivalent to indexmap's 408 | /// [`IndexedEntry::shift_remove`][ix::IndexedEntry::shift_remove], and 409 | /// like [`Vec::remove`], the pair is removed by shifting all of the 410 | /// elements that follow it, preserving their relative order. 411 | /// **This perturbs the index of all of those elements!** 412 | /// 413 | /// Computes in **O(n)** time (average). 414 | pub fn remove(self) -> V { 415 | self.inner.shift_remove() 416 | } 417 | 418 | /// Remove and return the key, value pair stored in the map for this entry 419 | /// 420 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 421 | /// the last element of the map and popping it off. 422 | /// **This perturbs the position of what used to be the last element!** 423 | /// 424 | /// Computes in **O(1)** time (average). 425 | pub fn swap_remove_entry(self) -> (K, V) { 426 | self.inner.swap_remove_entry() 427 | } 428 | 429 | /// Remove the key, value pair stored in the map for this entry, and return the value. 430 | /// 431 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 432 | /// the last element of the map and popping it off. 433 | /// **This perturbs the position of what used to be the last element!** 434 | /// 435 | /// Computes in **O(1)** time (average). 436 | pub fn swap_remove(self) -> V { 437 | self.inner.swap_remove() 438 | } 439 | 440 | /// Moves the position of the entry to a new index 441 | /// by shifting all other entries in-between. 442 | /// 443 | /// This is equivalent to [`OrderMap::move_index`][`crate::OrderMap::move_index`] 444 | /// coming `from` the current [`.index()`][Self::index]. 445 | /// 446 | /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up. 447 | /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down. 448 | /// 449 | /// ***Panics*** if `to` is out of bounds. 450 | /// 451 | /// Computes in **O(n)** time (average). 452 | #[track_caller] 453 | pub fn move_index(self, to: usize) { 454 | self.inner.move_index(to) 455 | } 456 | 457 | /// Swaps the position of entry with another. 458 | /// 459 | /// This is equivalent to [`OrderMap::swap_indices`][`crate::OrderMap::swap_indices`] 460 | /// with the current [`.index()`][Self::index] as one of the two being swapped. 461 | /// 462 | /// ***Panics*** if the `other` index is out of bounds. 463 | /// 464 | /// Computes in **O(1)** time (average). 465 | pub fn swap_indices(self, other: usize) { 466 | self.inner.swap_indices(other) 467 | } 468 | } 469 | 470 | impl fmt::Debug for IndexedEntry<'_, K, V> { 471 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 472 | f.debug_struct("IndexedEntry") 473 | .field("index", &self.index()) 474 | .field("key", self.key()) 475 | .field("value", self.get()) 476 | .finish() 477 | } 478 | } 479 | 480 | impl<'a, K, V> From> for IndexedEntry<'a, K, V> { 481 | fn from(entry: OccupiedEntry<'a, K, V>) -> Self { 482 | Self { 483 | inner: entry.inner.into(), 484 | } 485 | } 486 | } 487 | -------------------------------------------------------------------------------- /src/map/iter.rs: -------------------------------------------------------------------------------- 1 | use super::{IntoIter, Iter, IterMut, OrderMap}; 2 | 3 | impl<'a, K, V, S> IntoIterator for &'a OrderMap { 4 | type Item = (&'a K, &'a V); 5 | type IntoIter = Iter<'a, K, V>; 6 | 7 | fn into_iter(self) -> Self::IntoIter { 8 | self.inner.iter() 9 | } 10 | } 11 | 12 | impl<'a, K, V, S> IntoIterator for &'a mut OrderMap { 13 | type Item = (&'a K, &'a mut V); 14 | type IntoIter = IterMut<'a, K, V>; 15 | 16 | fn into_iter(self) -> Self::IntoIter { 17 | self.inner.iter_mut() 18 | } 19 | } 20 | 21 | impl IntoIterator for OrderMap { 22 | type Item = (K, V); 23 | type IntoIter = IntoIter; 24 | 25 | fn into_iter(self) -> Self::IntoIter { 26 | self.inner.into_iter() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/map/mutable.rs: -------------------------------------------------------------------------------- 1 | use super::{Entry, Equivalent, IndexedEntry, IterMut2, OccupiedEntry, OrderMap, VacantEntry}; 2 | use core::hash::{BuildHasher, Hash}; 3 | use indexmap::map::MutableEntryKey as _; 4 | use indexmap::map::MutableKeys as _; 5 | 6 | /// Opt-in mutable access to [`OrderMap`] keys. 7 | /// 8 | /// These methods expose `&mut K`, mutable references to the key as it is stored 9 | /// in the map. 10 | /// You are allowed to modify the keys in the map **if the modification 11 | /// does not change the key’s hash and equality**. 12 | /// 13 | /// If keys are modified erroneously, you can no longer look them up. 14 | /// This is sound (memory safe) but a logical error hazard (just like 15 | /// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be). 16 | /// 17 | /// `use` this trait to enable its methods for `OrderMap`. 18 | /// 19 | /// This trait is sealed and cannot be implemented for types outside this crate. 20 | pub trait MutableKeys: private::Sealed { 21 | type Key; 22 | type Value; 23 | 24 | /// Return item index, mutable reference to key and value 25 | /// 26 | /// Computes in **O(1)** time (average). 27 | fn get_full_mut2(&mut self, key: &Q) -> Option<(usize, &mut Self::Key, &mut Self::Value)> 28 | where 29 | Q: ?Sized + Hash + Equivalent; 30 | 31 | /// Return mutable reference to key and value at an index. 32 | /// 33 | /// Valid indices are `0 <= index < self.len()`. 34 | /// 35 | /// Computes in **O(1)** time. 36 | fn get_index_mut2(&mut self, index: usize) -> Option<(&mut Self::Key, &mut Self::Value)>; 37 | 38 | /// Return an iterator over the key-value pairs of the map, in their order 39 | fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value>; 40 | 41 | /// Scan through each key-value pair in the map and keep those where the 42 | /// closure `keep` returns `true`. 43 | /// 44 | /// The elements are visited in order, and remaining elements keep their 45 | /// order. 46 | /// 47 | /// Computes in **O(n)** time (average). 48 | fn retain2(&mut self, keep: F) 49 | where 50 | F: FnMut(&mut Self::Key, &mut Self::Value) -> bool; 51 | } 52 | 53 | /// Opt-in mutable access to [`OrderMap`] keys. 54 | /// 55 | /// See [`MutableKeys`] for more information. 56 | impl MutableKeys for OrderMap 57 | where 58 | S: BuildHasher, 59 | { 60 | type Key = K; 61 | type Value = V; 62 | 63 | fn get_full_mut2(&mut self, key: &Q) -> Option<(usize, &mut K, &mut V)> 64 | where 65 | Q: ?Sized + Hash + Equivalent, 66 | { 67 | self.inner.get_full_mut2(key) 68 | } 69 | 70 | fn get_index_mut2(&mut self, index: usize) -> Option<(&mut K, &mut V)> { 71 | self.inner.get_index_mut2(index) 72 | } 73 | 74 | fn iter_mut2(&mut self) -> IterMut2<'_, Self::Key, Self::Value> { 75 | self.inner.iter_mut2() 76 | } 77 | 78 | fn retain2(&mut self, keep: F) 79 | where 80 | F: FnMut(&mut K, &mut V) -> bool, 81 | { 82 | self.inner.retain2(keep); 83 | } 84 | } 85 | 86 | /// Opt-in mutable access to [`Entry`] keys. 87 | /// 88 | /// These methods expose `&mut K`, mutable references to the key as it is stored 89 | /// in the map. 90 | /// You are allowed to modify the keys in the map **if the modification 91 | /// does not change the key’s hash and equality**. 92 | /// 93 | /// If keys are modified erroneously, you can no longer look them up. 94 | /// This is sound (memory safe) but a logical error hazard (just like 95 | /// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be). 96 | /// 97 | /// `use` this trait to enable its methods for `Entry`. 98 | /// 99 | /// This trait is sealed and cannot be implemented for types outside this crate. 100 | pub trait MutableEntryKey: private::Sealed { 101 | type Key; 102 | 103 | /// Gets a mutable reference to the entry's key, either within the map if occupied, 104 | /// or else the new key that was used to find the entry. 105 | fn key_mut(&mut self) -> &mut Self::Key; 106 | } 107 | 108 | /// Opt-in mutable access to [`Entry`] keys. 109 | /// 110 | /// See [`MutableEntryKey`] for more information. 111 | impl MutableEntryKey for Entry<'_, K, V> { 112 | type Key = K; 113 | fn key_mut(&mut self) -> &mut Self::Key { 114 | match self { 115 | Entry::Occupied(e) => e.key_mut(), 116 | Entry::Vacant(e) => e.key_mut(), 117 | } 118 | } 119 | } 120 | 121 | /// Opt-in mutable access to [`OccupiedEntry`] keys. 122 | /// 123 | /// See [`MutableEntryKey`] for more information. 124 | impl MutableEntryKey for OccupiedEntry<'_, K, V> { 125 | type Key = K; 126 | fn key_mut(&mut self) -> &mut Self::Key { 127 | self.inner.key_mut() 128 | } 129 | } 130 | 131 | /// Opt-in mutable access to [`VacantEntry`] keys. 132 | /// 133 | /// See [`MutableEntryKey`] for more information. 134 | impl MutableEntryKey for VacantEntry<'_, K, V> { 135 | type Key = K; 136 | fn key_mut(&mut self) -> &mut Self::Key { 137 | self.inner.key_mut() 138 | } 139 | } 140 | 141 | /// Opt-in mutable access to [`IndexedEntry`] keys. 142 | /// 143 | /// See [`MutableEntryKey`] for more information. 144 | impl MutableEntryKey for IndexedEntry<'_, K, V> { 145 | type Key = K; 146 | fn key_mut(&mut self) -> &mut Self::Key { 147 | self.inner.key_mut() 148 | } 149 | } 150 | 151 | mod private { 152 | pub trait Sealed {} 153 | 154 | impl Sealed for super::OrderMap {} 155 | impl Sealed for super::Entry<'_, K, V> {} 156 | impl Sealed for super::OccupiedEntry<'_, K, V> {} 157 | impl Sealed for super::VacantEntry<'_, K, V> {} 158 | impl Sealed for super::IndexedEntry<'_, K, V> {} 159 | } 160 | -------------------------------------------------------------------------------- /src/map/raw_entry_v1.rs: -------------------------------------------------------------------------------- 1 | //! Opt-in access to the experimental raw entry API. 2 | //! 3 | //! This module is designed to mimic the raw entry API of [`HashMap`][std::collections::hash_map], 4 | //! matching its unstable state as of Rust 1.75. See the tracking issue 5 | //! [rust#56167](https://github.com/rust-lang/rust/issues/56167) for more details. 6 | //! 7 | //! The trait [`RawEntryApiV1`] and the `_v1` suffix on its methods are meant to insulate this for 8 | //! the future, in case later breaking changes are needed. If the standard library stabilizes its 9 | //! `hash_raw_entry` feature (or some replacement), matching *inherent* methods will be added to 10 | //! `OrderMap` without such an opt-in trait. 11 | 12 | use crate::{Equivalent, OrderMap}; 13 | use core::fmt; 14 | use core::hash::{BuildHasher, Hash}; 15 | use indexmap::map::raw_entry_v1 as ix; 16 | use indexmap::map::RawEntryApiV1 as _; 17 | 18 | #[cfg(doc)] 19 | use alloc::vec::Vec; 20 | 21 | /// Opt-in access to the experimental raw entry API. 22 | /// 23 | /// See the [`raw_entry_v1`][self] module documentation for more information. 24 | pub trait RawEntryApiV1: private::Sealed { 25 | /// Creates a raw immutable entry builder for the [`OrderMap`]. 26 | /// 27 | /// Raw entries provide the lowest level of control for searching and 28 | /// manipulating a map. They must be manually initialized with a hash and 29 | /// then manually searched. 30 | /// 31 | /// This is useful for 32 | /// * Hash memoization 33 | /// * Using a search key that doesn't work with the [`Equivalent`] trait 34 | /// * Using custom comparison logic without newtype wrappers 35 | /// 36 | /// Unless you are in such a situation, higher-level and more foolproof APIs like 37 | /// [`get`][OrderMap::get] should be preferred. 38 | /// 39 | /// Immutable raw entries have very limited use; you might instead want 40 | /// [`raw_entry_mut_v1`][Self::raw_entry_mut_v1]. 41 | /// 42 | /// # Examples 43 | /// 44 | /// ``` 45 | /// use core::hash::{BuildHasher, Hash}; 46 | /// use ordermap::map::{OrderMap, RawEntryApiV1}; 47 | /// 48 | /// let mut map = OrderMap::new(); 49 | /// map.extend([("a", 100), ("b", 200), ("c", 300)]); 50 | /// 51 | /// fn compute_hash(hash_builder: &S, key: &K) -> u64 { 52 | /// use core::hash::Hasher; 53 | /// let mut state = hash_builder.build_hasher(); 54 | /// key.hash(&mut state); 55 | /// state.finish() 56 | /// } 57 | /// 58 | /// for k in ["a", "b", "c", "d", "e", "f"] { 59 | /// let hash = compute_hash(map.hasher(), k); 60 | /// let i = map.get_index_of(k); 61 | /// let v = map.get(k); 62 | /// let kv = map.get_key_value(k); 63 | /// let ikv = map.get_full(k); 64 | /// 65 | /// println!("Key: {} and value: {:?}", k, v); 66 | /// 67 | /// assert_eq!(map.raw_entry_v1().from_key(k), kv); 68 | /// assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv); 69 | /// assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv); 70 | /// assert_eq!(map.raw_entry_v1().from_hash_full(hash, |q| *q == k), ikv); 71 | /// assert_eq!(map.raw_entry_v1().index_from_hash(hash, |q| *q == k), i); 72 | /// } 73 | /// ``` 74 | fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>; 75 | 76 | /// Creates a raw entry builder for the [`OrderMap`]. 77 | /// 78 | /// Raw entries provide the lowest level of control for searching and 79 | /// manipulating a map. They must be manually initialized with a hash and 80 | /// then manually searched. After this, insertions into a vacant entry 81 | /// still require an owned key to be provided. 82 | /// 83 | /// Raw entries are useful for such exotic situations as: 84 | /// 85 | /// * Hash memoization 86 | /// * Deferring the creation of an owned key until it is known to be required 87 | /// * Using a search key that doesn't work with the [`Equivalent`] trait 88 | /// * Using custom comparison logic without newtype wrappers 89 | /// 90 | /// Because raw entries provide much more low-level control, it's much easier 91 | /// to put the `OrderMap` into an inconsistent state which, while memory-safe, 92 | /// will cause the map to produce seemingly random results. Higher-level and more 93 | /// foolproof APIs like [`entry`][OrderMap::entry] should be preferred when possible. 94 | /// 95 | /// Raw entries give mutable access to the keys. This must not be used 96 | /// to modify how the key would compare or hash, as the map will not re-evaluate 97 | /// where the key should go, meaning the keys may become "lost" if their 98 | /// location does not reflect their state. For instance, if you change a key 99 | /// so that the map now contains keys which compare equal, search may start 100 | /// acting erratically, with two keys randomly masking each other. Implementations 101 | /// are free to assume this doesn't happen (within the limits of memory-safety). 102 | /// 103 | /// # Examples 104 | /// 105 | /// ``` 106 | /// use core::hash::{BuildHasher, Hash}; 107 | /// use ordermap::map::{OrderMap, RawEntryApiV1}; 108 | /// use ordermap::map::raw_entry_v1::RawEntryMut; 109 | /// 110 | /// let mut map = OrderMap::new(); 111 | /// map.extend([("a", 100), ("b", 200), ("c", 300)]); 112 | /// 113 | /// fn compute_hash(hash_builder: &S, key: &K) -> u64 { 114 | /// use core::hash::Hasher; 115 | /// let mut state = hash_builder.build_hasher(); 116 | /// key.hash(&mut state); 117 | /// state.finish() 118 | /// } 119 | /// 120 | /// // Existing key (insert and update) 121 | /// match map.raw_entry_mut_v1().from_key("a") { 122 | /// RawEntryMut::Vacant(_) => unreachable!(), 123 | /// RawEntryMut::Occupied(mut view) => { 124 | /// assert_eq!(view.index(), 0); 125 | /// assert_eq!(view.get(), &100); 126 | /// let v = view.get_mut(); 127 | /// let new_v = (*v) * 10; 128 | /// *v = new_v; 129 | /// assert_eq!(view.insert(1111), 1000); 130 | /// } 131 | /// } 132 | /// 133 | /// assert_eq!(map["a"], 1111); 134 | /// assert_eq!(map.len(), 3); 135 | /// 136 | /// // Existing key (take) 137 | /// let hash = compute_hash(map.hasher(), "c"); 138 | /// match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c") { 139 | /// RawEntryMut::Vacant(_) => unreachable!(), 140 | /// RawEntryMut::Occupied(view) => { 141 | /// assert_eq!(view.index(), 2); 142 | /// assert_eq!(view.remove_entry(), ("c", 300)); 143 | /// } 144 | /// } 145 | /// assert_eq!(map.raw_entry_v1().from_key("c"), None); 146 | /// assert_eq!(map.len(), 2); 147 | /// 148 | /// // Nonexistent key (insert and update) 149 | /// let key = "d"; 150 | /// let hash = compute_hash(map.hasher(), key); 151 | /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) { 152 | /// RawEntryMut::Occupied(_) => unreachable!(), 153 | /// RawEntryMut::Vacant(view) => { 154 | /// assert_eq!(view.index(), 2); 155 | /// let (k, value) = view.insert("d", 4000); 156 | /// assert_eq!((*k, *value), ("d", 4000)); 157 | /// *value = 40000; 158 | /// } 159 | /// } 160 | /// assert_eq!(map["d"], 40000); 161 | /// assert_eq!(map.len(), 3); 162 | /// 163 | /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) { 164 | /// RawEntryMut::Vacant(_) => unreachable!(), 165 | /// RawEntryMut::Occupied(view) => { 166 | /// assert_eq!(view.index(), 2); 167 | /// assert_eq!(view.swap_remove_entry(), ("d", 40000)); 168 | /// } 169 | /// } 170 | /// assert_eq!(map.get("d"), None); 171 | /// assert_eq!(map.len(), 2); 172 | /// ``` 173 | fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S>; 174 | } 175 | 176 | impl RawEntryApiV1 for OrderMap { 177 | fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S> { 178 | RawEntryBuilder { 179 | inner: self.inner.raw_entry_v1(), 180 | } 181 | } 182 | 183 | fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { 184 | RawEntryBuilderMut { 185 | inner: self.inner.raw_entry_mut_v1(), 186 | } 187 | } 188 | } 189 | 190 | /// A builder for computing where in an [`OrderMap`] a key-value pair would be stored. 191 | /// 192 | /// This `struct` is created by the [`OrderMap::raw_entry_v1`] method, provided by the 193 | /// [`RawEntryApiV1`] trait. See its documentation for more. 194 | pub struct RawEntryBuilder<'a, K, V, S> { 195 | inner: ix::RawEntryBuilder<'a, K, V, S>, 196 | } 197 | 198 | impl fmt::Debug for RawEntryBuilder<'_, K, V, S> { 199 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 200 | f.debug_struct("RawEntryBuilder").finish_non_exhaustive() 201 | } 202 | } 203 | 204 | impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> { 205 | /// Access an entry by key. 206 | pub fn from_key(self, key: &Q) -> Option<(&'a K, &'a V)> 207 | where 208 | S: BuildHasher, 209 | Q: ?Sized + Hash + Equivalent, 210 | { 211 | self.inner.from_key(key) 212 | } 213 | 214 | /// Access an entry by a key and its hash. 215 | pub fn from_key_hashed_nocheck(self, hash: u64, key: &Q) -> Option<(&'a K, &'a V)> 216 | where 217 | Q: ?Sized + Equivalent, 218 | { 219 | self.inner.from_key_hashed_nocheck(hash, key) 220 | } 221 | 222 | /// Access an entry by hash. 223 | pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> 224 | where 225 | F: FnMut(&K) -> bool, 226 | { 227 | self.inner.from_hash(hash, is_match) 228 | } 229 | 230 | /// Access an entry by hash, including its index. 231 | pub fn from_hash_full(self, hash: u64, is_match: F) -> Option<(usize, &'a K, &'a V)> 232 | where 233 | F: FnMut(&K) -> bool, 234 | { 235 | self.inner.from_hash_full(hash, is_match) 236 | } 237 | 238 | /// Access the index of an entry by hash. 239 | pub fn index_from_hash(self, hash: u64, is_match: F) -> Option 240 | where 241 | F: FnMut(&K) -> bool, 242 | { 243 | self.inner.index_from_hash(hash, is_match) 244 | } 245 | } 246 | 247 | /// A builder for computing where in an [`OrderMap`] a key-value pair would be stored. 248 | /// 249 | /// This `struct` is created by the [`OrderMap::raw_entry_mut_v1`] method, provided by the 250 | /// [`RawEntryApiV1`] trait. See its documentation for more. 251 | pub struct RawEntryBuilderMut<'a, K, V, S> { 252 | inner: ix::RawEntryBuilderMut<'a, K, V, S>, 253 | } 254 | 255 | impl fmt::Debug for RawEntryBuilderMut<'_, K, V, S> { 256 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 257 | f.debug_struct("RawEntryBuilderMut").finish_non_exhaustive() 258 | } 259 | } 260 | 261 | impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { 262 | /// Access an entry by key. 263 | pub fn from_key(self, key: &Q) -> RawEntryMut<'a, K, V, S> 264 | where 265 | S: BuildHasher, 266 | Q: ?Sized + Hash + Equivalent, 267 | { 268 | RawEntryMut::new(self.inner.from_key(key)) 269 | } 270 | 271 | /// Access an entry by a key and its hash. 272 | pub fn from_key_hashed_nocheck(self, hash: u64, key: &Q) -> RawEntryMut<'a, K, V, S> 273 | where 274 | Q: ?Sized + Equivalent, 275 | { 276 | RawEntryMut::new(self.inner.from_key_hashed_nocheck(hash, key)) 277 | } 278 | 279 | /// Access an entry by hash. 280 | pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> 281 | where 282 | F: FnMut(&K) -> bool, 283 | { 284 | RawEntryMut::new(self.inner.from_hash(hash, is_match)) 285 | } 286 | } 287 | 288 | /// Raw entry for an existing key-value pair or a vacant location to 289 | /// insert one. 290 | pub enum RawEntryMut<'a, K, V, S> { 291 | /// Existing slot with equivalent key. 292 | Occupied(RawOccupiedEntryMut<'a, K, V, S>), 293 | /// Vacant slot (no equivalent key in the map). 294 | Vacant(RawVacantEntryMut<'a, K, V, S>), 295 | } 296 | 297 | impl fmt::Debug for RawEntryMut<'_, K, V, S> { 298 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 299 | let mut tuple = f.debug_tuple("RawEntryMut"); 300 | match self { 301 | Self::Vacant(v) => tuple.field(v), 302 | Self::Occupied(o) => tuple.field(o), 303 | }; 304 | tuple.finish() 305 | } 306 | } 307 | 308 | impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { 309 | fn new(entry: ix::RawEntryMut<'a, K, V, S>) -> Self { 310 | match entry { 311 | ix::RawEntryMut::Occupied(inner) => Self::Occupied(RawOccupiedEntryMut { inner }), 312 | ix::RawEntryMut::Vacant(inner) => Self::Vacant(RawVacantEntryMut { inner }), 313 | } 314 | } 315 | 316 | /// Return the index where the key-value pair exists or may be inserted. 317 | #[inline] 318 | pub fn index(&self) -> usize { 319 | match self { 320 | Self::Occupied(entry) => entry.index(), 321 | Self::Vacant(entry) => entry.index(), 322 | } 323 | } 324 | 325 | /// Inserts the given default key and value in the entry if it is vacant and returns mutable 326 | /// references to them. Otherwise mutable references to an already existent pair are returned. 327 | pub fn or_insert(self, default_key: K, default_value: V) -> (&'a mut K, &'a mut V) 328 | where 329 | K: Hash, 330 | S: BuildHasher, 331 | { 332 | match self { 333 | Self::Occupied(entry) => entry.into_key_value_mut(), 334 | Self::Vacant(entry) => entry.insert(default_key, default_value), 335 | } 336 | } 337 | 338 | /// Inserts the result of the `call` function in the entry if it is vacant and returns mutable 339 | /// references to them. Otherwise mutable references to an already existent pair are returned. 340 | pub fn or_insert_with(self, call: F) -> (&'a mut K, &'a mut V) 341 | where 342 | F: FnOnce() -> (K, V), 343 | K: Hash, 344 | S: BuildHasher, 345 | { 346 | match self { 347 | Self::Occupied(entry) => entry.into_key_value_mut(), 348 | Self::Vacant(entry) => { 349 | let (key, value) = call(); 350 | entry.insert(key, value) 351 | } 352 | } 353 | } 354 | 355 | /// Modifies the entry if it is occupied. 356 | pub fn and_modify(mut self, f: F) -> Self 357 | where 358 | F: FnOnce(&mut K, &mut V), 359 | { 360 | if let Self::Occupied(entry) = &mut self { 361 | let (k, v) = entry.get_key_value_mut(); 362 | f(k, v); 363 | } 364 | self 365 | } 366 | } 367 | 368 | /// A raw view into an occupied entry in an [`OrderMap`]. 369 | /// It is part of the [`RawEntryMut`] enum. 370 | pub struct RawOccupiedEntryMut<'a, K, V, S> { 371 | inner: ix::RawOccupiedEntryMut<'a, K, V, S>, 372 | } 373 | 374 | impl fmt::Debug for RawOccupiedEntryMut<'_, K, V, S> { 375 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 376 | f.debug_struct("RawOccupiedEntryMut") 377 | .field("key", self.key()) 378 | .field("value", self.get()) 379 | .finish_non_exhaustive() 380 | } 381 | } 382 | 383 | impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { 384 | /// Return the index of the key-value pair 385 | #[inline] 386 | pub fn index(&self) -> usize { 387 | self.inner.index() 388 | } 389 | 390 | /// Gets a reference to the entry's key in the map. 391 | /// 392 | /// Note that this is not the key that was used to find the entry. There may be an observable 393 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like 394 | /// extra fields or the memory address of an allocation. 395 | pub fn key(&self) -> &K { 396 | self.inner.key() 397 | } 398 | 399 | /// Gets a mutable reference to the entry's key in the map. 400 | /// 401 | /// Note that this is not the key that was used to find the entry. There may be an observable 402 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like 403 | /// extra fields or the memory address of an allocation. 404 | pub fn key_mut(&mut self) -> &mut K { 405 | self.inner.key_mut() 406 | } 407 | 408 | /// Converts into a mutable reference to the entry's key in the map, 409 | /// with a lifetime bound to the map itself. 410 | /// 411 | /// Note that this is not the key that was used to find the entry. There may be an observable 412 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like 413 | /// extra fields or the memory address of an allocation. 414 | pub fn into_key(self) -> &'a mut K { 415 | self.inner.into_key() 416 | } 417 | 418 | /// Gets a reference to the entry's value in the map. 419 | pub fn get(&self) -> &V { 420 | self.inner.get() 421 | } 422 | 423 | /// Gets a mutable reference to the entry's value in the map. 424 | /// 425 | /// If you need a reference which may outlive the destruction of the 426 | /// [`RawEntryMut`] value, see [`into_mut`][Self::into_mut]. 427 | pub fn get_mut(&mut self) -> &mut V { 428 | self.inner.get_mut() 429 | } 430 | 431 | /// Converts into a mutable reference to the entry's value in the map, 432 | /// with a lifetime bound to the map itself. 433 | pub fn into_mut(self) -> &'a mut V { 434 | self.inner.into_mut() 435 | } 436 | 437 | /// Gets a reference to the entry's key and value in the map. 438 | pub fn get_key_value(&self) -> (&K, &V) { 439 | self.inner.get_key_value() 440 | } 441 | 442 | /// Gets a reference to the entry's key and value in the map. 443 | pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { 444 | self.inner.get_key_value_mut() 445 | } 446 | 447 | /// Converts into a mutable reference to the entry's key and value in the map, 448 | /// with a lifetime bound to the map itself. 449 | pub fn into_key_value_mut(self) -> (&'a mut K, &'a mut V) { 450 | self.inner.into_key_value_mut() 451 | } 452 | 453 | /// Sets the value of the entry, and returns the entry's old value. 454 | pub fn insert(&mut self, value: V) -> V { 455 | self.inner.insert(value) 456 | } 457 | 458 | /// Sets the key of the entry, and returns the entry's old key. 459 | pub fn insert_key(&mut self, key: K) -> K { 460 | self.inner.insert_key(key) 461 | } 462 | 463 | /// Remove the key, value pair stored in the map for this entry, and return the value. 464 | /// 465 | /// **NOTE:** This is equivalent to indexmap's 466 | /// [`RawOccupiedEntryMut::shift_remove`][ix::RawOccupiedEntryMut::shift_remove], and 467 | /// like [`Vec::remove`], the pair is removed by shifting all of the 468 | /// elements that follow it, preserving their relative order. 469 | /// **This perturbs the index of all of those elements!** 470 | /// 471 | /// Computes in **O(n)** time (average). 472 | pub fn remove(self) -> V { 473 | self.inner.shift_remove() 474 | } 475 | 476 | /// Remove the key, value pair stored in the map for this entry, and return the value. 477 | /// 478 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 479 | /// the last element of the map and popping it off. 480 | /// **This perturbs the position of what used to be the last element!** 481 | /// 482 | /// Computes in **O(1)** time (average). 483 | pub fn swap_remove(self) -> V { 484 | self.inner.swap_remove() 485 | } 486 | 487 | /// Remove and return the key, value pair stored in the map for this entry 488 | /// 489 | /// **NOTE:** This is equivalent to indexmap's 490 | /// [`RawOccupiedEntryMut::shift_remove_entry`][ix::RawOccupiedEntryMut::shift_remove_entry], and 491 | /// like [`Vec::remove`], the pair is removed by shifting all of the 492 | /// elements that follow it, preserving their relative order. 493 | /// **This perturbs the index of all of those elements!** 494 | /// 495 | /// Computes in **O(n)** time (average). 496 | pub fn remove_entry(self) -> (K, V) { 497 | self.inner.shift_remove_entry() 498 | } 499 | 500 | /// Remove and return the key, value pair stored in the map for this entry 501 | /// 502 | /// Like [`Vec::swap_remove`], the pair is removed by swapping it with 503 | /// the last element of the map and popping it off. 504 | /// **This perturbs the position of what used to be the last element!** 505 | /// 506 | /// Computes in **O(1)** time (average). 507 | pub fn swap_remove_entry(self) -> (K, V) { 508 | self.inner.swap_remove_entry() 509 | } 510 | 511 | /// Moves the position of the entry to a new index 512 | /// by shifting all other entries in-between. 513 | /// 514 | /// This is equivalent to [`OrderMap::move_index`] 515 | /// coming `from` the current [`.index()`][Self::index]. 516 | /// 517 | /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up. 518 | /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down. 519 | /// 520 | /// ***Panics*** if `to` is out of bounds. 521 | /// 522 | /// Computes in **O(n)** time (average). 523 | pub fn move_index(self, to: usize) { 524 | self.inner.move_index(to); 525 | } 526 | 527 | /// Swaps the position of entry with another. 528 | /// 529 | /// This is equivalent to [`OrderMap::swap_indices`] 530 | /// with the current [`.index()`][Self::index] as one of the two being swapped. 531 | /// 532 | /// ***Panics*** if the `other` index is out of bounds. 533 | /// 534 | /// Computes in **O(1)** time (average). 535 | pub fn swap_indices(self, other: usize) { 536 | self.inner.swap_indices(other); 537 | } 538 | } 539 | 540 | /// A view into a vacant raw entry in an [`OrderMap`]. 541 | /// It is part of the [`RawEntryMut`] enum. 542 | pub struct RawVacantEntryMut<'a, K, V, S> { 543 | inner: ix::RawVacantEntryMut<'a, K, V, S>, 544 | } 545 | 546 | impl fmt::Debug for RawVacantEntryMut<'_, K, V, S> { 547 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 548 | f.debug_struct("RawVacantEntryMut").finish_non_exhaustive() 549 | } 550 | } 551 | 552 | impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { 553 | /// Return the index where a key-value pair may be inserted. 554 | pub fn index(&self) -> usize { 555 | self.inner.index() 556 | } 557 | 558 | /// Inserts the given key and value into the map, 559 | /// and returns mutable references to them. 560 | pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) 561 | where 562 | K: Hash, 563 | S: BuildHasher, 564 | { 565 | self.inner.insert(key, value) 566 | } 567 | 568 | /// Inserts the given key and value into the map with the provided hash, 569 | /// and returns mutable references to them. 570 | pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) { 571 | self.inner.insert_hashed_nocheck(hash, key, value) 572 | } 573 | 574 | /// Inserts the given key and value into the map at the given index, 575 | /// shifting others to the right, and returns mutable references to them. 576 | /// 577 | /// ***Panics*** if `index` is out of bounds. 578 | /// 579 | /// Computes in **O(n)** time (average). 580 | pub fn shift_insert(self, index: usize, key: K, value: V) -> (&'a mut K, &'a mut V) 581 | where 582 | K: Hash, 583 | S: BuildHasher, 584 | { 585 | self.inner.shift_insert(index, key, value) 586 | } 587 | 588 | /// Inserts the given key and value into the map with the provided hash 589 | /// at the given index, and returns mutable references to them. 590 | /// 591 | /// ***Panics*** if `index` is out of bounds. 592 | /// 593 | /// Computes in **O(n)** time (average). 594 | pub fn shift_insert_hashed_nocheck( 595 | self, 596 | index: usize, 597 | hash: u64, 598 | key: K, 599 | value: V, 600 | ) -> (&'a mut K, &'a mut V) { 601 | self.inner 602 | .shift_insert_hashed_nocheck(index, hash, key, value) 603 | } 604 | } 605 | 606 | mod private { 607 | pub trait Sealed {} 608 | 609 | impl Sealed for super::OrderMap {} 610 | } 611 | -------------------------------------------------------------------------------- /src/map/rayon.rs: -------------------------------------------------------------------------------- 1 | //! Parallel iterator types for [`OrderMap`] with [`rayon`]. 2 | //! 3 | //! You will rarely need to interact with this module directly unless you need to name one of the 4 | //! iterator types. 5 | 6 | pub use indexmap::map::rayon::{ 7 | IntoParIter, ParDrain, ParIter, ParIterMut, ParKeys, ParValues, ParValuesMut, 8 | }; 9 | 10 | use super::OrderMap; 11 | use core::cmp::Ordering; 12 | use core::hash::{BuildHasher, Hash}; 13 | use core::ops::RangeBounds; 14 | use rayon::prelude::*; 15 | 16 | impl IntoParallelIterator for OrderMap 17 | where 18 | K: Send, 19 | V: Send, 20 | { 21 | type Item = (K, V); 22 | type Iter = IntoParIter; 23 | 24 | fn into_par_iter(self) -> Self::Iter { 25 | self.inner.into_par_iter() 26 | } 27 | } 28 | 29 | impl<'a, K, V, S> IntoParallelIterator for &'a OrderMap 30 | where 31 | K: Sync, 32 | V: Sync, 33 | { 34 | type Item = (&'a K, &'a V); 35 | type Iter = ParIter<'a, K, V>; 36 | 37 | fn into_par_iter(self) -> Self::Iter { 38 | self.inner.par_iter() 39 | } 40 | } 41 | 42 | impl<'a, K, V, S> IntoParallelIterator for &'a mut OrderMap 43 | where 44 | K: Sync + Send, 45 | V: Send, 46 | { 47 | type Item = (&'a K, &'a mut V); 48 | type Iter = ParIterMut<'a, K, V>; 49 | 50 | fn into_par_iter(self) -> Self::Iter { 51 | self.inner.par_iter_mut() 52 | } 53 | } 54 | 55 | impl<'a, K, V, S> ParallelDrainRange for &'a mut OrderMap 56 | where 57 | K: Send, 58 | V: Send, 59 | { 60 | type Item = (K, V); 61 | type Iter = ParDrain<'a, K, V>; 62 | 63 | fn par_drain>(self, range: R) -> Self::Iter { 64 | self.inner.par_drain(range) 65 | } 66 | } 67 | 68 | /// Parallel iterator methods and other parallel methods. 69 | /// 70 | /// The following methods **require crate feature `"rayon"`**. 71 | /// 72 | /// See also the `IntoParallelIterator` implementations. 73 | impl OrderMap 74 | where 75 | K: Sync, 76 | V: Sync, 77 | { 78 | /// Return a parallel iterator over the keys of the map. 79 | /// 80 | /// While parallel iterators can process items in any order, their relative order 81 | /// in the map is still preserved for operations like `reduce` and `collect`. 82 | pub fn par_keys(&self) -> ParKeys<'_, K, V> { 83 | self.inner.par_keys() 84 | } 85 | 86 | /// Return a parallel iterator over the values of the map. 87 | /// 88 | /// While parallel iterators can process items in any order, their relative order 89 | /// in the map is still preserved for operations like `reduce` and `collect`. 90 | pub fn par_values(&self) -> ParValues<'_, K, V> { 91 | self.inner.par_values() 92 | } 93 | } 94 | 95 | impl OrderMap 96 | where 97 | K: PartialEq + Sync, 98 | V: Sync, 99 | { 100 | /// Returns `true` if `self` contains all of the same key-value pairs as `other`, 101 | /// in the same indexed order, determined in parallel. 102 | pub fn par_eq(&self, other: &OrderMap) -> bool 103 | where 104 | V: PartialEq, 105 | { 106 | self.len() == other.len() && self.par_iter().eq(other) 107 | } 108 | } 109 | 110 | impl OrderMap 111 | where 112 | K: Send, 113 | V: Send, 114 | { 115 | /// Return a parallel iterator over mutable references to the values of the map 116 | /// 117 | /// While parallel iterators can process items in any order, their relative order 118 | /// in the map is still preserved for operations like `reduce` and `collect`. 119 | pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> { 120 | self.inner.par_values_mut() 121 | } 122 | } 123 | 124 | impl OrderMap 125 | where 126 | K: Send, 127 | V: Send, 128 | { 129 | /// Sort the map’s key-value pairs in parallel, by the default ordering of the keys. 130 | pub fn par_sort_keys(&mut self) 131 | where 132 | K: Ord, 133 | { 134 | self.inner.par_sort_keys(); 135 | } 136 | 137 | /// Sort the map’s key-value pairs in place and in parallel, using the comparison 138 | /// function `cmp`. 139 | /// 140 | /// The comparison function receives two key and value pairs to compare (you 141 | /// can sort by keys or values or their combination as needed). 142 | pub fn par_sort_by(&mut self, cmp: F) 143 | where 144 | F: Fn(&K, &V, &K, &V) -> Ordering + Sync, 145 | { 146 | self.inner.par_sort_by(cmp); 147 | } 148 | 149 | /// Sort the key-value pairs of the map in parallel and return a by-value parallel 150 | /// iterator of the key-value pairs with the result. 151 | pub fn par_sorted_by(self, cmp: F) -> IntoParIter 152 | where 153 | F: Fn(&K, &V, &K, &V) -> Ordering + Sync, 154 | { 155 | self.inner.par_sorted_by(cmp) 156 | } 157 | 158 | /// Sort the map's key-value pairs in parallel, by the default ordering of the keys. 159 | pub fn par_sort_unstable_keys(&mut self) 160 | where 161 | K: Ord, 162 | { 163 | self.inner.par_sort_unstable_keys(); 164 | } 165 | 166 | /// Sort the map's key-value pairs in place and in parallel, using the comparison 167 | /// function `cmp`. 168 | /// 169 | /// The comparison function receives two key and value pairs to compare (you 170 | /// can sort by keys or values or their combination as needed). 171 | pub fn par_sort_unstable_by(&mut self, cmp: F) 172 | where 173 | F: Fn(&K, &V, &K, &V) -> Ordering + Sync, 174 | { 175 | self.inner.par_sort_unstable_by(cmp); 176 | } 177 | 178 | /// Sort the key-value pairs of the map in parallel and return a by-value parallel 179 | /// iterator of the key-value pairs with the result. 180 | pub fn par_sorted_unstable_by(self, cmp: F) -> IntoParIter 181 | where 182 | F: Fn(&K, &V, &K, &V) -> Ordering + Sync, 183 | { 184 | self.inner.par_sorted_unstable_by(cmp) 185 | } 186 | 187 | /// Sort the map’s key-value pairs in place and in parallel, using a sort-key extraction 188 | /// function. 189 | pub fn par_sort_by_cached_key(&mut self, sort_key: F) 190 | where 191 | T: Ord + Send, 192 | F: Fn(&K, &V) -> T + Sync, 193 | { 194 | self.inner.par_sort_by_cached_key(sort_key) 195 | } 196 | } 197 | 198 | impl FromParallelIterator<(K, V)> for OrderMap 199 | where 200 | K: Eq + Hash + Send, 201 | V: Send, 202 | S: BuildHasher + Default + Send, 203 | { 204 | fn from_par_iter(iter: I) -> Self 205 | where 206 | I: IntoParallelIterator, 207 | { 208 | Self { 209 | inner: <_>::from_par_iter(iter), 210 | } 211 | } 212 | } 213 | 214 | impl ParallelExtend<(K, V)> for OrderMap 215 | where 216 | K: Eq + Hash + Send, 217 | V: Send, 218 | S: BuildHasher + Send, 219 | { 220 | fn par_extend(&mut self, iter: I) 221 | where 222 | I: IntoParallelIterator, 223 | { 224 | self.inner.par_extend(iter); 225 | } 226 | } 227 | 228 | impl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for OrderMap 229 | where 230 | K: Copy + Eq + Hash + Send + Sync, 231 | V: Copy + Send + Sync, 232 | S: BuildHasher + Send, 233 | { 234 | fn par_extend(&mut self, iter: I) 235 | where 236 | I: IntoParallelIterator, 237 | { 238 | self.inner.par_extend(iter); 239 | } 240 | } 241 | 242 | #[cfg(test)] 243 | mod tests { 244 | use super::*; 245 | use std::vec::Vec; 246 | 247 | #[test] 248 | fn insert_order() { 249 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 250 | let mut map = OrderMap::new(); 251 | 252 | for &elt in &insert { 253 | map.insert(elt, ()); 254 | } 255 | 256 | assert_eq!(map.par_keys().count(), map.len()); 257 | assert_eq!(map.par_keys().count(), insert.len()); 258 | insert.par_iter().zip(map.par_keys()).for_each(|(a, b)| { 259 | assert_eq!(a, b); 260 | }); 261 | (0..insert.len()) 262 | .into_par_iter() 263 | .zip(map.par_keys()) 264 | .for_each(|(i, k)| { 265 | assert_eq!(map.get_index(i).unwrap().0, k); 266 | }); 267 | } 268 | 269 | #[test] 270 | fn partial_eq_and_eq() { 271 | let mut map_a = OrderMap::new(); 272 | map_a.insert(1, "1"); 273 | map_a.insert(2, "2"); 274 | let mut map_b = map_a.clone(); 275 | assert!(map_a.par_eq(&map_b)); 276 | map_b.swap_remove(&1); 277 | assert!(!map_a.par_eq(&map_b)); 278 | map_b.insert(3, "3"); 279 | assert!(!map_a.par_eq(&map_b)); 280 | } 281 | 282 | #[test] 283 | fn extend() { 284 | let mut map = OrderMap::new(); 285 | map.par_extend(vec![(&1, &2), (&3, &4)]); 286 | map.par_extend(vec![(5, 6)]); 287 | assert_eq!( 288 | map.into_par_iter().collect::>(), 289 | vec![(1, 2), (3, 4), (5, 6)] 290 | ); 291 | } 292 | 293 | #[test] 294 | fn keys() { 295 | let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; 296 | let map: OrderMap<_, _> = vec.into_par_iter().collect(); 297 | let keys: Vec<_> = map.par_keys().copied().collect(); 298 | assert_eq!(keys.len(), 3); 299 | assert!(keys.contains(&1)); 300 | assert!(keys.contains(&2)); 301 | assert!(keys.contains(&3)); 302 | } 303 | 304 | #[test] 305 | fn values() { 306 | let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; 307 | let map: OrderMap<_, _> = vec.into_par_iter().collect(); 308 | let values: Vec<_> = map.par_values().copied().collect(); 309 | assert_eq!(values.len(), 3); 310 | assert!(values.contains(&'a')); 311 | assert!(values.contains(&'b')); 312 | assert!(values.contains(&'c')); 313 | } 314 | 315 | #[test] 316 | fn values_mut() { 317 | let vec = vec![(1, 1), (2, 2), (3, 3)]; 318 | let mut map: OrderMap<_, _> = vec.into_par_iter().collect(); 319 | map.par_values_mut().for_each(|value| *value *= 2); 320 | let values: Vec<_> = map.par_values().copied().collect(); 321 | assert_eq!(values.len(), 3); 322 | assert!(values.contains(&2)); 323 | assert!(values.contains(&4)); 324 | assert!(values.contains(&6)); 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /src/map/serde_seq.rs: -------------------------------------------------------------------------------- 1 | //! Functions to serialize and deserialize an [`OrderMap`] as an ordered sequence. 2 | //! 3 | //! The default `serde` implementation serializes `OrderMap` as a normal map, 4 | //! but there is no guarantee that serialization formats will preserve the order 5 | //! of the key-value pairs. This module serializes `OrderMap` as a sequence of 6 | //! `(key, value)` elements instead, in order. 7 | //! 8 | //! This module may be used in a field attribute for derived implementations: 9 | //! 10 | //! ``` 11 | //! # use ordermap::OrderMap; 12 | //! # use serde_derive::{Deserialize, Serialize}; 13 | //! #[derive(Deserialize, Serialize)] 14 | //! struct Data { 15 | //! #[serde(with = "ordermap::map::serde_seq")] 16 | //! map: OrderMap, 17 | //! // ... 18 | //! } 19 | //! ``` 20 | 21 | use crate::OrderMap; 22 | use core::hash::{BuildHasher, Hash}; 23 | use indexmap::map::serde_seq as ix; 24 | use serde::de::{Deserialize, Deserializer}; 25 | use serde::ser::{Serialize, Serializer}; 26 | 27 | /// Serializes an [`OrderMap`] as an ordered sequence. 28 | /// 29 | /// This function may be used in a field attribute for deriving [`Serialize`]: 30 | /// 31 | /// ``` 32 | /// # use ordermap::OrderMap; 33 | /// # use serde_derive::Serialize; 34 | /// #[derive(Serialize)] 35 | /// struct Data { 36 | /// #[serde(serialize_with = "ordermap::map::serde_seq::serialize")] 37 | /// map: OrderMap, 38 | /// // ... 39 | /// } 40 | /// ``` 41 | pub fn serialize(map: &OrderMap, serializer: T) -> Result 42 | where 43 | K: Serialize, 44 | V: Serialize, 45 | T: Serializer, 46 | { 47 | ix::serialize(&map.inner, serializer) 48 | } 49 | 50 | /// Deserializes an [`OrderMap`] from an ordered sequence. 51 | /// 52 | /// This function may be used in a field attribute for deriving [`Deserialize`]: 53 | /// 54 | /// ``` 55 | /// # use ordermap::OrderMap; 56 | /// # use serde_derive::Deserialize; 57 | /// #[derive(Deserialize)] 58 | /// struct Data { 59 | /// #[serde(deserialize_with = "ordermap::map::serde_seq::deserialize")] 60 | /// map: OrderMap, 61 | /// // ... 62 | /// } 63 | /// ``` 64 | pub fn deserialize<'de, D, K, V, S>(deserializer: D) -> Result, D::Error> 65 | where 66 | D: Deserializer<'de>, 67 | K: Deserialize<'de> + Eq + Hash, 68 | V: Deserialize<'de>, 69 | S: Default + BuildHasher, 70 | { 71 | Ok(OrderMap { 72 | inner: ix::deserialize(deserializer)?, 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /src/map/slice.rs: -------------------------------------------------------------------------------- 1 | use super::OrderMap; 2 | use core::ops::{self, Bound, Index, IndexMut}; 3 | use indexmap::map::Slice; 4 | 5 | // We can't have `impl> Index` because that conflicts 6 | // both upstream with `Index` and downstream with `Index<&Q>`. 7 | // Instead, we repeat the implementations for all the core range types. 8 | macro_rules! impl_index { 9 | ($($range:ty),*) => {$( 10 | impl Index<$range> for OrderMap { 11 | type Output = Slice; 12 | 13 | fn index(&self, range: $range) -> &Self::Output { 14 | &self.inner[range] 15 | } 16 | } 17 | 18 | impl IndexMut<$range> for OrderMap { 19 | fn index_mut(&mut self, range: $range) -> &mut Self::Output { 20 | &mut self.inner[range] 21 | } 22 | } 23 | )*} 24 | } 25 | impl_index!( 26 | ops::Range, 27 | ops::RangeFrom, 28 | ops::RangeFull, 29 | ops::RangeInclusive, 30 | ops::RangeTo, 31 | ops::RangeToInclusive, 32 | (Bound, Bound) 33 | ); 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | use alloc::vec::Vec; 39 | 40 | #[test] 41 | fn slice_index() { 42 | fn check( 43 | vec_slice: &[(i32, i32)], 44 | map_slice: &Slice, 45 | sub_slice: &Slice, 46 | ) { 47 | assert_eq!(map_slice as *const _, sub_slice as *const _); 48 | itertools::assert_equal( 49 | vec_slice.iter().copied(), 50 | map_slice.iter().map(|(&k, &v)| (k, v)), 51 | ); 52 | itertools::assert_equal(vec_slice.iter().map(|(k, _)| k), map_slice.keys()); 53 | itertools::assert_equal(vec_slice.iter().map(|(_, v)| v), map_slice.values()); 54 | } 55 | 56 | let vec: Vec<(i32, i32)> = (0..10).map(|i| (i, i * i)).collect(); 57 | let map: OrderMap = vec.iter().cloned().collect(); 58 | let slice = map.as_slice(); 59 | 60 | // RangeFull 61 | check(&vec[..], &map[..], &slice[..]); 62 | 63 | for i in 0usize..10 { 64 | // Index 65 | assert_eq!(vec[i].1, map[i]); 66 | assert_eq!(vec[i].1, slice[i]); 67 | assert_eq!(map[&(i as i32)], map[i]); 68 | assert_eq!(map[&(i as i32)], slice[i]); 69 | 70 | // RangeFrom 71 | check(&vec[i..], &map[i..], &slice[i..]); 72 | 73 | // RangeTo 74 | check(&vec[..i], &map[..i], &slice[..i]); 75 | 76 | // RangeToInclusive 77 | check(&vec[..=i], &map[..=i], &slice[..=i]); 78 | 79 | // (Bound, Bound) 80 | let bounds = (Bound::Excluded(i), Bound::Unbounded); 81 | check(&vec[i + 1..], &map[bounds], &slice[bounds]); 82 | 83 | for j in i..=10 { 84 | // Range 85 | check(&vec[i..j], &map[i..j], &slice[i..j]); 86 | } 87 | 88 | for j in i..10 { 89 | // RangeInclusive 90 | check(&vec[i..=j], &map[i..=j], &slice[i..=j]); 91 | } 92 | } 93 | } 94 | 95 | #[test] 96 | fn slice_index_mut() { 97 | fn check_mut( 98 | vec_slice: &[(i32, i32)], 99 | map_slice: &mut Slice, 100 | sub_slice: &mut Slice, 101 | ) { 102 | assert_eq!(map_slice, sub_slice); 103 | itertools::assert_equal( 104 | vec_slice.iter().copied(), 105 | map_slice.iter_mut().map(|(&k, &mut v)| (k, v)), 106 | ); 107 | itertools::assert_equal( 108 | vec_slice.iter().map(|&(_, v)| v), 109 | map_slice.values_mut().map(|&mut v| v), 110 | ); 111 | } 112 | 113 | let vec: Vec<(i32, i32)> = (0..10).map(|i| (i, i * i)).collect(); 114 | let mut map: OrderMap = vec.iter().cloned().collect(); 115 | let mut map2 = map.clone(); 116 | let slice = map2.as_mut_slice(); 117 | 118 | // RangeFull 119 | check_mut(&vec[..], &mut map[..], &mut slice[..]); 120 | 121 | for i in 0usize..10 { 122 | // IndexMut 123 | assert_eq!(&mut map[i], &mut slice[i]); 124 | 125 | // RangeFrom 126 | check_mut(&vec[i..], &mut map[i..], &mut slice[i..]); 127 | 128 | // RangeTo 129 | check_mut(&vec[..i], &mut map[..i], &mut slice[..i]); 130 | 131 | // RangeToInclusive 132 | check_mut(&vec[..=i], &mut map[..=i], &mut slice[..=i]); 133 | 134 | // (Bound, Bound) 135 | let bounds = (Bound::Excluded(i), Bound::Unbounded); 136 | check_mut(&vec[i + 1..], &mut map[bounds], &mut slice[bounds]); 137 | 138 | for j in i..=10 { 139 | // Range 140 | check_mut(&vec[i..j], &mut map[i..j], &mut slice[i..j]); 141 | } 142 | 143 | for j in i..10 { 144 | // RangeInclusive 145 | check_mut(&vec[i..=j], &mut map[i..=j], &mut slice[i..=j]); 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, doc(cfg(feature = "serde")))] 2 | 3 | use crate::{OrderMap, OrderSet}; 4 | use core::hash::{BuildHasher, Hash}; 5 | use serde::de::value::{MapDeserializer, SeqDeserializer}; 6 | use serde::de::{Deserialize, Deserializer, Error, IntoDeserializer}; 7 | use serde::ser::{Serialize, Serializer}; 8 | 9 | impl Serialize for OrderMap 10 | where 11 | K: Serialize, 12 | V: Serialize, 13 | { 14 | fn serialize(&self, serializer: T) -> Result 15 | where 16 | T: Serializer, 17 | { 18 | self.inner.serialize(serializer) 19 | } 20 | } 21 | 22 | impl<'de, K, V, S> Deserialize<'de> for OrderMap 23 | where 24 | K: Deserialize<'de> + Eq + Hash, 25 | V: Deserialize<'de>, 26 | S: Default + BuildHasher, 27 | { 28 | fn deserialize(deserializer: D) -> Result 29 | where 30 | D: Deserializer<'de>, 31 | { 32 | Ok(Self { 33 | inner: <_>::deserialize(deserializer)?, 34 | }) 35 | } 36 | } 37 | 38 | impl<'de, K, V, S, E> IntoDeserializer<'de, E> for OrderMap 39 | where 40 | K: IntoDeserializer<'de, E> + Eq + Hash, 41 | V: IntoDeserializer<'de, E>, 42 | S: BuildHasher, 43 | E: Error, 44 | { 45 | type Deserializer = MapDeserializer<'de, ::IntoIter, E>; 46 | 47 | fn into_deserializer(self) -> Self::Deserializer { 48 | self.inner.into_deserializer() 49 | } 50 | } 51 | 52 | impl Serialize for OrderSet 53 | where 54 | T: Serialize, 55 | { 56 | fn serialize(&self, serializer: Se) -> Result 57 | where 58 | Se: Serializer, 59 | { 60 | self.inner.serialize(serializer) 61 | } 62 | } 63 | 64 | impl<'de, T, S> Deserialize<'de> for OrderSet 65 | where 66 | T: Deserialize<'de> + Eq + Hash, 67 | S: Default + BuildHasher, 68 | { 69 | fn deserialize(deserializer: D) -> Result 70 | where 71 | D: Deserializer<'de>, 72 | { 73 | Ok(Self { 74 | inner: <_>::deserialize(deserializer)?, 75 | }) 76 | } 77 | } 78 | 79 | impl<'de, T, S, E> IntoDeserializer<'de, E> for OrderSet 80 | where 81 | T: IntoDeserializer<'de, E> + Eq + Hash, 82 | S: BuildHasher, 83 | E: Error, 84 | { 85 | type Deserializer = SeqDeserializer<::IntoIter, E>; 86 | 87 | fn into_deserializer(self) -> Self::Deserializer { 88 | self.inner.into_deserializer() 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/set/iter.rs: -------------------------------------------------------------------------------- 1 | use super::OrderSet; 2 | use indexmap::set::{IntoIter, Iter}; 3 | 4 | impl<'a, T, S> IntoIterator for &'a OrderSet { 5 | type Item = &'a T; 6 | type IntoIter = Iter<'a, T>; 7 | 8 | fn into_iter(self) -> Self::IntoIter { 9 | self.inner.iter() 10 | } 11 | } 12 | 13 | impl IntoIterator for OrderSet { 14 | type Item = T; 15 | type IntoIter = IntoIter; 16 | 17 | fn into_iter(self) -> Self::IntoIter { 18 | self.inner.into_iter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/set/mutable.rs: -------------------------------------------------------------------------------- 1 | use super::{Equivalent, OrderSet}; 2 | use core::hash::{BuildHasher, Hash}; 3 | use indexmap::set::MutableValues as _; 4 | 5 | /// Opt-in mutable access to [`OrderSet`] values. 6 | /// 7 | /// These methods expose `&mut T`, mutable references to the value as it is stored 8 | /// in the set. 9 | /// You are allowed to modify the values in the set **if the modification 10 | /// does not change the value’s hash and equality**. 11 | /// 12 | /// If values are modified erroneously, you can no longer look them up. 13 | /// This is sound (memory safe) but a logical error hazard (just like 14 | /// implementing `PartialEq`, `Eq`, or `Hash` incorrectly would be). 15 | /// 16 | /// `use` this trait to enable its methods for `OrderSet`. 17 | /// 18 | /// This trait is sealed and cannot be implemented for types outside this crate. 19 | pub trait MutableValues: private::Sealed { 20 | type Value; 21 | 22 | /// Return item index and mutable reference to the value 23 | /// 24 | /// Computes in **O(1)** time (average). 25 | fn get_full_mut2(&mut self, value: &Q) -> Option<(usize, &mut Self::Value)> 26 | where 27 | Q: ?Sized + Hash + Equivalent; 28 | 29 | /// Return mutable reference to the value at an index. 30 | /// 31 | /// Valid indices are `0 <= index < self.len()`. 32 | /// 33 | /// Computes in **O(1)** time. 34 | fn get_index_mut2(&mut self, index: usize) -> Option<&mut Self::Value>; 35 | 36 | /// Scan through each value in the set and keep those where the 37 | /// closure `keep` returns `true`. 38 | /// 39 | /// The values are visited in order, and remaining values keep their order. 40 | /// 41 | /// Computes in **O(n)** time (average). 42 | fn retain2(&mut self, keep: F) 43 | where 44 | F: FnMut(&mut Self::Value) -> bool; 45 | } 46 | 47 | /// Opt-in mutable access to [`OrderSet`] values. 48 | /// 49 | /// See [`MutableValues`] for more information. 50 | impl MutableValues for OrderSet 51 | where 52 | S: BuildHasher, 53 | { 54 | type Value = T; 55 | 56 | fn get_full_mut2(&mut self, value: &Q) -> Option<(usize, &mut T)> 57 | where 58 | Q: ?Sized + Hash + Equivalent, 59 | { 60 | self.inner.get_full_mut2(value) 61 | } 62 | 63 | fn get_index_mut2(&mut self, index: usize) -> Option<&mut T> { 64 | self.inner.get_index_mut2(index) 65 | } 66 | 67 | fn retain2(&mut self, keep: F) 68 | where 69 | F: FnMut(&mut T) -> bool, 70 | { 71 | self.inner.retain2(keep); 72 | } 73 | } 74 | 75 | mod private { 76 | pub trait Sealed {} 77 | 78 | impl Sealed for super::OrderSet {} 79 | } 80 | -------------------------------------------------------------------------------- /src/set/rayon.rs: -------------------------------------------------------------------------------- 1 | //! Parallel iterator types for [`OrderSet`] with [rayon]. 2 | //! 3 | //! You will rarely need to interact with this module directly unless you need to name one of the 4 | //! iterator types. 5 | 6 | pub use indexmap::set::rayon::{ 7 | IntoParIter, ParDifference, ParDrain, ParIntersection, ParIter, ParSymmetricDifference, 8 | ParUnion, 9 | }; 10 | 11 | use super::OrderSet; 12 | use core::cmp::Ordering; 13 | use core::hash::{BuildHasher, Hash}; 14 | use core::ops::RangeBounds; 15 | use rayon::prelude::*; 16 | 17 | impl IntoParallelIterator for OrderSet 18 | where 19 | T: Send, 20 | { 21 | type Item = T; 22 | type Iter = IntoParIter; 23 | 24 | fn into_par_iter(self) -> Self::Iter { 25 | self.inner.into_par_iter() 26 | } 27 | } 28 | 29 | impl<'a, T, S> IntoParallelIterator for &'a OrderSet 30 | where 31 | T: Sync, 32 | { 33 | type Item = &'a T; 34 | type Iter = ParIter<'a, T>; 35 | 36 | fn into_par_iter(self) -> Self::Iter { 37 | self.inner.par_iter() 38 | } 39 | } 40 | 41 | impl<'a, T, S> ParallelDrainRange for &'a mut OrderSet 42 | where 43 | T: Send, 44 | { 45 | type Item = T; 46 | type Iter = ParDrain<'a, T>; 47 | 48 | fn par_drain>(self, range: R) -> Self::Iter { 49 | self.inner.par_drain(range) 50 | } 51 | } 52 | 53 | impl OrderSet 54 | where 55 | T: PartialEq + Sync, 56 | { 57 | /// Returns `true` if `self` contains all of the same values as `other`, 58 | /// in the same indexed order, determined in parallel. 59 | pub fn par_eq(&self, other: &OrderSet) -> bool 60 | where 61 | S2: BuildHasher + Sync, 62 | { 63 | self.len() == other.len() && self.par_iter().eq(other) 64 | } 65 | } 66 | 67 | /// Parallel iterator methods and other parallel methods. 68 | /// 69 | /// The following methods **require crate feature `"rayon"`**. 70 | /// 71 | /// See also the `IntoParallelIterator` implementations. 72 | impl OrderSet 73 | where 74 | T: Hash + Eq + Sync, 75 | S: BuildHasher + Sync, 76 | { 77 | /// Return a parallel iterator over the values that are in `self` but not `other`. 78 | /// 79 | /// While parallel iterators can process items in any order, their relative order 80 | /// in the `self` set is still preserved for operations like `reduce` and `collect`. 81 | pub fn par_difference<'a, S2>( 82 | &'a self, 83 | other: &'a OrderSet, 84 | ) -> ParDifference<'a, T, S, S2> 85 | where 86 | S2: BuildHasher + Sync, 87 | { 88 | self.inner.par_difference(&other.inner) 89 | } 90 | 91 | /// Return a parallel iterator over the values that are in `self` or `other`, 92 | /// but not in both. 93 | /// 94 | /// While parallel iterators can process items in any order, their relative order 95 | /// in the sets is still preserved for operations like `reduce` and `collect`. 96 | /// Values from `self` are produced in their original order, followed by 97 | /// values from `other` in their original order. 98 | pub fn par_symmetric_difference<'a, S2>( 99 | &'a self, 100 | other: &'a OrderSet, 101 | ) -> ParSymmetricDifference<'a, T, S, S2> 102 | where 103 | S2: BuildHasher + Sync, 104 | { 105 | self.inner.par_symmetric_difference(&other.inner) 106 | } 107 | 108 | /// Return a parallel iterator over the values that are in both `self` and `other`. 109 | /// 110 | /// While parallel iterators can process items in any order, their relative order 111 | /// in the `self` set is still preserved for operations like `reduce` and `collect`. 112 | pub fn par_intersection<'a, S2>( 113 | &'a self, 114 | other: &'a OrderSet, 115 | ) -> ParIntersection<'a, T, S, S2> 116 | where 117 | S2: BuildHasher + Sync, 118 | { 119 | self.inner.par_intersection(&other.inner) 120 | } 121 | 122 | /// Return a parallel iterator over all values that are in `self` or `other`. 123 | /// 124 | /// While parallel iterators can process items in any order, their relative order 125 | /// in the sets is still preserved for operations like `reduce` and `collect`. 126 | /// Values from `self` are produced in their original order, followed by 127 | /// values that are unique to `other` in their original order. 128 | pub fn par_union<'a, S2>(&'a self, other: &'a OrderSet) -> ParUnion<'a, T, S, S2> 129 | where 130 | S2: BuildHasher + Sync, 131 | { 132 | self.inner.par_union(&other.inner) 133 | } 134 | 135 | /// Returns `true` if `self` has no elements in common with `other`, 136 | /// determined in parallel. 137 | pub fn par_is_disjoint(&self, other: &OrderSet) -> bool 138 | where 139 | S2: BuildHasher + Sync, 140 | { 141 | self.inner.par_is_disjoint(&other.inner) 142 | } 143 | 144 | /// Returns `true` if all elements of `other` are contained in `self`, 145 | /// determined in parallel. 146 | pub fn par_is_superset(&self, other: &OrderSet) -> bool 147 | where 148 | S2: BuildHasher + Sync, 149 | { 150 | self.inner.par_is_superset(&other.inner) 151 | } 152 | 153 | /// Returns `true` if all elements of `self` are contained in `other`, 154 | /// determined in parallel. 155 | pub fn par_is_subset(&self, other: &OrderSet) -> bool 156 | where 157 | S2: BuildHasher + Sync, 158 | { 159 | self.inner.par_is_subset(&other.inner) 160 | } 161 | 162 | /// Returns `true` if `self` contains all of the same values as `other`, 163 | /// regardless of each set's indexed order, determined in parallel. 164 | pub fn par_set_eq(&self, other: &OrderSet) -> bool 165 | where 166 | S2: BuildHasher + Sync, 167 | { 168 | self.inner.par_eq(&other.inner) 169 | } 170 | } 171 | 172 | /// Parallel sorting methods. 173 | /// 174 | /// The following methods **require crate feature `"rayon"`**. 175 | impl OrderSet 176 | where 177 | T: Send, 178 | { 179 | /// Sort the set’s values in parallel by their default ordering. 180 | pub fn par_sort(&mut self) 181 | where 182 | T: Ord, 183 | { 184 | self.inner.par_sort(); 185 | } 186 | 187 | /// Sort the set’s values in place and in parallel, using the comparison function `cmp`. 188 | pub fn par_sort_by(&mut self, cmp: F) 189 | where 190 | F: Fn(&T, &T) -> Ordering + Sync, 191 | { 192 | self.inner.par_sort_by(cmp); 193 | } 194 | 195 | /// Sort the values of the set in parallel and return a by-value parallel iterator of 196 | /// the values with the result. 197 | pub fn par_sorted_by(self, cmp: F) -> IntoParIter 198 | where 199 | F: Fn(&T, &T) -> Ordering + Sync, 200 | { 201 | self.inner.par_sorted_by(cmp) 202 | } 203 | 204 | /// Sort the set's values in parallel by their default ordering. 205 | pub fn par_sort_unstable(&mut self) 206 | where 207 | T: Ord, 208 | { 209 | self.inner.par_sort_unstable(); 210 | } 211 | 212 | /// Sort the set’s values in place and in parallel, using the comparison function `cmp`. 213 | pub fn par_sort_unstable_by(&mut self, cmp: F) 214 | where 215 | F: Fn(&T, &T) -> Ordering + Sync, 216 | { 217 | self.inner.par_sort_unstable_by(cmp); 218 | } 219 | 220 | /// Sort the values of the set in parallel and return a by-value parallel iterator of 221 | /// the values with the result. 222 | pub fn par_sorted_unstable_by(self, cmp: F) -> IntoParIter 223 | where 224 | F: Fn(&T, &T) -> Ordering + Sync, 225 | { 226 | self.inner.par_sorted_unstable_by(cmp) 227 | } 228 | 229 | /// Sort the set’s values in place and in parallel, using a key extraction function. 230 | pub fn par_sort_by_cached_key(&mut self, sort_key: F) 231 | where 232 | K: Ord + Send, 233 | F: Fn(&T) -> K + Sync, 234 | { 235 | self.inner.par_sort_by_cached_key(sort_key); 236 | } 237 | } 238 | 239 | impl FromParallelIterator for OrderSet 240 | where 241 | T: Eq + Hash + Send, 242 | S: BuildHasher + Default + Send, 243 | { 244 | fn from_par_iter(iter: I) -> Self 245 | where 246 | I: IntoParallelIterator, 247 | { 248 | Self { 249 | inner: <_>::from_par_iter(iter), 250 | } 251 | } 252 | } 253 | 254 | impl ParallelExtend for OrderSet 255 | where 256 | T: Eq + Hash + Send, 257 | S: BuildHasher + Send, 258 | { 259 | fn par_extend(&mut self, iter: I) 260 | where 261 | I: IntoParallelIterator, 262 | { 263 | self.inner.par_extend(iter); 264 | } 265 | } 266 | 267 | impl<'a, T: 'a, S> ParallelExtend<&'a T> for OrderSet 268 | where 269 | T: Copy + Eq + Hash + Send + Sync, 270 | S: BuildHasher + Send, 271 | { 272 | fn par_extend(&mut self, iter: I) 273 | where 274 | I: IntoParallelIterator, 275 | { 276 | self.inner.par_extend(iter); 277 | } 278 | } 279 | 280 | #[cfg(test)] 281 | mod tests { 282 | use super::*; 283 | use std::vec::Vec; 284 | 285 | #[test] 286 | fn insert_order() { 287 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 288 | let mut set = OrderSet::new(); 289 | 290 | for &elt in &insert { 291 | set.insert(elt); 292 | } 293 | 294 | assert_eq!(set.par_iter().count(), set.len()); 295 | assert_eq!(set.par_iter().count(), insert.len()); 296 | insert.par_iter().zip(&set).for_each(|(a, b)| { 297 | assert_eq!(a, b); 298 | }); 299 | (0..insert.len()) 300 | .into_par_iter() 301 | .zip(&set) 302 | .for_each(|(i, v)| { 303 | assert_eq!(set.get_index(i).unwrap(), v); 304 | }); 305 | } 306 | 307 | #[test] 308 | fn partial_eq_and_eq() { 309 | let mut set_a = OrderSet::new(); 310 | set_a.insert(1); 311 | set_a.insert(2); 312 | let mut set_b = set_a.clone(); 313 | assert!(set_a.par_eq(&set_b)); 314 | set_b.swap_remove(&1); 315 | assert!(!set_a.par_eq(&set_b)); 316 | set_b.insert(3); 317 | assert!(!set_a.par_eq(&set_b)); 318 | 319 | let set_c: OrderSet<_> = set_b.into_par_iter().collect(); 320 | assert!(!set_a.par_eq(&set_c)); 321 | assert!(!set_c.par_eq(&set_a)); 322 | } 323 | 324 | #[test] 325 | fn extend() { 326 | let mut set = OrderSet::new(); 327 | set.par_extend(vec![&1, &2, &3, &4]); 328 | set.par_extend(vec![5, 6]); 329 | assert_eq!( 330 | set.into_par_iter().collect::>(), 331 | vec![1, 2, 3, 4, 5, 6] 332 | ); 333 | } 334 | 335 | #[test] 336 | fn comparisons() { 337 | let set_a: OrderSet<_> = (0..3).collect(); 338 | let set_b: OrderSet<_> = (3..6).collect(); 339 | let set_c: OrderSet<_> = (0..6).collect(); 340 | let set_d: OrderSet<_> = (3..9).collect(); 341 | 342 | assert!(!set_a.par_is_disjoint(&set_a)); 343 | assert!(set_a.par_is_subset(&set_a)); 344 | assert!(set_a.par_is_superset(&set_a)); 345 | 346 | assert!(set_a.par_is_disjoint(&set_b)); 347 | assert!(set_b.par_is_disjoint(&set_a)); 348 | assert!(!set_a.par_is_subset(&set_b)); 349 | assert!(!set_b.par_is_subset(&set_a)); 350 | assert!(!set_a.par_is_superset(&set_b)); 351 | assert!(!set_b.par_is_superset(&set_a)); 352 | 353 | assert!(!set_a.par_is_disjoint(&set_c)); 354 | assert!(!set_c.par_is_disjoint(&set_a)); 355 | assert!(set_a.par_is_subset(&set_c)); 356 | assert!(!set_c.par_is_subset(&set_a)); 357 | assert!(!set_a.par_is_superset(&set_c)); 358 | assert!(set_c.par_is_superset(&set_a)); 359 | 360 | assert!(!set_c.par_is_disjoint(&set_d)); 361 | assert!(!set_d.par_is_disjoint(&set_c)); 362 | assert!(!set_c.par_is_subset(&set_d)); 363 | assert!(!set_d.par_is_subset(&set_c)); 364 | assert!(!set_c.par_is_superset(&set_d)); 365 | assert!(!set_d.par_is_superset(&set_c)); 366 | } 367 | 368 | #[test] 369 | fn iter_comparisons() { 370 | use std::iter::empty; 371 | 372 | fn check<'a, I1, I2>(iter1: I1, iter2: I2) 373 | where 374 | I1: ParallelIterator, 375 | I2: Iterator, 376 | { 377 | let v1: Vec<_> = iter1.copied().collect(); 378 | let v2: Vec<_> = iter2.collect(); 379 | assert_eq!(v1, v2); 380 | } 381 | 382 | let set_a: OrderSet<_> = (0..3).collect(); 383 | let set_b: OrderSet<_> = (3..6).collect(); 384 | let set_c: OrderSet<_> = (0..6).collect(); 385 | let set_d: OrderSet<_> = (3..9).rev().collect(); 386 | 387 | check(set_a.par_difference(&set_a), empty()); 388 | check(set_a.par_symmetric_difference(&set_a), empty()); 389 | check(set_a.par_intersection(&set_a), 0..3); 390 | check(set_a.par_union(&set_a), 0..3); 391 | 392 | check(set_a.par_difference(&set_b), 0..3); 393 | check(set_b.par_difference(&set_a), 3..6); 394 | check(set_a.par_symmetric_difference(&set_b), 0..6); 395 | check(set_b.par_symmetric_difference(&set_a), (3..6).chain(0..3)); 396 | check(set_a.par_intersection(&set_b), empty()); 397 | check(set_b.par_intersection(&set_a), empty()); 398 | check(set_a.par_union(&set_b), 0..6); 399 | check(set_b.par_union(&set_a), (3..6).chain(0..3)); 400 | 401 | check(set_a.par_difference(&set_c), empty()); 402 | check(set_c.par_difference(&set_a), 3..6); 403 | check(set_a.par_symmetric_difference(&set_c), 3..6); 404 | check(set_c.par_symmetric_difference(&set_a), 3..6); 405 | check(set_a.par_intersection(&set_c), 0..3); 406 | check(set_c.par_intersection(&set_a), 0..3); 407 | check(set_a.par_union(&set_c), 0..6); 408 | check(set_c.par_union(&set_a), 0..6); 409 | 410 | check(set_c.par_difference(&set_d), 0..3); 411 | check(set_d.par_difference(&set_c), (6..9).rev()); 412 | check( 413 | set_c.par_symmetric_difference(&set_d), 414 | (0..3).chain((6..9).rev()), 415 | ); 416 | check( 417 | set_d.par_symmetric_difference(&set_c), 418 | (6..9).rev().chain(0..3), 419 | ); 420 | check(set_c.par_intersection(&set_d), 3..6); 421 | check(set_d.par_intersection(&set_c), (3..6).rev()); 422 | check(set_c.par_union(&set_d), (0..6).chain((6..9).rev())); 423 | check(set_d.par_union(&set_c), (3..9).rev().chain(0..3)); 424 | } 425 | } 426 | -------------------------------------------------------------------------------- /src/set/slice.rs: -------------------------------------------------------------------------------- 1 | use super::OrderSet; 2 | use core::ops::{self, Bound, Index}; 3 | use indexmap::set::Slice; 4 | 5 | // We can't have `impl> Index` because that conflicts with `Index`. 6 | // Instead, we repeat the implementations for all the core range types. 7 | macro_rules! impl_index { 8 | ($($range:ty),*) => {$( 9 | impl Index<$range> for OrderSet { 10 | type Output = Slice; 11 | 12 | fn index(&self, range: $range) -> &Self::Output { 13 | &self.inner[range] 14 | } 15 | } 16 | )*} 17 | } 18 | impl_index!( 19 | ops::Range, 20 | ops::RangeFrom, 21 | ops::RangeFull, 22 | ops::RangeInclusive, 23 | ops::RangeTo, 24 | ops::RangeToInclusive, 25 | (Bound, Bound) 26 | ); 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | use alloc::vec::Vec; 32 | 33 | #[test] 34 | fn slice_index() { 35 | fn check(vec_slice: &[i32], set_slice: &Slice, sub_slice: &Slice) { 36 | assert_eq!(set_slice as *const _, sub_slice as *const _); 37 | itertools::assert_equal(vec_slice, set_slice); 38 | } 39 | 40 | let vec: Vec = (0..10).map(|i| i * i).collect(); 41 | let set: OrderSet = vec.iter().cloned().collect(); 42 | let slice = set.as_slice(); 43 | 44 | // RangeFull 45 | check(&vec[..], &set[..], &slice[..]); 46 | 47 | for i in 0usize..10 { 48 | // Index 49 | assert_eq!(vec[i], set[i]); 50 | assert_eq!(vec[i], slice[i]); 51 | 52 | // RangeFrom 53 | check(&vec[i..], &set[i..], &slice[i..]); 54 | 55 | // RangeTo 56 | check(&vec[..i], &set[..i], &slice[..i]); 57 | 58 | // RangeToInclusive 59 | check(&vec[..=i], &set[..=i], &slice[..=i]); 60 | 61 | // (Bound, Bound) 62 | let bounds = (Bound::Excluded(i), Bound::Unbounded); 63 | check(&vec[i + 1..], &set[bounds], &slice[bounds]); 64 | 65 | for j in i..=10 { 66 | // Range 67 | check(&vec[i..j], &set[i..j], &slice[i..j]); 68 | } 69 | 70 | for j in i..10 { 71 | // RangeInclusive 72 | check(&vec[i..=j], &set[i..=j], &slice[i..=j]); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/set/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::string::String; 3 | use std::vec::Vec; 4 | 5 | #[test] 6 | fn it_works() { 7 | let mut set = OrderSet::new(); 8 | assert_eq!(set.is_empty(), true); 9 | set.insert(1); 10 | set.insert(1); 11 | assert_eq!(set.len(), 1); 12 | assert!(set.get(&1).is_some()); 13 | assert_eq!(set.is_empty(), false); 14 | } 15 | 16 | #[test] 17 | fn new() { 18 | let set = OrderSet::::new(); 19 | println!("{:?}", set); 20 | assert_eq!(set.capacity(), 0); 21 | assert_eq!(set.len(), 0); 22 | assert_eq!(set.is_empty(), true); 23 | } 24 | 25 | #[test] 26 | fn insert() { 27 | let insert = [0, 4, 2, 12, 8, 7, 11, 5]; 28 | let not_present = [1, 3, 6, 9, 10]; 29 | let mut set = OrderSet::with_capacity(insert.len()); 30 | 31 | for (i, &elt) in insert.iter().enumerate() { 32 | assert_eq!(set.len(), i); 33 | set.insert(elt); 34 | assert_eq!(set.len(), i + 1); 35 | assert_eq!(set.get(&elt), Some(&elt)); 36 | } 37 | println!("{:?}", set); 38 | 39 | for &elt in ¬_present { 40 | assert!(set.get(&elt).is_none()); 41 | } 42 | } 43 | 44 | #[test] 45 | fn insert_full() { 46 | let insert = vec![9, 2, 7, 1, 4, 6, 13]; 47 | let present = vec![1, 6, 2]; 48 | let mut set = OrderSet::with_capacity(insert.len()); 49 | 50 | for (i, &elt) in insert.iter().enumerate() { 51 | assert_eq!(set.len(), i); 52 | let (index, success) = set.insert_full(elt); 53 | assert!(success); 54 | assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); 55 | assert_eq!(set.len(), i + 1); 56 | } 57 | 58 | let len = set.len(); 59 | for &elt in &present { 60 | let (index, success) = set.insert_full(elt); 61 | assert!(!success); 62 | assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); 63 | assert_eq!(set.len(), len); 64 | } 65 | } 66 | 67 | #[test] 68 | fn insert_2() { 69 | let mut set = OrderSet::with_capacity(16); 70 | 71 | let mut values = vec![]; 72 | values.extend(0..16); 73 | values.extend(if cfg!(miri) { 32..64 } else { 128..267 }); 74 | 75 | for &i in &values { 76 | let old_set = set.clone(); 77 | set.insert(i); 78 | for value in old_set.iter() { 79 | if set.get(value).is_none() { 80 | println!("old_set: {:?}", old_set); 81 | println!("set: {:?}", set); 82 | panic!("did not find {} in set", value); 83 | } 84 | } 85 | } 86 | 87 | for &i in &values { 88 | assert!(set.get(&i).is_some(), "did not find {}", i); 89 | } 90 | } 91 | 92 | #[test] 93 | fn insert_dup() { 94 | let mut elements = vec![0, 2, 4, 6, 8]; 95 | let mut set: OrderSet = elements.drain(..).collect(); 96 | { 97 | let (i, v) = set.get_full(&0).unwrap(); 98 | assert_eq!(set.len(), 5); 99 | assert_eq!(i, 0); 100 | assert_eq!(*v, 0); 101 | } 102 | { 103 | let inserted = set.insert(0); 104 | let (i, v) = set.get_full(&0).unwrap(); 105 | assert_eq!(set.len(), 5); 106 | assert_eq!(inserted, false); 107 | assert_eq!(i, 0); 108 | assert_eq!(*v, 0); 109 | } 110 | } 111 | 112 | #[test] 113 | fn insert_order() { 114 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 115 | let mut set = OrderSet::new(); 116 | 117 | for &elt in &insert { 118 | set.insert(elt); 119 | } 120 | 121 | assert_eq!(set.iter().count(), set.len()); 122 | assert_eq!(set.iter().count(), insert.len()); 123 | for (a, b) in insert.iter().zip(set.iter()) { 124 | assert_eq!(a, b); 125 | } 126 | for (i, v) in (0..insert.len()).zip(set.iter()) { 127 | assert_eq!(set.get_index(i).unwrap(), v); 128 | } 129 | } 130 | 131 | #[test] 132 | fn shift_insert() { 133 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 134 | let mut set = OrderSet::new(); 135 | 136 | for &elt in &insert { 137 | set.shift_insert(0, elt); 138 | } 139 | 140 | assert_eq!(set.iter().count(), set.len()); 141 | assert_eq!(set.iter().count(), insert.len()); 142 | for (a, b) in insert.iter().rev().zip(set.iter()) { 143 | assert_eq!(a, b); 144 | } 145 | for (i, v) in (0..insert.len()).zip(set.iter()) { 146 | assert_eq!(set.get_index(i).unwrap(), v); 147 | } 148 | 149 | // "insert" that moves an existing entry 150 | set.shift_insert(0, insert[0]); 151 | assert_eq!(set.iter().count(), insert.len()); 152 | assert_eq!(insert[0], set[0]); 153 | for (a, b) in insert[1..].iter().rev().zip(set.iter().skip(1)) { 154 | assert_eq!(a, b); 155 | } 156 | } 157 | 158 | #[test] 159 | fn replace() { 160 | let replace = [0, 4, 2, 12, 8, 7, 11, 5]; 161 | let not_present = [1, 3, 6, 9, 10]; 162 | let mut set = OrderSet::with_capacity(replace.len()); 163 | 164 | for (i, &elt) in replace.iter().enumerate() { 165 | assert_eq!(set.len(), i); 166 | set.replace(elt); 167 | assert_eq!(set.len(), i + 1); 168 | assert_eq!(set.get(&elt), Some(&elt)); 169 | } 170 | println!("{:?}", set); 171 | 172 | for &elt in ¬_present { 173 | assert!(set.get(&elt).is_none()); 174 | } 175 | } 176 | 177 | #[test] 178 | fn replace_full() { 179 | let replace = vec![9, 2, 7, 1, 4, 6, 13]; 180 | let present = vec![1, 6, 2]; 181 | let mut set = OrderSet::with_capacity(replace.len()); 182 | 183 | for (i, &elt) in replace.iter().enumerate() { 184 | assert_eq!(set.len(), i); 185 | let (index, replaced) = set.replace_full(elt); 186 | assert!(replaced.is_none()); 187 | assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); 188 | assert_eq!(set.len(), i + 1); 189 | } 190 | 191 | let len = set.len(); 192 | for &elt in &present { 193 | let (index, replaced) = set.replace_full(elt); 194 | assert_eq!(Some(elt), replaced); 195 | assert_eq!(Some(index), set.get_full(&elt).map(|x| x.0)); 196 | assert_eq!(set.len(), len); 197 | } 198 | } 199 | 200 | #[test] 201 | fn replace_2() { 202 | let mut set = OrderSet::with_capacity(16); 203 | 204 | let mut values = vec![]; 205 | values.extend(0..16); 206 | values.extend(if cfg!(miri) { 32..64 } else { 128..267 }); 207 | 208 | for &i in &values { 209 | let old_set = set.clone(); 210 | set.replace(i); 211 | for value in old_set.iter() { 212 | if set.get(value).is_none() { 213 | println!("old_set: {:?}", old_set); 214 | println!("set: {:?}", set); 215 | panic!("did not find {} in set", value); 216 | } 217 | } 218 | } 219 | 220 | for &i in &values { 221 | assert!(set.get(&i).is_some(), "did not find {}", i); 222 | } 223 | } 224 | 225 | #[test] 226 | fn replace_dup() { 227 | let mut elements = vec![0, 2, 4, 6, 8]; 228 | let mut set: OrderSet = elements.drain(..).collect(); 229 | { 230 | let (i, v) = set.get_full(&0).unwrap(); 231 | assert_eq!(set.len(), 5); 232 | assert_eq!(i, 0); 233 | assert_eq!(*v, 0); 234 | } 235 | { 236 | let replaced = set.replace(0); 237 | let (i, v) = set.get_full(&0).unwrap(); 238 | assert_eq!(set.len(), 5); 239 | assert_eq!(replaced, Some(0)); 240 | assert_eq!(i, 0); 241 | assert_eq!(*v, 0); 242 | } 243 | } 244 | 245 | #[test] 246 | fn replace_order() { 247 | let replace = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 248 | let mut set = OrderSet::new(); 249 | 250 | for &elt in &replace { 251 | set.replace(elt); 252 | } 253 | 254 | assert_eq!(set.iter().count(), set.len()); 255 | assert_eq!(set.iter().count(), replace.len()); 256 | for (a, b) in replace.iter().zip(set.iter()) { 257 | assert_eq!(a, b); 258 | } 259 | for (i, v) in (0..replace.len()).zip(set.iter()) { 260 | assert_eq!(set.get_index(i).unwrap(), v); 261 | } 262 | } 263 | 264 | #[test] 265 | fn replace_change() { 266 | // Check pointers to make sure it really changes 267 | let mut set = orderset!(vec![42]); 268 | let old_ptr = set[0].as_ptr(); 269 | let new = set[0].clone(); 270 | let new_ptr = new.as_ptr(); 271 | assert_ne!(old_ptr, new_ptr); 272 | let replaced = set.replace(new).unwrap(); 273 | assert_eq!(replaced.as_ptr(), old_ptr); 274 | } 275 | 276 | #[test] 277 | fn grow() { 278 | let insert = [0, 4, 2, 12, 8, 7, 11]; 279 | let not_present = [1, 3, 6, 9, 10]; 280 | let mut set = OrderSet::with_capacity(insert.len()); 281 | 282 | for (i, &elt) in insert.iter().enumerate() { 283 | assert_eq!(set.len(), i); 284 | set.insert(elt); 285 | assert_eq!(set.len(), i + 1); 286 | assert_eq!(set.get(&elt), Some(&elt)); 287 | } 288 | 289 | println!("{:?}", set); 290 | for &elt in &insert { 291 | set.insert(elt * 10); 292 | } 293 | for &elt in &insert { 294 | set.insert(elt * 100); 295 | } 296 | for (i, &elt) in insert.iter().cycle().enumerate().take(100) { 297 | set.insert(elt * 100 + i as i32); 298 | } 299 | println!("{:?}", set); 300 | for &elt in ¬_present { 301 | assert!(set.get(&elt).is_none()); 302 | } 303 | } 304 | 305 | #[test] 306 | fn reserve() { 307 | let mut set = OrderSet::::new(); 308 | assert_eq!(set.capacity(), 0); 309 | set.reserve(100); 310 | let capacity = set.capacity(); 311 | assert!(capacity >= 100); 312 | for i in 0..capacity { 313 | assert_eq!(set.len(), i); 314 | set.insert(i); 315 | assert_eq!(set.len(), i + 1); 316 | assert_eq!(set.capacity(), capacity); 317 | assert_eq!(set.get(&i), Some(&i)); 318 | } 319 | set.insert(capacity); 320 | assert_eq!(set.len(), capacity + 1); 321 | assert!(set.capacity() > capacity); 322 | assert_eq!(set.get(&capacity), Some(&capacity)); 323 | } 324 | 325 | #[test] 326 | fn try_reserve() { 327 | let mut set = OrderSet::::new(); 328 | assert_eq!(set.capacity(), 0); 329 | assert_eq!(set.try_reserve(100), Ok(())); 330 | assert!(set.capacity() >= 100); 331 | assert!(set.try_reserve(usize::MAX).is_err()); 332 | } 333 | 334 | #[test] 335 | fn shrink_to_fit() { 336 | let mut set = OrderSet::::new(); 337 | assert_eq!(set.capacity(), 0); 338 | for i in 0..100 { 339 | assert_eq!(set.len(), i); 340 | set.insert(i); 341 | assert_eq!(set.len(), i + 1); 342 | assert!(set.capacity() >= i + 1); 343 | assert_eq!(set.get(&i), Some(&i)); 344 | set.shrink_to_fit(); 345 | assert_eq!(set.len(), i + 1); 346 | assert_eq!(set.capacity(), i + 1); 347 | assert_eq!(set.get(&i), Some(&i)); 348 | } 349 | } 350 | 351 | #[test] 352 | fn remove() { 353 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 354 | let mut set = OrderSet::new(); 355 | 356 | for &elt in &insert { 357 | set.insert(elt); 358 | } 359 | 360 | assert_eq!(set.iter().count(), set.len()); 361 | assert_eq!(set.iter().count(), insert.len()); 362 | for (a, b) in insert.iter().zip(set.iter()) { 363 | assert_eq!(a, b); 364 | } 365 | 366 | let remove_fail = [99, 77]; 367 | let remove = [4, 12, 8, 7]; 368 | 369 | for &value in &remove_fail { 370 | assert!(set.swap_remove_full(&value).is_none()); 371 | } 372 | println!("{:?}", set); 373 | for &value in &remove { 374 | //println!("{:?}", set); 375 | let index = set.get_full(&value).unwrap().0; 376 | assert_eq!(set.swap_remove_full(&value), Some((index, value))); 377 | } 378 | println!("{:?}", set); 379 | 380 | for value in &insert { 381 | assert_eq!(set.get(value).is_some(), !remove.contains(value)); 382 | } 383 | assert_eq!(set.len(), insert.len() - remove.len()); 384 | assert_eq!(set.iter().count(), insert.len() - remove.len()); 385 | } 386 | 387 | #[test] 388 | fn swap_remove_index() { 389 | let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; 390 | let mut set = OrderSet::new(); 391 | 392 | for &elt in &insert { 393 | set.insert(elt); 394 | } 395 | 396 | let mut vector = insert.to_vec(); 397 | let remove_sequence = &[3, 3, 10, 4, 5, 4, 3, 0, 1]; 398 | 399 | // check that the same swap remove sequence on vec and set 400 | // have the same result. 401 | for &rm in remove_sequence { 402 | let out_vec = vector.swap_remove(rm); 403 | let out_set = set.swap_remove_index(rm).unwrap(); 404 | assert_eq!(out_vec, out_set); 405 | } 406 | assert_eq!(vector.len(), set.len()); 407 | for (a, b) in vector.iter().zip(set.iter()) { 408 | assert_eq!(a, b); 409 | } 410 | } 411 | 412 | #[test] 413 | fn partial_eq_and_eq() { 414 | let mut set_a = OrderSet::new(); 415 | set_a.insert(1); 416 | set_a.insert(2); 417 | let mut set_b = set_a.clone(); 418 | assert_eq!(set_a, set_b); 419 | set_b.swap_remove(&1); 420 | assert_ne!(set_a, set_b); 421 | 422 | let set_c: OrderSet<_> = set_b.into_iter().collect(); 423 | assert_ne!(set_a, set_c); 424 | assert_ne!(set_c, set_a); 425 | } 426 | 427 | #[test] 428 | fn extend() { 429 | let mut set = OrderSet::new(); 430 | set.extend(vec![&1, &2, &3, &4]); 431 | set.extend(vec![5, 6]); 432 | assert_eq!(set.into_iter().collect::>(), vec![1, 2, 3, 4, 5, 6]); 433 | } 434 | 435 | #[test] 436 | fn comparisons() { 437 | let set_a: OrderSet<_> = (0..3).collect(); 438 | let set_b: OrderSet<_> = (3..6).collect(); 439 | let set_c: OrderSet<_> = (0..6).collect(); 440 | let set_d: OrderSet<_> = (3..9).collect(); 441 | 442 | assert!(!set_a.is_disjoint(&set_a)); 443 | assert!(set_a.is_subset(&set_a)); 444 | assert!(set_a.is_superset(&set_a)); 445 | 446 | assert!(set_a.is_disjoint(&set_b)); 447 | assert!(set_b.is_disjoint(&set_a)); 448 | assert!(!set_a.is_subset(&set_b)); 449 | assert!(!set_b.is_subset(&set_a)); 450 | assert!(!set_a.is_superset(&set_b)); 451 | assert!(!set_b.is_superset(&set_a)); 452 | 453 | assert!(!set_a.is_disjoint(&set_c)); 454 | assert!(!set_c.is_disjoint(&set_a)); 455 | assert!(set_a.is_subset(&set_c)); 456 | assert!(!set_c.is_subset(&set_a)); 457 | assert!(!set_a.is_superset(&set_c)); 458 | assert!(set_c.is_superset(&set_a)); 459 | 460 | assert!(!set_c.is_disjoint(&set_d)); 461 | assert!(!set_d.is_disjoint(&set_c)); 462 | assert!(!set_c.is_subset(&set_d)); 463 | assert!(!set_d.is_subset(&set_c)); 464 | assert!(!set_c.is_superset(&set_d)); 465 | assert!(!set_d.is_superset(&set_c)); 466 | } 467 | 468 | #[test] 469 | fn iter_comparisons() { 470 | use std::iter::empty; 471 | 472 | fn check<'a, I1, I2>(iter1: I1, iter2: I2) 473 | where 474 | I1: Iterator, 475 | I2: Iterator, 476 | { 477 | assert!(iter1.copied().eq(iter2)); 478 | } 479 | 480 | let set_a: OrderSet<_> = (0..3).collect(); 481 | let set_b: OrderSet<_> = (3..6).collect(); 482 | let set_c: OrderSet<_> = (0..6).collect(); 483 | let set_d: OrderSet<_> = (3..9).rev().collect(); 484 | 485 | check(set_a.difference(&set_a), empty()); 486 | check(set_a.symmetric_difference(&set_a), empty()); 487 | check(set_a.intersection(&set_a), 0..3); 488 | check(set_a.union(&set_a), 0..3); 489 | 490 | check(set_a.difference(&set_b), 0..3); 491 | check(set_b.difference(&set_a), 3..6); 492 | check(set_a.symmetric_difference(&set_b), 0..6); 493 | check(set_b.symmetric_difference(&set_a), (3..6).chain(0..3)); 494 | check(set_a.intersection(&set_b), empty()); 495 | check(set_b.intersection(&set_a), empty()); 496 | check(set_a.union(&set_b), 0..6); 497 | check(set_b.union(&set_a), (3..6).chain(0..3)); 498 | 499 | check(set_a.difference(&set_c), empty()); 500 | check(set_c.difference(&set_a), 3..6); 501 | check(set_a.symmetric_difference(&set_c), 3..6); 502 | check(set_c.symmetric_difference(&set_a), 3..6); 503 | check(set_a.intersection(&set_c), 0..3); 504 | check(set_c.intersection(&set_a), 0..3); 505 | check(set_a.union(&set_c), 0..6); 506 | check(set_c.union(&set_a), 0..6); 507 | 508 | check(set_c.difference(&set_d), 0..3); 509 | check(set_d.difference(&set_c), (6..9).rev()); 510 | check( 511 | set_c.symmetric_difference(&set_d), 512 | (0..3).chain((6..9).rev()), 513 | ); 514 | check(set_d.symmetric_difference(&set_c), (6..9).rev().chain(0..3)); 515 | check(set_c.intersection(&set_d), 3..6); 516 | check(set_d.intersection(&set_c), (3..6).rev()); 517 | check(set_c.union(&set_d), (0..6).chain((6..9).rev())); 518 | check(set_d.union(&set_c), (3..9).rev().chain(0..3)); 519 | } 520 | 521 | #[test] 522 | fn ops() { 523 | let empty = OrderSet::::new(); 524 | let set_a: OrderSet<_> = (0..3).collect(); 525 | let set_b: OrderSet<_> = (3..6).collect(); 526 | let set_c: OrderSet<_> = (0..6).collect(); 527 | let set_d: OrderSet<_> = (3..9).rev().collect(); 528 | 529 | #[allow(clippy::eq_op)] 530 | { 531 | assert_eq!(&set_a & &set_a, set_a); 532 | assert_eq!(&set_a | &set_a, set_a); 533 | assert_eq!(&set_a ^ &set_a, empty); 534 | assert_eq!(&set_a - &set_a, empty); 535 | } 536 | 537 | assert_eq!(&set_a & &set_b, empty); 538 | assert_eq!(&set_b & &set_a, empty); 539 | assert_eq!(&set_a | &set_b, set_c); 540 | assert_ne!(&set_b | &set_a, set_c); 541 | assert!((&set_b | &set_a).set_eq(&set_c)); 542 | assert_eq!(&set_a ^ &set_b, set_c); 543 | assert_ne!(&set_b ^ &set_a, set_c); 544 | assert!((&set_b ^ &set_a).set_eq(&set_c)); 545 | assert_eq!(&set_a - &set_b, set_a); 546 | assert_eq!(&set_b - &set_a, set_b); 547 | 548 | assert_eq!(&set_a & &set_c, set_a); 549 | assert_eq!(&set_c & &set_a, set_a); 550 | assert_eq!(&set_a | &set_c, set_c); 551 | assert_eq!(&set_c | &set_a, set_c); 552 | assert_eq!(&set_a ^ &set_c, set_b); 553 | assert_eq!(&set_c ^ &set_a, set_b); 554 | assert_eq!(&set_a - &set_c, empty); 555 | assert_eq!(&set_c - &set_a, set_b); 556 | 557 | assert_eq!(&set_c & &set_d, set_b); 558 | assert_ne!(&set_d & &set_c, set_b); 559 | assert!((&set_d & &set_c).set_eq(&set_b)); 560 | assert_ne!(&set_c | &set_d, &set_a | &set_d); 561 | assert!((&set_c | &set_d).set_eq(&(&set_a | &set_d))); 562 | assert_ne!(&set_d | &set_c, &set_a | &set_d); 563 | assert!((&set_d | &set_c).set_eq(&(&set_a | &set_d))); 564 | assert_eq!(&set_c ^ &set_d, &set_a | &(&set_d - &set_b)); 565 | assert_ne!(&set_d ^ &set_c, &set_a | &(&set_d - &set_b)); 566 | assert!((&set_d ^ &set_c).set_eq(&(&set_a | &(&set_d - &set_b)))); 567 | assert_eq!(&set_c - &set_d, set_a); 568 | assert_eq!(&set_d - &set_c, &set_d - &set_b); 569 | } 570 | 571 | #[test] 572 | #[cfg(feature = "std")] 573 | fn from_array() { 574 | let set1 = OrderSet::from([1, 2, 3, 4]); 575 | let set2: OrderSet<_> = [1, 2, 3, 4].into(); 576 | 577 | assert_eq!(set1, set2); 578 | } 579 | 580 | #[test] 581 | fn iter_default() { 582 | struct Item; 583 | fn assert_default() 584 | where 585 | T: Default + Iterator, 586 | { 587 | assert!(T::default().next().is_none()); 588 | } 589 | assert_default::>(); 590 | assert_default::>(); 591 | } 592 | 593 | #[test] 594 | fn test_binary_search_by() { 595 | // adapted from std's test for binary_search 596 | let b: OrderSet = [].into(); 597 | assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(0)); 598 | 599 | let b: OrderSet = [4].into(); 600 | assert_eq!(b.binary_search_by(|x| x.cmp(&3)), Err(0)); 601 | assert_eq!(b.binary_search_by(|x| x.cmp(&4)), Ok(0)); 602 | assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(1)); 603 | 604 | let b: OrderSet = [1, 2, 4, 6, 8, 9].into(); 605 | assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(3)); 606 | assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Ok(3)); 607 | assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Err(4)); 608 | assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Ok(4)); 609 | 610 | let b: OrderSet = [1, 2, 4, 5, 6, 8].into(); 611 | assert_eq!(b.binary_search_by(|x| x.cmp(&9)), Err(6)); 612 | 613 | let b: OrderSet = [1, 2, 4, 6, 7, 8, 9].into(); 614 | assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Ok(3)); 615 | assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(3)); 616 | assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Ok(5)); 617 | 618 | let b: OrderSet = [1, 2, 4, 5, 6, 8, 9].into(); 619 | assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Err(5)); 620 | assert_eq!(b.binary_search_by(|x| x.cmp(&0)), Err(0)); 621 | 622 | let b: OrderSet = [1, 3, 3, 3, 7].into(); 623 | assert_eq!(b.binary_search_by(|x| x.cmp(&0)), Err(0)); 624 | assert_eq!(b.binary_search_by(|x| x.cmp(&1)), Ok(0)); 625 | assert_eq!(b.binary_search_by(|x| x.cmp(&2)), Err(1)); 626 | // diff from std as set merges the duplicate keys 627 | assert!(match b.binary_search_by(|x| x.cmp(&3)) { 628 | Ok(1..=2) => true, 629 | _ => false, 630 | }); 631 | assert!(match b.binary_search_by(|x| x.cmp(&3)) { 632 | Ok(1..=2) => true, 633 | _ => false, 634 | }); 635 | assert_eq!(b.binary_search_by(|x| x.cmp(&4)), Err(2)); 636 | assert_eq!(b.binary_search_by(|x| x.cmp(&5)), Err(2)); 637 | assert_eq!(b.binary_search_by(|x| x.cmp(&6)), Err(2)); 638 | assert_eq!(b.binary_search_by(|x| x.cmp(&7)), Ok(2)); 639 | assert_eq!(b.binary_search_by(|x| x.cmp(&8)), Err(3)); 640 | } 641 | 642 | #[test] 643 | fn test_binary_search_by_key() { 644 | // adapted from std's test for binary_search 645 | let b: OrderSet = [].into(); 646 | assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(0)); 647 | 648 | let b: OrderSet = [4].into(); 649 | assert_eq!(b.binary_search_by_key(&3, |&x| x), Err(0)); 650 | assert_eq!(b.binary_search_by_key(&4, |&x| x), Ok(0)); 651 | assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(1)); 652 | 653 | let b: OrderSet = [1, 2, 4, 6, 8, 9].into(); 654 | assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(3)); 655 | assert_eq!(b.binary_search_by_key(&6, |&x| x), Ok(3)); 656 | assert_eq!(b.binary_search_by_key(&7, |&x| x), Err(4)); 657 | assert_eq!(b.binary_search_by_key(&8, |&x| x), Ok(4)); 658 | 659 | let b: OrderSet = [1, 2, 4, 5, 6, 8].into(); 660 | assert_eq!(b.binary_search_by_key(&9, |&x| x), Err(6)); 661 | 662 | let b: OrderSet = [1, 2, 4, 6, 7, 8, 9].into(); 663 | assert_eq!(b.binary_search_by_key(&6, |&x| x), Ok(3)); 664 | assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(3)); 665 | assert_eq!(b.binary_search_by_key(&8, |&x| x), Ok(5)); 666 | 667 | let b: OrderSet = [1, 2, 4, 5, 6, 8, 9].into(); 668 | assert_eq!(b.binary_search_by_key(&7, |&x| x), Err(5)); 669 | assert_eq!(b.binary_search_by_key(&0, |&x| x), Err(0)); 670 | 671 | let b: OrderSet = [1, 3, 3, 3, 7].into(); 672 | assert_eq!(b.binary_search_by_key(&0, |&x| x), Err(0)); 673 | assert_eq!(b.binary_search_by_key(&1, |&x| x), Ok(0)); 674 | assert_eq!(b.binary_search_by_key(&2, |&x| x), Err(1)); 675 | // diff from std as set merges the duplicate keys 676 | assert!(match b.binary_search_by_key(&3, |&x| x) { 677 | Ok(1..=2) => true, 678 | _ => false, 679 | }); 680 | assert!(match b.binary_search_by_key(&3, |&x| x) { 681 | Ok(1..=2) => true, 682 | _ => false, 683 | }); 684 | assert_eq!(b.binary_search_by_key(&4, |&x| x), Err(2)); 685 | assert_eq!(b.binary_search_by_key(&5, |&x| x), Err(2)); 686 | assert_eq!(b.binary_search_by_key(&6, |&x| x), Err(2)); 687 | assert_eq!(b.binary_search_by_key(&7, |&x| x), Ok(2)); 688 | assert_eq!(b.binary_search_by_key(&8, |&x| x), Err(3)); 689 | } 690 | 691 | #[test] 692 | fn test_partition_point() { 693 | // adapted from std's test for partition_point 694 | let b: OrderSet = [].into(); 695 | assert_eq!(b.partition_point(|&x| x < 5), 0); 696 | 697 | let b: OrderSet<_> = [4].into(); 698 | assert_eq!(b.partition_point(|&x| x < 3), 0); 699 | assert_eq!(b.partition_point(|&x| x < 4), 0); 700 | assert_eq!(b.partition_point(|&x| x < 5), 1); 701 | 702 | let b: OrderSet<_> = [1, 2, 4, 6, 8, 9].into(); 703 | assert_eq!(b.partition_point(|&x| x < 5), 3); 704 | assert_eq!(b.partition_point(|&x| x < 6), 3); 705 | assert_eq!(b.partition_point(|&x| x < 7), 4); 706 | assert_eq!(b.partition_point(|&x| x < 8), 4); 707 | 708 | let b: OrderSet<_> = [1, 2, 4, 5, 6, 8].into(); 709 | assert_eq!(b.partition_point(|&x| x < 9), 6); 710 | 711 | let b: OrderSet<_> = [1, 2, 4, 6, 7, 8, 9].into(); 712 | assert_eq!(b.partition_point(|&x| x < 6), 3); 713 | assert_eq!(b.partition_point(|&x| x < 5), 3); 714 | assert_eq!(b.partition_point(|&x| x < 8), 5); 715 | 716 | let b: OrderSet<_> = [1, 2, 4, 5, 6, 8, 9].into(); 717 | assert_eq!(b.partition_point(|&x| x < 7), 5); 718 | assert_eq!(b.partition_point(|&x| x < 0), 0); 719 | 720 | let b: OrderSet<_> = [1, 3, 3, 3, 7].into(); 721 | assert_eq!(b.partition_point(|&x| x < 0), 0); 722 | assert_eq!(b.partition_point(|&x| x < 1), 0); 723 | assert_eq!(b.partition_point(|&x| x < 2), 1); 724 | assert_eq!(b.partition_point(|&x| x < 3), 1); 725 | assert_eq!(b.partition_point(|&x| x < 4), 2); // diff from std as set merges the duplicate keys 726 | assert_eq!(b.partition_point(|&x| x < 5), 2); 727 | assert_eq!(b.partition_point(|&x| x < 6), 2); 728 | assert_eq!(b.partition_point(|&x| x < 7), 2); 729 | assert_eq!(b.partition_point(|&x| x < 8), 3); 730 | } 731 | -------------------------------------------------------------------------------- /test-nostd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-nostd" 3 | version = "0.1.0" 4 | publish = false 5 | edition = "2021" 6 | 7 | [dependencies.ordermap] 8 | path = ".." 9 | default-features = false 10 | features = ["serde"] 11 | 12 | [dev-dependencies] 13 | -------------------------------------------------------------------------------- /test-nostd/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | use core::hash::BuildHasherDefault; 4 | use core::hash::Hasher; 5 | 6 | use ordermap::OrderMap; 7 | use ordermap::OrderSet; 8 | 9 | #[derive(Default)] 10 | struct BadHasher(u64); 11 | 12 | impl Hasher for BadHasher { 13 | fn finish(&self) -> u64 { 14 | self.0 15 | } 16 | fn write(&mut self, bytes: &[u8]) { 17 | for &byte in bytes { 18 | self.0 += byte as u64 19 | } 20 | } 21 | } 22 | 23 | type Map = OrderMap>; 24 | type Set = OrderSet>; 25 | 26 | pub fn test_compile() { 27 | let mut map = Map::default(); 28 | map.insert(1, 1); 29 | map.insert(2, 4); 30 | for (_, _) in map.iter() {} 31 | 32 | let _map2 = Map::from_iter(Some((1, 1))); 33 | 34 | let mut set = Set::default(); 35 | set.insert("a"); 36 | } 37 | -------------------------------------------------------------------------------- /test-serde/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-serde" 3 | version = "0.1.0" 4 | publish = false 5 | edition = "2021" 6 | 7 | [dependencies] 8 | 9 | [dev-dependencies] 10 | fnv = "1.0" 11 | ordermap = { path = "..", features = ["serde"] } 12 | serde = { version = "1.0.99", features = ["derive"] } 13 | serde_test = "1.0.99" 14 | -------------------------------------------------------------------------------- /test-serde/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg(test)] 2 | 3 | use fnv::FnvBuildHasher; 4 | use ordermap::{ordermap, orderset, OrderMap, OrderSet}; 5 | use serde::{Deserialize, Serialize}; 6 | use serde_test::{assert_tokens, Token}; 7 | 8 | #[test] 9 | fn test_serde_map() { 10 | let map = ordermap! { 1 => 2, 3 => 4 }; 11 | assert_tokens( 12 | &map, 13 | &[ 14 | Token::Map { len: Some(2) }, 15 | Token::I32(1), 16 | Token::I32(2), 17 | Token::I32(3), 18 | Token::I32(4), 19 | Token::MapEnd, 20 | ], 21 | ); 22 | } 23 | 24 | #[test] 25 | fn test_serde_set() { 26 | let set = orderset! { 1, 2, 3, 4 }; 27 | assert_tokens( 28 | &set, 29 | &[ 30 | Token::Seq { len: Some(4) }, 31 | Token::I32(1), 32 | Token::I32(2), 33 | Token::I32(3), 34 | Token::I32(4), 35 | Token::SeqEnd, 36 | ], 37 | ); 38 | } 39 | 40 | #[test] 41 | fn test_serde_map_fnv_hasher() { 42 | let mut map: OrderMap = Default::default(); 43 | map.insert(1, 2); 44 | map.insert(3, 4); 45 | assert_tokens( 46 | &map, 47 | &[ 48 | Token::Map { len: Some(2) }, 49 | Token::I32(1), 50 | Token::I32(2), 51 | Token::I32(3), 52 | Token::I32(4), 53 | Token::MapEnd, 54 | ], 55 | ); 56 | } 57 | 58 | #[test] 59 | fn test_serde_set_fnv_hasher() { 60 | let mut set: OrderSet = Default::default(); 61 | set.extend(1..5); 62 | assert_tokens( 63 | &set, 64 | &[ 65 | Token::Seq { len: Some(4) }, 66 | Token::I32(1), 67 | Token::I32(2), 68 | Token::I32(3), 69 | Token::I32(4), 70 | Token::SeqEnd, 71 | ], 72 | ); 73 | } 74 | 75 | #[test] 76 | fn test_serde_seq_map() { 77 | #[derive(Debug, Deserialize, Serialize)] 78 | #[serde(transparent)] 79 | struct SeqOrderMap { 80 | #[serde(with = "ordermap::map::serde_seq")] 81 | map: OrderMap, 82 | } 83 | 84 | impl PartialEq for SeqOrderMap { 85 | fn eq(&self, other: &Self) -> bool { 86 | // explicitly compare items in order 87 | self.map.iter().eq(&other.map) 88 | } 89 | } 90 | 91 | let map = ordermap! { 1 => 2, 3 => 4, -1 => -2, -3 => -4 }; 92 | assert_tokens( 93 | &SeqOrderMap { map }, 94 | &[ 95 | Token::Seq { len: Some(4) }, 96 | Token::Tuple { len: 2 }, 97 | Token::I32(1), 98 | Token::I32(2), 99 | Token::TupleEnd, 100 | Token::Tuple { len: 2 }, 101 | Token::I32(3), 102 | Token::I32(4), 103 | Token::TupleEnd, 104 | Token::Tuple { len: 2 }, 105 | Token::I32(-1), 106 | Token::I32(-2), 107 | Token::TupleEnd, 108 | Token::Tuple { len: 2 }, 109 | Token::I32(-3), 110 | Token::I32(-4), 111 | Token::TupleEnd, 112 | Token::SeqEnd, 113 | ], 114 | ); 115 | } 116 | -------------------------------------------------------------------------------- /tests/equivalent_trait.rs: -------------------------------------------------------------------------------- 1 | use ordermap::ordermap; 2 | use ordermap::Equivalent; 3 | 4 | use std::hash::Hash; 5 | 6 | #[derive(Debug, Hash)] 7 | pub struct Pair(pub A, pub B); 8 | 9 | impl PartialEq<(A, B)> for Pair 10 | where 11 | C: PartialEq, 12 | D: PartialEq, 13 | { 14 | fn eq(&self, rhs: &(A, B)) -> bool { 15 | self.0 == rhs.0 && self.1 == rhs.1 16 | } 17 | } 18 | 19 | impl Equivalent for Pair 20 | where 21 | Pair: PartialEq, 22 | A: Hash + Eq, 23 | B: Hash + Eq, 24 | { 25 | fn equivalent(&self, other: &X) -> bool { 26 | *self == *other 27 | } 28 | } 29 | 30 | #[test] 31 | fn test_lookup() { 32 | let s = String::from; 33 | let map = ordermap! { 34 | (s("a"), s("b")) => 1, 35 | (s("a"), s("x")) => 2, 36 | }; 37 | 38 | assert!(map.contains_key(&Pair("a", "b"))); 39 | assert!(!map.contains_key(&Pair("b", "a"))); 40 | } 41 | 42 | #[test] 43 | fn test_string_str() { 44 | let s = String::from; 45 | let mut map = ordermap! { 46 | s("a") => 1, s("b") => 2, 47 | s("x") => 3, s("y") => 4, 48 | }; 49 | 50 | assert!(map.contains_key("a")); 51 | assert!(!map.contains_key("z")); 52 | assert_eq!(map.swap_remove("b"), Some(2)); 53 | } 54 | -------------------------------------------------------------------------------- /tests/macros_full_path.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn test_create_map() { 3 | let _m = ordermap::ordermap! { 4 | 1 => 2, 5 | 7 => 1, 6 | 2 => 2, 7 | 3 => 3, 8 | }; 9 | } 10 | 11 | #[test] 12 | fn test_create_set() { 13 | let _s = ordermap::orderset! { 14 | 1, 15 | 7, 16 | 2, 17 | 3, 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /tests/quick.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | use ordermap::{OrderMap, OrderSet}; 3 | 4 | use quickcheck::Arbitrary; 5 | use quickcheck::Gen; 6 | use quickcheck::QuickCheck; 7 | use quickcheck::TestResult; 8 | 9 | use fnv::FnvHasher; 10 | use std::hash::{BuildHasher, BuildHasherDefault}; 11 | type FnvBuilder = BuildHasherDefault; 12 | type OrderMapFnv = OrderMap; 13 | 14 | use std::cmp::min; 15 | use std::collections::HashMap; 16 | use std::collections::HashSet; 17 | use std::fmt::Debug; 18 | use std::hash::Hash; 19 | use std::ops::Bound; 20 | use std::ops::Deref; 21 | 22 | use ordermap::map::Entry; 23 | use std::collections::hash_map::Entry as StdEntry; 24 | 25 | fn set<'a, T: 'a, I>(iter: I) -> HashSet 26 | where 27 | I: IntoIterator, 28 | T: Copy + Hash + Eq, 29 | { 30 | iter.into_iter().copied().collect() 31 | } 32 | 33 | fn ordermap<'a, T: 'a, I>(iter: I) -> OrderMap 34 | where 35 | I: IntoIterator, 36 | T: Copy + Hash + Eq, 37 | { 38 | OrderMap::from_iter(iter.into_iter().copied().map(|k| (k, ()))) 39 | } 40 | 41 | // Helper macro to allow us to use smaller quickcheck limits under miri. 42 | macro_rules! quickcheck_limit { 43 | (@as_items $($i:item)*) => ($($i)*); 44 | { 45 | $( 46 | $(#[$m:meta])* 47 | fn $fn_name:ident($($arg_name:ident : $arg_ty:ty),*) -> $ret:ty { 48 | $($code:tt)* 49 | } 50 | )* 51 | } => ( 52 | quickcheck::quickcheck! { 53 | @as_items 54 | $( 55 | #[test] 56 | $(#[$m])* 57 | fn $fn_name() { 58 | fn prop($($arg_name: $arg_ty),*) -> $ret { 59 | $($code)* 60 | } 61 | let mut quickcheck = QuickCheck::new(); 62 | if cfg!(miri) { 63 | quickcheck = quickcheck 64 | .gen(Gen::new(10)) 65 | .tests(10) 66 | .max_tests(100); 67 | } 68 | 69 | quickcheck.quickcheck(prop as fn($($arg_ty),*) -> $ret); 70 | } 71 | )* 72 | } 73 | ) 74 | } 75 | 76 | quickcheck_limit! { 77 | fn contains(insert: Vec) -> bool { 78 | let mut map = OrderMap::new(); 79 | for &key in &insert { 80 | map.insert(key, ()); 81 | } 82 | insert.iter().all(|&key| map.get(&key).is_some()) 83 | } 84 | 85 | fn contains_not(insert: Vec, not: Vec) -> bool { 86 | let mut map = OrderMap::new(); 87 | for &key in &insert { 88 | map.insert(key, ()); 89 | } 90 | let nots = &set(¬) - &set(&insert); 91 | nots.iter().all(|&key| map.get(&key).is_none()) 92 | } 93 | 94 | fn insert_remove(insert: Vec, remove: Vec) -> bool { 95 | let mut map = OrderMap::new(); 96 | for &key in &insert { 97 | map.insert(key, ()); 98 | } 99 | for &key in &remove { 100 | map.swap_remove(&key); 101 | } 102 | let elements = &set(&insert) - &set(&remove); 103 | map.len() == elements.len() && map.iter().count() == elements.len() && 104 | elements.iter().all(|k| map.get(k).is_some()) 105 | } 106 | 107 | fn insertion_order(insert: Vec) -> bool { 108 | let mut map = OrderMap::new(); 109 | for &key in &insert { 110 | map.insert(key, ()); 111 | } 112 | itertools::assert_equal(insert.iter().unique(), map.keys()); 113 | true 114 | } 115 | 116 | fn insert_sorted(insert: Vec<(u32, u32)>) -> bool { 117 | let mut hmap = HashMap::new(); 118 | let mut map = OrderMap::new(); 119 | let mut map2 = OrderMap::new(); 120 | for &(key, value) in &insert { 121 | hmap.insert(key, value); 122 | map.insert_sorted(key, value); 123 | match map2.entry(key) { 124 | Entry::Occupied(e) => *e.into_mut() = value, 125 | Entry::Vacant(e) => { e.insert_sorted(value); } 126 | } 127 | } 128 | itertools::assert_equal(hmap.iter().sorted(), &map); 129 | itertools::assert_equal(&map, &map2); 130 | true 131 | } 132 | 133 | fn pop(insert: Vec) -> bool { 134 | let mut map = OrderMap::new(); 135 | for &key in &insert { 136 | map.insert(key, ()); 137 | } 138 | let mut pops = Vec::new(); 139 | while let Some((key, _v)) = map.pop() { 140 | pops.push(key); 141 | } 142 | pops.reverse(); 143 | 144 | itertools::assert_equal(insert.iter().unique(), &pops); 145 | true 146 | } 147 | 148 | fn with_cap(template: Vec<()>) -> bool { 149 | let cap = template.len(); 150 | let map: OrderMap = OrderMap::with_capacity(cap); 151 | println!("wish: {}, got: {} (diff: {})", cap, map.capacity(), map.capacity() as isize - cap as isize); 152 | map.capacity() >= cap 153 | } 154 | 155 | fn drain_full(insert: Vec) -> bool { 156 | let mut map = OrderMap::new(); 157 | for &key in &insert { 158 | map.insert(key, ()); 159 | } 160 | let mut clone = map.clone(); 161 | let drained = clone.drain(..); 162 | for (key, _) in drained { 163 | map.swap_remove(&key); 164 | } 165 | map.is_empty() 166 | } 167 | 168 | fn drain_bounds(insert: Vec, range: (Bound, Bound)) -> TestResult { 169 | let mut map = OrderMap::new(); 170 | for &key in &insert { 171 | map.insert(key, ()); 172 | } 173 | 174 | // First see if `Vec::drain` is happy with this range. 175 | let result = std::panic::catch_unwind(|| { 176 | let mut keys: Vec = map.keys().copied().collect(); 177 | keys.drain(range); 178 | keys 179 | }); 180 | 181 | if let Ok(keys) = result { 182 | map.drain(range); 183 | // Check that our `drain` matches the same key order. 184 | assert!(map.keys().eq(&keys)); 185 | // Check that hash lookups all work too. 186 | assert!(keys.iter().all(|key| map.contains_key(key))); 187 | TestResult::passed() 188 | } else { 189 | // If `Vec::drain` panicked, so should we. 190 | TestResult::must_fail(move || { map.drain(range); }) 191 | } 192 | } 193 | 194 | // aka shift_remove 195 | fn remove(insert: Vec, remove: Vec) -> bool { 196 | let mut map = OrderMap::new(); 197 | for &key in &insert { 198 | map.insert(key, ()); 199 | } 200 | for &key in &remove { 201 | map.remove(&key); 202 | } 203 | let elements = &set(&insert) - &set(&remove); 204 | 205 | // Check that order is preserved after removals 206 | let mut iter = map.keys(); 207 | for &key in insert.iter().unique() { 208 | if elements.contains(&key) { 209 | assert_eq!(Some(&key), iter.next()); 210 | } 211 | } 212 | 213 | map.len() == elements.len() && map.iter().count() == elements.len() && 214 | elements.iter().all(|k| map.get(k).is_some()) 215 | } 216 | 217 | fn indexing(insert: Vec) -> bool { 218 | let mut map: OrderMap<_, _> = insert.into_iter().map(|x| (x, x)).collect(); 219 | let set: OrderSet<_> = map.keys().copied().collect(); 220 | assert_eq!(map.len(), set.len()); 221 | 222 | for (i, &key) in set.iter().enumerate() { 223 | assert_eq!(map.get_index(i), Some((&key, &key))); 224 | assert_eq!(set.get_index(i), Some(&key)); 225 | assert_eq!(map[i], key); 226 | assert_eq!(set[i], key); 227 | 228 | *map.get_index_mut(i).unwrap().1 >>= 1; 229 | map[i] <<= 1; 230 | } 231 | 232 | set.iter().enumerate().all(|(i, &key)| { 233 | let value = key & !1; 234 | map[&key] == value && map[i] == value 235 | }) 236 | } 237 | 238 | // Use `u8` test indices so quickcheck is less likely to go out of bounds. 239 | fn set_swap_indices(vec: Vec, a: u8, b: u8) -> TestResult { 240 | let mut set = OrderSet::::from_iter(vec); 241 | let a = usize::from(a); 242 | let b = usize::from(b); 243 | 244 | if a >= set.len() || b >= set.len() { 245 | return TestResult::discard(); 246 | } 247 | 248 | let mut vec = Vec::from_iter(set.iter().cloned()); 249 | vec.swap(a, b); 250 | 251 | set.swap_indices(a, b); 252 | 253 | // Check both iteration order and hash lookups 254 | assert!(set.iter().eq(vec.iter())); 255 | assert!(vec.iter().enumerate().all(|(i, x)| { 256 | set.get_index_of(x) == Some(i) 257 | })); 258 | TestResult::passed() 259 | } 260 | 261 | fn map_swap_indices(vec: Vec, from: u8, to: u8) -> TestResult { 262 | test_map_swap_indices(vec, from, to, OrderMap::swap_indices) 263 | } 264 | 265 | fn occupied_entry_swap_indices(vec: Vec, from: u8, to: u8) -> TestResult { 266 | test_map_swap_indices(vec, from, to, |map, from, to| { 267 | let key = map.keys()[from]; 268 | match map.entry(key) { 269 | Entry::Occupied(entry) => entry.swap_indices(to), 270 | _ => unreachable!(), 271 | } 272 | }) 273 | } 274 | 275 | fn indexed_entry_swap_indices(vec: Vec, from: u8, to: u8) -> TestResult { 276 | test_map_swap_indices(vec, from, to, |map, from, to| { 277 | map.get_index_entry(from).unwrap().swap_indices(to); 278 | }) 279 | } 280 | 281 | fn raw_occupied_entry_swap_indices(vec: Vec, from: u8, to: u8) -> TestResult { 282 | use ordermap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut}; 283 | test_map_swap_indices(vec, from, to, |map, from, to| { 284 | let key = map.keys()[from]; 285 | match map.raw_entry_mut_v1().from_key(&key) { 286 | RawEntryMut::Occupied(entry) => entry.swap_indices(to), 287 | _ => unreachable!(), 288 | } 289 | }) 290 | } 291 | 292 | // Use `u8` test indices so quickcheck is less likely to go out of bounds. 293 | fn set_move_index(vec: Vec, from: u8, to: u8) -> TestResult { 294 | let mut set = OrderSet::::from_iter(vec); 295 | let from = usize::from(from); 296 | let to = usize::from(to); 297 | 298 | if from >= set.len() || to >= set.len() { 299 | return TestResult::discard(); 300 | } 301 | 302 | let mut vec = Vec::from_iter(set.iter().cloned()); 303 | let x = vec.remove(from); 304 | vec.insert(to, x); 305 | 306 | set.move_index(from, to); 307 | 308 | // Check both iteration order and hash lookups 309 | assert!(set.iter().eq(vec.iter())); 310 | assert!(vec.iter().enumerate().all(|(i, x)| { 311 | set.get_index_of(x) == Some(i) 312 | })); 313 | TestResult::passed() 314 | } 315 | 316 | fn map_move_index(vec: Vec, from: u8, to: u8) -> TestResult { 317 | test_map_move_index(vec, from, to, OrderMap::move_index) 318 | } 319 | 320 | fn occupied_entry_move_index(vec: Vec, from: u8, to: u8) -> TestResult { 321 | test_map_move_index(vec, from, to, |map, from, to| { 322 | let key = map.keys()[from]; 323 | match map.entry(key) { 324 | Entry::Occupied(entry) => entry.move_index(to), 325 | _ => unreachable!(), 326 | } 327 | }) 328 | } 329 | 330 | fn indexed_entry_move_index(vec: Vec, from: u8, to: u8) -> TestResult { 331 | test_map_move_index(vec, from, to, |map, from, to| { 332 | map.get_index_entry(from).unwrap().move_index(to); 333 | }) 334 | } 335 | 336 | fn raw_occupied_entry_move_index(vec: Vec, from: u8, to: u8) -> TestResult { 337 | use ordermap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut}; 338 | test_map_move_index(vec, from, to, |map, from, to| { 339 | let key = map.keys()[from]; 340 | match map.raw_entry_mut_v1().from_key(&key) { 341 | RawEntryMut::Occupied(entry) => entry.move_index(to), 342 | _ => unreachable!(), 343 | } 344 | }) 345 | } 346 | 347 | fn occupied_entry_shift_insert(vec: Vec, i: u8) -> TestResult { 348 | test_map_shift_insert(vec, i, |map, i, key| { 349 | match map.entry(key) { 350 | Entry::Vacant(entry) => entry.shift_insert(i, ()), 351 | _ => unreachable!(), 352 | }; 353 | }) 354 | } 355 | 356 | fn raw_occupied_entry_shift_insert(vec: Vec, i: u8) -> TestResult { 357 | use ordermap::map::raw_entry_v1::{RawEntryApiV1, RawEntryMut}; 358 | test_map_shift_insert(vec, i, |map, i, key| { 359 | match map.raw_entry_mut_v1().from_key(&key) { 360 | RawEntryMut::Vacant(entry) => entry.shift_insert(i, key, ()), 361 | _ => unreachable!(), 362 | }; 363 | }) 364 | } 365 | } 366 | 367 | fn test_map_swap_indices(vec: Vec, a: u8, b: u8, swap_indices: F) -> TestResult 368 | where 369 | F: FnOnce(&mut OrderMap, usize, usize), 370 | { 371 | let mut map = OrderMap::::from_iter(vec.into_iter().map(|k| (k, ()))); 372 | let a = usize::from(a); 373 | let b = usize::from(b); 374 | 375 | if a >= map.len() || b >= map.len() { 376 | return TestResult::discard(); 377 | } 378 | 379 | let mut vec = Vec::from_iter(map.keys().copied()); 380 | vec.swap(a, b); 381 | 382 | swap_indices(&mut map, a, b); 383 | 384 | // Check both iteration order and hash lookups 385 | assert!(map.keys().eq(vec.iter())); 386 | assert!(vec 387 | .iter() 388 | .enumerate() 389 | .all(|(i, x)| { map.get_index_of(x) == Some(i) })); 390 | TestResult::passed() 391 | } 392 | 393 | fn test_map_move_index(vec: Vec, from: u8, to: u8, move_index: F) -> TestResult 394 | where 395 | F: FnOnce(&mut OrderMap, usize, usize), 396 | { 397 | let mut map = OrderMap::::from_iter(vec.into_iter().map(|k| (k, ()))); 398 | let from = usize::from(from); 399 | let to = usize::from(to); 400 | 401 | if from >= map.len() || to >= map.len() { 402 | return TestResult::discard(); 403 | } 404 | 405 | let mut vec = Vec::from_iter(map.keys().copied()); 406 | let x = vec.remove(from); 407 | vec.insert(to, x); 408 | 409 | move_index(&mut map, from, to); 410 | 411 | // Check both iteration order and hash lookups 412 | assert!(map.keys().eq(vec.iter())); 413 | assert!(vec 414 | .iter() 415 | .enumerate() 416 | .all(|(i, x)| { map.get_index_of(x) == Some(i) })); 417 | TestResult::passed() 418 | } 419 | 420 | fn test_map_shift_insert(vec: Vec, i: u8, shift_insert: F) -> TestResult 421 | where 422 | F: FnOnce(&mut OrderMap, usize, u8), 423 | { 424 | let mut map = OrderMap::::from_iter(vec.into_iter().map(|k| (k, ()))); 425 | let i = usize::from(i); 426 | if i >= map.len() { 427 | return TestResult::discard(); 428 | } 429 | 430 | let mut vec = Vec::from_iter(map.keys().copied()); 431 | let x = vec.pop().unwrap(); 432 | vec.insert(i, x); 433 | 434 | let (last, ()) = map.pop().unwrap(); 435 | assert_eq!(x, last); 436 | map.shrink_to_fit(); // so we might have to grow and rehash the table 437 | 438 | shift_insert(&mut map, i, last); 439 | 440 | // Check both iteration order and hash lookups 441 | assert!(map.keys().eq(vec.iter())); 442 | assert!(vec 443 | .iter() 444 | .enumerate() 445 | .all(|(i, x)| { map.get_index_of(x) == Some(i) })); 446 | TestResult::passed() 447 | } 448 | 449 | use crate::Op::*; 450 | #[derive(Copy, Clone, Debug)] 451 | enum Op { 452 | Add(K, V), 453 | Remove(K), 454 | AddEntry(K, V), 455 | RemoveEntry(K), 456 | } 457 | 458 | impl Arbitrary for Op 459 | where 460 | K: Arbitrary, 461 | V: Arbitrary, 462 | { 463 | fn arbitrary(g: &mut Gen) -> Self { 464 | match u32::arbitrary(g) % 4 { 465 | 0 => Add(K::arbitrary(g), V::arbitrary(g)), 466 | 1 => AddEntry(K::arbitrary(g), V::arbitrary(g)), 467 | 2 => Remove(K::arbitrary(g)), 468 | _ => RemoveEntry(K::arbitrary(g)), 469 | } 470 | } 471 | } 472 | 473 | fn do_ops(ops: &[Op], a: &mut OrderMap, b: &mut HashMap) 474 | where 475 | K: Hash + Eq + Clone, 476 | V: Clone, 477 | S: BuildHasher, 478 | { 479 | for op in ops { 480 | match *op { 481 | Add(ref k, ref v) => { 482 | a.insert(k.clone(), v.clone()); 483 | b.insert(k.clone(), v.clone()); 484 | } 485 | AddEntry(ref k, ref v) => { 486 | a.entry(k.clone()).or_insert_with(|| v.clone()); 487 | b.entry(k.clone()).or_insert_with(|| v.clone()); 488 | } 489 | Remove(ref k) => { 490 | a.swap_remove(k); 491 | b.remove(k); 492 | } 493 | RemoveEntry(ref k) => { 494 | if let Entry::Occupied(ent) = a.entry(k.clone()) { 495 | ent.swap_remove_entry(); 496 | } 497 | if let StdEntry::Occupied(ent) = b.entry(k.clone()) { 498 | ent.remove_entry(); 499 | } 500 | } 501 | } 502 | //println!("{:?}", a); 503 | } 504 | } 505 | 506 | fn assert_maps_equivalent(a: &OrderMap, b: &HashMap) -> bool 507 | where 508 | K: Hash + Eq + Debug, 509 | V: Eq + Debug, 510 | { 511 | assert_eq!(a.len(), b.len()); 512 | assert_eq!(a.iter().next().is_some(), b.iter().next().is_some()); 513 | for key in a.keys() { 514 | assert!(b.contains_key(key), "b does not contain {:?}", key); 515 | } 516 | for key in b.keys() { 517 | assert!(a.get(key).is_some(), "a does not contain {:?}", key); 518 | } 519 | for key in a.keys() { 520 | assert_eq!(a[key], b[key]); 521 | } 522 | true 523 | } 524 | 525 | quickcheck_limit! { 526 | fn operations_i8(ops: Large>>) -> bool { 527 | let mut map = OrderMap::new(); 528 | let mut reference = HashMap::new(); 529 | do_ops(&ops, &mut map, &mut reference); 530 | assert_maps_equivalent(&map, &reference) 531 | } 532 | 533 | fn operations_string(ops: Vec>) -> bool { 534 | let mut map = OrderMap::new(); 535 | let mut reference = HashMap::new(); 536 | do_ops(&ops, &mut map, &mut reference); 537 | assert_maps_equivalent(&map, &reference) 538 | } 539 | 540 | fn keys_values(ops: Large>>) -> bool { 541 | let mut map = OrderMap::new(); 542 | let mut reference = HashMap::new(); 543 | do_ops(&ops, &mut map, &mut reference); 544 | let mut visit = OrderMap::new(); 545 | for (k, v) in map.keys().zip(map.values()) { 546 | assert_eq!(&map[k], v); 547 | assert!(!visit.contains_key(k)); 548 | visit.insert(*k, *v); 549 | } 550 | assert_eq!(visit.len(), reference.len()); 551 | true 552 | } 553 | 554 | fn keys_values_mut(ops: Large>>) -> bool { 555 | let mut map = OrderMap::new(); 556 | let mut reference = HashMap::new(); 557 | do_ops(&ops, &mut map, &mut reference); 558 | let mut visit = OrderMap::new(); 559 | let keys = Vec::from_iter(map.keys().copied()); 560 | for (k, v) in keys.iter().zip(map.values_mut()) { 561 | assert_eq!(&reference[k], v); 562 | assert!(!visit.contains_key(k)); 563 | visit.insert(*k, *v); 564 | } 565 | assert_eq!(visit.len(), reference.len()); 566 | true 567 | } 568 | 569 | fn equality(ops1: Vec>, removes: Vec) -> bool { 570 | let mut map = OrderMap::new(); 571 | let mut reference = HashMap::new(); 572 | do_ops(&ops1, &mut map, &mut reference); 573 | let mut ops2 = ops1.clone(); 574 | for &r in &removes { 575 | if !ops2.is_empty() { 576 | let i = r % ops2.len(); 577 | ops2.remove(i); 578 | } 579 | } 580 | let mut map2 = OrderMapFnv::default(); 581 | let mut reference2 = HashMap::new(); 582 | do_ops(&ops2, &mut map2, &mut reference2); 583 | 584 | map.sort_keys(); 585 | map2.sort_keys(); 586 | assert_eq!(map == map2, reference == reference2); 587 | true 588 | } 589 | 590 | fn retain_ordered(keys: Large>, remove: Large>) -> () { 591 | let mut map = ordermap(keys.iter()); 592 | let initial_map = map.clone(); // deduplicated in-order input 593 | let remove_map = ordermap(remove.iter()); 594 | let keys_s = set(keys.iter()); 595 | let remove_s = set(remove.iter()); 596 | let answer = &keys_s - &remove_s; 597 | map.retain(|k, _| !remove_map.contains_key(k)); 598 | 599 | // check the values 600 | assert_eq!(map.len(), answer.len()); 601 | for key in &answer { 602 | assert!(map.contains_key(key)); 603 | } 604 | // check the order 605 | itertools::assert_equal(map.keys(), initial_map.keys().filter(|&k| !remove_map.contains_key(k))); 606 | } 607 | 608 | fn sort_1(keyvals: Large>) -> () { 609 | let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec()); 610 | let mut answer = keyvals.0; 611 | answer.sort_by_key(|t| t.0); 612 | 613 | // reverse dedup: Because OrderMap::from_iter keeps the last value for 614 | // identical keys 615 | answer.reverse(); 616 | answer.dedup_by_key(|t| t.0); 617 | answer.reverse(); 618 | 619 | map.sort_by(|k1, _, k2, _| Ord::cmp(k1, k2)); 620 | 621 | // check it contains all the values it should 622 | for &(key, val) in &answer { 623 | assert_eq!(map[&key], val); 624 | } 625 | 626 | // check the order 627 | 628 | let mapv = Vec::from_iter(map); 629 | assert_eq!(answer, mapv); 630 | 631 | } 632 | 633 | fn sort_2(keyvals: Large>) -> () { 634 | let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec()); 635 | map.sort_by(|_, v1, _, v2| Ord::cmp(v1, v2)); 636 | assert_sorted_by_key(map, |t| t.1); 637 | } 638 | 639 | fn sort_3(keyvals: Large>) -> () { 640 | let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec()); 641 | map.sort_by_cached_key(|&k, _| std::cmp::Reverse(k)); 642 | assert_sorted_by_key(map, |t| std::cmp::Reverse(t.0)); 643 | } 644 | 645 | fn reverse(keyvals: Large>) -> () { 646 | let mut map: OrderMap<_, _> = OrderMap::from_iter(keyvals.to_vec()); 647 | 648 | fn generate_answer(input: &Vec<(i8, i8)>) -> Vec<(i8, i8)> { 649 | // to mimic what `OrderMap::from_iter` does: 650 | // need to get (A) the unique keys in forward order, and (B) the 651 | // last value of each of those keys. 652 | 653 | // create (A): an iterable that yields the unique keys in ltr order 654 | let mut seen_keys = HashSet::new(); 655 | let unique_keys_forward = input.iter().filter_map(move |(k, _)| { 656 | if seen_keys.contains(k) { None } 657 | else { seen_keys.insert(*k); Some(*k) } 658 | }); 659 | 660 | // create (B): a mapping of keys to the last value seen for that key 661 | // this is the same as reversing the input and taking the first 662 | // value seen for that key! 663 | let mut last_val_per_key = HashMap::new(); 664 | for &(k, v) in input.iter().rev() { 665 | if !last_val_per_key.contains_key(&k) { 666 | last_val_per_key.insert(k, v); 667 | } 668 | } 669 | 670 | // iterate over the keys in (A) in order, and match each one with 671 | // the corresponding last value from (B) 672 | let mut ans: Vec<_> = unique_keys_forward 673 | .map(|k| (k, *last_val_per_key.get(&k).unwrap())) 674 | .collect(); 675 | 676 | // finally, since this test is testing `.reverse()`, reverse the 677 | // answer in-place 678 | ans.reverse(); 679 | 680 | ans 681 | } 682 | 683 | let answer = generate_answer(&keyvals.0); 684 | 685 | // perform the work 686 | map.reverse(); 687 | 688 | // check it contains all the values it should 689 | for &(key, val) in &answer { 690 | assert_eq!(map[&key], val); 691 | } 692 | 693 | // check the order 694 | let mapv = Vec::from_iter(map); 695 | assert_eq!(answer, mapv); 696 | } 697 | } 698 | 699 | fn assert_sorted_by_key(iterable: I, key: Key) 700 | where 701 | I: IntoIterator, 702 | I::Item: Ord + Clone + Debug, 703 | Key: Fn(&I::Item) -> X, 704 | X: Ord, 705 | { 706 | let input = Vec::from_iter(iterable); 707 | let mut sorted = input.clone(); 708 | sorted.sort_by_key(key); 709 | assert_eq!(input, sorted); 710 | } 711 | 712 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] 713 | struct Alpha(String); 714 | 715 | impl Deref for Alpha { 716 | type Target = String; 717 | fn deref(&self) -> &String { 718 | &self.0 719 | } 720 | } 721 | 722 | const ALPHABET: &[u8] = b"abcdefghijklmnopqrstuvwxyz"; 723 | 724 | impl Arbitrary for Alpha { 725 | fn arbitrary(g: &mut Gen) -> Self { 726 | let len = usize::arbitrary(g) % g.size(); 727 | let len = min(len, 16); 728 | Alpha( 729 | (0..len) 730 | .map(|_| ALPHABET[usize::arbitrary(g) % ALPHABET.len()] as char) 731 | .collect(), 732 | ) 733 | } 734 | 735 | fn shrink(&self) -> Box> { 736 | Box::new((**self).shrink().map(Alpha)) 737 | } 738 | } 739 | 740 | /// quickcheck Arbitrary adaptor -- make a larger vec 741 | #[derive(Clone, Debug)] 742 | struct Large(T); 743 | 744 | impl Deref for Large { 745 | type Target = T; 746 | fn deref(&self) -> &T { 747 | &self.0 748 | } 749 | } 750 | 751 | impl Arbitrary for Large> 752 | where 753 | T: Arbitrary, 754 | { 755 | fn arbitrary(g: &mut Gen) -> Self { 756 | let len = usize::arbitrary(g) % (g.size() * 10); 757 | Large((0..len).map(|_| T::arbitrary(g)).collect()) 758 | } 759 | 760 | fn shrink(&self) -> Box> { 761 | Box::new((**self).shrink().map(Large)) 762 | } 763 | } 764 | -------------------------------------------------------------------------------- /tests/tests.rs: -------------------------------------------------------------------------------- 1 | use ordermap::{ordermap, orderset}; 2 | 3 | #[test] 4 | fn test_sort() { 5 | let m = ordermap! { 6 | 1 => 2, 7 | 7 => 1, 8 | 2 => 2, 9 | 3 => 3, 10 | }; 11 | 12 | itertools::assert_equal( 13 | m.sorted_by(|_k1, v1, _k2, v2| v1.cmp(v2)), 14 | vec![(7, 1), (1, 2), (2, 2), (3, 3)], 15 | ); 16 | } 17 | 18 | #[test] 19 | fn test_sort_set() { 20 | let s = orderset! { 21 | 1, 22 | 7, 23 | 2, 24 | 3, 25 | }; 26 | 27 | itertools::assert_equal(s.sorted_by(|v1, v2| v1.cmp(v2)), vec![1, 2, 3, 7]); 28 | } 29 | --------------------------------------------------------------------------------