├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.fuzz.md ├── README.md ├── benches └── benches.rs ├── bors.toml ├── examples └── roster.rs ├── fuzz ├── .gitignore ├── Cargo.toml └── fuzz_targets │ ├── rangemap_coalesce.rs │ ├── rangemap_gaps.rs │ ├── rangemap_inclusive_coalesce.rs │ └── rangemap_inclusive_gaps.rs ├── pre_commit.sh └── src ├── dense.rs ├── inclusive_map.rs ├── inclusive_set.rs ├── lib.rs ├── map.rs ├── operations.rs ├── range_wrapper.rs ├── readme.rs ├── set.rs └── std_ext.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main, staging, trying] 6 | pull_request: 7 | branches: [main] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | test: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | toolchain: 18 | # Don't forget to update the README when bumping MSRV. 19 | - 1.66.0 20 | - stable 21 | - beta 22 | - nightly 23 | os: 24 | - ubuntu-latest 25 | - macos-latest 26 | - windows-latest 27 | steps: 28 | - name: checkout 29 | uses: actions/checkout@v2 30 | - name: install toolchain 31 | uses: actions-rs/toolchain@v1 32 | with: 33 | toolchain: ${{ matrix.toolchain }} 34 | default: true 35 | profile: minimal 36 | - name: stable test without serde 37 | uses: actions-rs/cargo@v1 38 | if: matrix.toolchain != 'nightly' 39 | with: 40 | command: test 41 | # We just need to make sure we haven't broken it in some obvious way 42 | # either with or without serde enabled, so only test with serde on stable. 43 | - name: stable test with serde 44 | uses: actions-rs/cargo@v1 45 | if: matrix.toolchain == 'stable' 46 | with: 47 | command: test 48 | args: --features serde1 49 | # Make sure we haven't broken the const_fn feature. 50 | - name: stable test with const_fn 51 | uses: actions-rs/cargo@v1 52 | if: matrix.toolchain == 'stable' 53 | with: 54 | command: test 55 | args: --features const_fn 56 | - name: nightly test 57 | uses: actions-rs/cargo@v1 58 | if: matrix.toolchain == 'nightly' 59 | with: 60 | command: test 61 | args: --features nightly 62 | ci-success: 63 | name: ci 64 | if: ${{ success() }} 65 | needs: 66 | - test 67 | runs-on: ubuntu-20.04 68 | steps: 69 | - name: CI succeeded 70 | run: exit 0 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### v1.6.0 (unreleased) 2 | 3 | - **Features**: 4 | - Add quickcheck support, gated behind the `quickcheck` feature. 5 | - Improve performance of `RangeMap::gaps` by efficiently seeking to the start of the query range. 6 | 7 | 8 | ### v1.5.1 (2024-02-27) 9 | 10 | - **Fixes**: 11 | - Relax bounds on `Default` implementation for all map and set types. Requiring `K: Default` and `V: Default` was accidentally introduced in v1.5.0. 12 | 13 | 14 | ### v1.5.0 (2024-02-09) "xfbs rampage edition" 15 | 16 | Huge thanks to [xfbs](https://github.com/xfbs), who did pretty much all the work you see in the changelog below! 💖 17 | 18 | - **Features**: 19 | - Add `union` and `intersection` methods to iterate over the union or intersection of two sets. 20 | - Add `first_range_value` and `last_range_value` methods to map types and `first` and `last` methods to set types. 21 | - Add literal macros for all collection types — e.g. `range_set![0..100, 200..300, 400..500]`. 22 | - Implement `Default` and `Hash` for all collection types. 23 | - Implement `DoubleEndedIterator` for all iterators. 24 | - Implement `From<[_; N]>` (e.g. `From<[Range; N]> for RangeSet`) for all collections. (Previously you could build a collection from an iterator, but not directly from an array.) 25 | - Implement `BitOr` and `BitAnd` for set types. (Convenience wrapper around the `union` and `intersection` methods mentioned above.) 26 | - Accept any `R: Borrow>` as argument to `overlapping` methods, allowing it to take ranges by value. 27 | 28 | - **Changes**: 29 | - Bump minimum supported Rust version to 1.66.0 (released 2022-12-15). This is to gain access to `BTreeMap::first_key_value` and `BTreeMap::last_key_value`, and for compatibility with new versions of some of rangemap's test dependencies. 30 | 31 | - **Internal**: 32 | - New benchmarks and improved test coverage. 33 | 34 | ### v1.4.0 (2023-09-19) 35 | 36 | - **Changes**: 37 | - Bump minimum supported Rust version to 1.61.0 (released 2022-05-19). This is for compatibility with new versions of some of rangemap's test dependencies. 38 | 39 | 40 | ### v1.3.1 (2023-09-19) 41 | 42 | - **Fixes**: 43 | - Fix `PartialEq`, `PartialOrd`, and `Ord` implementations for `RangeMap` (and `RangeSet`). These previously only compared the starts of ranges instead of the entire range. Thanks to https://github.com/hecrj for finding and fixing this! 44 | - **Changes**: 45 | - Minimum supported Rust version for running this crate's tests has increased to 1.61.0 due to a corresponding MSRV bump in a test dependency. This is causing CI builds to fail against rustc 1.56.1, but should not affect consumers of the crate. The next minor release (1.4.0) will bump the minimum supported Rust version of rangemap itself. 46 | 47 | 48 | ### v1.3.0 (2023-01-03) 49 | 50 | - **Features**: 51 | - Add `overlapping` method to all collection types, which returns an iterator over all stored entries that completely or partially overlap a given range. 52 | - Add `overlaps` convenience method to all collection types, which returns whether any stored range completely or partially overlaps a given range. 53 | - Credit to [Rua](https://github.com/Rua) for the original implementation of these new methods. (Unfortunately I couldn't use their code directly because I made other incompatible changes.) Thanks also to [rumpuslabs](https://github.com/rumpuslabs) for their engagement. 54 | 55 | 56 | ### v1.2.0 (2022-12-27) 57 | 58 | - **Features**: 59 | - Add `clear`, `len`, and `is_empty` methods for all map and set types. 60 | - **Fixes**: 61 | - Make `const_fn` feature work again. (Previous release accidentally broke the const versions of `RangeMap::new` and `RangeSet::new`.) 62 | 63 | 64 | ### v1.1.0 (2022-11-12) 65 | 66 | - **Features**: 67 | - Implement `PartialEq`, `Eq`, `PartialOrd`, and `Ord` for all map and set types. 68 | - Make `new` functions for all map and set types `const` when `const_fn` feature is enabled. 69 | - **Changes**: 70 | - Bump minimum supported Rust version to 1.56.1. (Released a year ago.) This is for compatibility with new versions of some of rangemap's development dependencies. 71 | 72 | 73 | ### v1.0.3 (2022-06-11) 74 | 75 | - **Fixes**: 76 | - Fix `Gaps` iterator for `RangeMap` yielding an empty gap for an empty outer range. Simplified gaps logic and expanded fuzz testing to better cover this and similar cases. 77 | 78 | 79 | ### v1.0.2 (2022-05-17) 80 | 81 | - **Fixes**: 82 | - Fix empty gaps returned by `Gaps` iterator for `RangeInclusiveMap`. Added fuzz tests for `Gaps` iterators. 83 | 84 | 85 | ### v1.0.1 (2022-01-29) 86 | 87 | - **Fixes**: 88 | - Fix empty gaps returned by `Gaps` iterator for `RangeMap`, and incorrect gaps returned by `Gaps` iterator for `RangeInclusiveMap`. 89 | 90 | 91 | ### v1.0.0 (2022-01-28) 92 | 93 | It's time. (No functional change.) 94 | 95 | 96 | ### v0.1.14 (2021-11-16) 97 | 98 | - **Features**: 99 | - Expose nameable types for iterators: `Iterator`, `IntoIterator`, `Gaps` (for each collection type). 100 | - **Changes**: 101 | - Document overflow behaviour required by implementors of `StepLite` and `StepFns`. 102 | 103 | 104 | ### v0.1.13 (2021-08-25) 105 | 106 | - **Features**: 107 | - Add serde support. 108 | 109 | 110 | ### v0.1.12 (2021-08-23) 111 | 112 | - **Features**: 113 | - Implement more traits for all map and set types: `IntoIter`, `FromIter`, and `Extend`. 114 | - **Changes**: 115 | - Bump minimum supported Rust version to 1.46. 116 | 117 | 118 | ### v0.1.11 (2021-06-30) "EOFY edition" 119 | 120 | - **Features**: 121 | - Support `no_std` environments. 122 | - **Changes**: 123 | - Update all dev-dependencies to latest versions. 124 | 125 | 126 | ### v0.1.10 (2021-02-23) 127 | 128 | - **Fixes**: 129 | - Fix performance regression introduced in v0.1.9, which made inserts extremely slow for large maps. 130 | 131 | 132 | ### v0.1.9 (2021-02-23) 133 | 134 | - **Fixes**: 135 | - Fix coalescing of contiguous ranges. In some cases `RangeMap` and `RangeInclusiveMap` would leave two separate contiguous ranges with the same value instead of combining them into one. 136 | 137 | 138 | ### v0.1.8 (2020-11-22) 139 | 140 | - **Features**: 141 | - Implement `Debug` for all map and set types. 142 | 143 | 144 | ### v0.1.7 (2020-09-07) 145 | 146 | - **Features**: 147 | - Add `gaps` method to all map and set types for iterating over sub-ranges of a given outer range that are not covered by any stored range. 148 | 149 | 150 | ### v0.1.6 (2020-07-15) 151 | 152 | - **Features**: 153 | - Add `RangeInclusiveMap` and `RangeInclusiveSet` types for storing closed ranges. 154 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rangemap" 3 | version = "1.6.0" 4 | authors = ["Jeff Parsons "] 5 | edition = "2018" 6 | license = "MIT/Apache-2.0" 7 | readme = "README.md" 8 | repository = "https://github.com/jeffparsons/rangemap" 9 | documentation = "https://docs.rs/rangemap" 10 | homepage = "https://github.com/jeffparsons/rangemap" 11 | description = """ 12 | Map and set data structures whose keys are stored as ranges. 13 | 14 | Contiguous and overlapping ranges that map to the same value are coalesced into a single range. 15 | """ 16 | categories = ["data-structures"] 17 | rust-version = "1.66.0" 18 | 19 | [dependencies] 20 | quickcheck = { version = "1.0.3", optional = true } 21 | serde = { version = "1", optional = true } 22 | 23 | [dev-dependencies] 24 | permutator = "0.4" 25 | # Criterion bumps its MSRV in 0.3.6; it is probably reasonable 26 | # to update rangemap's MSRV, too, but until I actually publish 27 | # a policy on that I'm going to avoid doing a big bump right now. 28 | # (Later problem!) 29 | criterion = "= 0.3.5" 30 | rand = "0.8" 31 | chrono = "0.4" # For examples 32 | rustc_version = "0.4" 33 | serde_json = "1" 34 | proptest = "1.4.0" 35 | test-strategy = "0.3.1" 36 | 37 | [features] 38 | serde1 = ["serde"] 39 | # So we can run doc tests from "README.md". 40 | nightly = [] 41 | # Enables `RangeMap::new()`, `RangeInclusiveMap::new()`, `RangeSet::new()`, 42 | # and `RangeInclusiveSet::new()` to be const functions. 43 | # Requires a nightly compiler because `const_btree_new` is an unstable feature, 44 | # but is soon to be stabilized: 45 | const_fn = [] 46 | quickcheck = ["dep:quickcheck"] 47 | 48 | [[bench]] 49 | name = "benches" 50 | harness = false 51 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | Copyright 2019-2022 Jeff Parsons, and [contributors](https://github.com/jeffparsons/rangemap/contributors) 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2019 Jeffrey Parsons 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.fuzz.md: -------------------------------------------------------------------------------- 1 | # rangemap fuzz tests 2 | 3 | These fuzz tests use the [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz) tool. 4 | 5 | Run one of these: 6 | 7 | ``` 8 | cargo +nightly fuzz run rangemap_coalesce 9 | cargo +nightly fuzz run rangemap_inclusive_coalesce 10 | cargo +nightly fuzz run rangemap_gaps 11 | cargo +nightly fuzz run rangemap_inclusive_gaps 12 | ``` 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rangemap 2 | 3 | [![Crate](https://img.shields.io/crates/v/rangemap.svg)](https://crates.io/crates/rangemap) 4 | [![Docs](https://docs.rs/rangemap/badge.svg)](https://docs.rs/rangemap) 5 | [![Build status](https://github.com/jeffparsons/rangemap/workflows/CI/badge.svg)](https://github.com/jeffparsons/rangemap/actions) 6 | [![Rust](https://img.shields.io/badge/rust-1.66.0%2B-blue.svg?maxAge=3600)](https://github.com/jeffparsons/rangemap) 7 | 8 | [`RangeMap`] and [`RangeInclusiveMap`] are map data structures whose keys 9 | are stored as ranges. Contiguous and overlapping ranges that map to the same 10 | value are coalesced into a single range. 11 | 12 | Corresponding [`RangeSet`] and [`RangeInclusiveSet`] structures are also provided. 13 | 14 | 15 | ## Different kinds of ranges 16 | 17 | `RangeMap` and `RangeInclusiveMap` correspond to the [`Range`] 18 | and [`RangeInclusive`] types from the standard library respectively. 19 | For some applications the choice of range type may be obvious, 20 | or even be dictated by pre-existing design decisions. For other applications 21 | the choice may seem arbitrary, and be guided instead by convenience or 22 | aesthetic preference. 23 | 24 | If the choice is not obvious in your case, consider these differences: 25 | 26 | - If your key type `K` represents points on a continuum (e.g. `f64`), 27 | and the choice of which of two adjacent ranges "owns" the value 28 | where they touch is largely arbitrary, then it may be more natural 29 | to work with half-open `Range`s like `0.0..1.0` and `1.0..2.0`. If you 30 | were to use closed `RangeInclusive`s here instead, then to represent two such adjacent 31 | ranges you would need to subtract some infinitesimal (which may depend, 32 | as it does in the case of `f64`, on the specific value of `K`) 33 | from the end of the earlier range. (See the last point below for more 34 | on this problem.) 35 | - If you need to represent ranges that _include_ the maximum 36 | value in the key domain (e.g. `255u8`) then you will 37 | probably want to use `RangeInclusive`s like `128u8..=255u8`. Sometimes 38 | it may be possible to instead work around this by using a wider key 39 | type than the values you are actually trying to represent (`K=u16` 40 | even though you are only trying to represent ranges covering `u8`) 41 | but in these cases the key domain often represents discrete objects 42 | rather than points on a continuum, and so `RangeInclusive` may 43 | be a more natural way to express these ranges anyway. 44 | - If you are using `RangeInclusive`, then it must be possible to define 45 | _successor_ and _predecessor_ functions for your key type `K`, 46 | because adjacent ranges can not be detected (and thereby coalesced) 47 | simply by testing their ends for equality. For key types that represent 48 | points on a continuum, defining these functions may be awkward and error-prone. 49 | For key types that represent discrete objects, this is usually much 50 | more straightforward. 51 | 52 | 53 | ## Example: use with Chrono 54 | 55 | ```rust 56 | use chrono::offset::TimeZone; 57 | use chrono::{Duration, Utc}; 58 | use rangemap::RangeMap; 59 | 60 | fn main() { 61 | let people = ["Alice", "Bob", "Carol"]; 62 | let mut roster = RangeMap::new(); 63 | 64 | // Set up initial roster. 65 | let start_of_roster = Utc.ymd(2019, 1, 7); 66 | let mut week_start = start_of_roster; 67 | for _ in 0..3 { 68 | for person in &people { 69 | let next_week = week_start + Duration::weeks(1); 70 | roster.insert(week_start..next_week, person); 71 | week_start = next_week; 72 | } 73 | } 74 | 75 | // Bob is covering Alice's second shift (the fourth shift overall). 76 | let fourth_shift_start = start_of_roster + Duration::weeks(3); 77 | let fourth_shift_end = fourth_shift_start + Duration::weeks(1); 78 | roster.insert(fourth_shift_start..fourth_shift_end, &"Bob"); 79 | 80 | for (range, person) in roster.iter() { 81 | println!("{} ({}): {}", range.start, range.end - range.start, person); 82 | } 83 | 84 | // Output: 85 | // 2019-01-07UTC (P7D): Alice 86 | // 2019-01-14UTC (P7D): Bob 87 | // 2019-01-21UTC (P7D): Carol 88 | // 2019-01-28UTC (P14D): Bob 89 | // 2019-02-11UTC (P7D): Carol 90 | // 2019-02-18UTC (P7D): Alice 91 | // 2019-02-25UTC (P7D): Bob 92 | // 2019-03-04UTC (P7D): Carol 93 | } 94 | ``` 95 | 96 | 97 | ## Crate features 98 | 99 | By default this crate has no dependencies on other crates. 100 | 101 | If you enable the **serde1** feature it will introduce a dependency on 102 | the _serde_ crate and provide `Serialize` and `Deserialize` 103 | implementations for all map and set types in this crate. 104 | 105 | You can enable the **serde1** feature in your _Cargo.toml_ file like so: 106 | 107 | ```toml 108 | [dependencies] 109 | rangemap = { version = "1", features = ["serde1"] } 110 | ``` 111 | 112 | You can similarly enable support for _quickcheck_ by enabling 113 | the **quickcheck** feature. 114 | 115 | ## Building without the Rust standard library 116 | 117 | This crate can work without the full standard library available 118 | (e.g. when running on bare metal without an operating system) 119 | but relies on the presence of a global allocator — 120 | i.e. it links the `core` and `alloc` crates, but not `std`. 121 | 122 | Presently there is no functionality in the crate that require 123 | the standard library. Such functionality will likely be 124 | introduced in the future, and will be gated behind a default-on 125 | `std` feature. 126 | 127 | See [The Rust Programming Language](https://doc.rust-lang.org/1.7.0/book/no-stdlib.html) 128 | book for general information about operating without the standard library. 129 | 130 | 131 | 132 | [`RangeMap`]: https://docs.rs/rangemap/latest/rangemap/map/struct.RangeMap.html 133 | [`RangeInclusiveMap`]: https://docs.rs/rangemap/latest/rangemap/inclusive_map/struct.RangeInclusiveMap.html 134 | [`RangeSet`]: https://docs.rs/rangemap/latest/rangemap/set/struct.RangeSet.html 135 | [`RangeInclusiveSet`]: https://docs.rs/rangemap/latest/rangemap/inclusive_set/struct.RangeInclusiveSet.html 136 | [`Range`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html 137 | [`RangeInclusive`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeInclusive.html 138 | -------------------------------------------------------------------------------- /benches/benches.rs: -------------------------------------------------------------------------------- 1 | use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; 2 | use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner}; 3 | use rangemap::*; 4 | use std::{any::type_name, fmt::Debug, ops::*}; 5 | use test_strategy::Arbitrary; 6 | 7 | type Key = i64; 8 | type Value = i64; 9 | 10 | const COUNT: usize = 100000; 11 | const OPERATIONS: usize = 100000; 12 | const LOOKUPS: usize = 1000000; 13 | 14 | #[derive(Debug, Clone, Arbitrary)] 15 | enum Operation { 16 | Insert(K, V), 17 | Delete(K), 18 | } 19 | 20 | fn range_inclusive_map( 21 | values: impl Strategy, V)>, 22 | size: usize, 23 | ) -> impl Strategy> { 24 | prop::collection::vec(values, size) 25 | .prop_map(|ranges| ranges.into_iter().collect::>()) 26 | } 27 | 28 | fn range_map( 29 | values: impl Strategy, V)>, 30 | size: usize, 31 | ) -> impl Strategy> { 32 | prop::collection::vec(values, size) 33 | .prop_map(|ranges| ranges.into_iter().collect::>()) 34 | } 35 | 36 | fn criterion_benchmark(c: &mut Criterion) { 37 | let mut runner = TestRunner::deterministic(); 38 | 39 | let mut group = c.benchmark_group(format!( 40 | "RangeMap<{}, {}>", 41 | type_name::(), 42 | type_name::() 43 | )); 44 | 45 | group.throughput(Throughput::Elements(COUNT as u64)); 46 | group.bench_function("insert", |b| { 47 | let entries = prop::collection::vec(any::<(Range, Value)>(), COUNT) 48 | .new_tree(&mut runner) 49 | .unwrap() 50 | .current(); 51 | b.iter_with_large_drop(|| { 52 | let mut map = RangeMap::new(); 53 | for (range, value) in entries.clone().into_iter() { 54 | map.insert(range, value); 55 | } 56 | map 57 | }) 58 | }); 59 | 60 | group.throughput(Throughput::Elements(OPERATIONS as u64)); 61 | group.bench_function("operations", |b| { 62 | let map = range_map(any::<(Range, Value)>(), COUNT) 63 | .new_tree(&mut runner) 64 | .unwrap() 65 | .current(); 66 | let operations = prop::collection::vec(any::, Value>>(), OPERATIONS) 67 | .new_tree(&mut runner) 68 | .unwrap() 69 | .current(); 70 | b.iter_with_large_drop(|| { 71 | let mut map = map.clone(); 72 | for operation in operations.clone().into_iter() { 73 | match operation { 74 | Operation::Insert(key, value) => map.insert(key, value), 75 | Operation::Delete(key) => map.remove(key), 76 | } 77 | } 78 | map 79 | }) 80 | }); 81 | 82 | group.throughput(Throughput::Elements(LOOKUPS as u64)); 83 | group.bench_function("lookups", |b| { 84 | let map = range_map(any::<(Range, Value)>(), COUNT) 85 | .new_tree(&mut runner) 86 | .unwrap() 87 | .current(); 88 | let lookups = prop::collection::vec(any::(), LOOKUPS) 89 | .new_tree(&mut runner) 90 | .unwrap() 91 | .current(); 92 | b.iter(|| { 93 | for lookup in lookups.iter() { 94 | black_box(map.get(lookup)); 95 | } 96 | }) 97 | }); 98 | 99 | group.finish(); 100 | 101 | let mut group = c.benchmark_group(format!( 102 | "RangeInclusiveMap<{}, {}>", 103 | type_name::(), 104 | type_name::() 105 | )); 106 | 107 | group.throughput(Throughput::Elements(COUNT as u64)); 108 | group.bench_function("insert", |b| { 109 | let entries = prop::collection::vec(any::<(RangeInclusive, Value)>(), COUNT) 110 | .new_tree(&mut runner) 111 | .unwrap() 112 | .current(); 113 | b.iter_with_large_drop(|| { 114 | let mut map = RangeInclusiveMap::new(); 115 | for (range, value) in entries.clone().into_iter() { 116 | map.insert(range, value); 117 | } 118 | map 119 | }) 120 | }); 121 | 122 | group.throughput(Throughput::Elements(OPERATIONS as u64)); 123 | group.bench_function("operations", |b| { 124 | let map = range_inclusive_map(any::<(RangeInclusive, Value)>(), COUNT) 125 | .new_tree(&mut runner) 126 | .unwrap() 127 | .current(); 128 | let operations = 129 | prop::collection::vec(any::, Value>>(), OPERATIONS) 130 | .new_tree(&mut runner) 131 | .unwrap() 132 | .current(); 133 | b.iter_with_large_drop(|| { 134 | let mut map = map.clone(); 135 | for operation in operations.clone().into_iter() { 136 | match operation { 137 | Operation::Insert(key, value) => map.insert(key, value), 138 | Operation::Delete(key) => map.remove(key), 139 | } 140 | } 141 | map 142 | }) 143 | }); 144 | 145 | group.throughput(Throughput::Elements(LOOKUPS as u64)); 146 | group.bench_function("lookups", |b| { 147 | let map = range_inclusive_map(any::<(RangeInclusive, Value)>(), COUNT) 148 | .new_tree(&mut runner) 149 | .unwrap() 150 | .current(); 151 | let lookups = prop::collection::vec(any::(), LOOKUPS) 152 | .new_tree(&mut runner) 153 | .unwrap() 154 | .current(); 155 | b.iter(|| { 156 | for lookup in lookups.iter() { 157 | black_box(map.get(lookup)); 158 | } 159 | }) 160 | }); 161 | 162 | group.finish(); 163 | } 164 | 165 | criterion_group!(benches, criterion_benchmark); 166 | criterion_main!(benches); 167 | -------------------------------------------------------------------------------- /bors.toml: -------------------------------------------------------------------------------- 1 | status = [ "ci" ] 2 | timeout_sec = 3600 # One hour 3 | -------------------------------------------------------------------------------- /examples/roster.rs: -------------------------------------------------------------------------------- 1 | use chrono::offset::TimeZone; 2 | use chrono::{Duration, Utc}; 3 | use rangemap::RangeMap; 4 | 5 | fn main() { 6 | let people = ["Alice", "Bob", "Carol"]; 7 | let mut roster = RangeMap::new(); 8 | 9 | // Set up initial roster. 10 | let start_of_roster = Utc.with_ymd_and_hms(2019, 1, 7, 0, 0, 0).unwrap(); 11 | let mut week_start = start_of_roster; 12 | for _ in 0..3 { 13 | for person in &people { 14 | let next_week = week_start + Duration::weeks(1); 15 | roster.insert(week_start..next_week, person); 16 | week_start = next_week; 17 | } 18 | } 19 | 20 | // Bob is covering Alice's second shift (the fourth shift overall). 21 | let fourth_shift_start = start_of_roster + Duration::weeks(3); 22 | let fourth_shift_end = fourth_shift_start + Duration::weeks(1); 23 | roster.insert(fourth_shift_start..fourth_shift_end, &"Bob"); 24 | 25 | // Print out the roster, and observe that 26 | // the fourth and fifth shifts have been coalesced 27 | // into one range. 28 | for (range, person) in roster.iter() { 29 | println!("{} ({}): {}", range.start, range.end - range.start, person); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "rangemap-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.3" 14 | arbitrary = { version = "0.4.7", features = ["derive"] } 15 | 16 | [dependencies.rangemap] 17 | path = ".." 18 | 19 | # Prevent this from interfering with workspaces 20 | [workspace] 21 | members = ["."] 22 | 23 | [[bin]] 24 | name = "rangemap_coalesce" 25 | path = "fuzz_targets/rangemap_coalesce.rs" 26 | test = false 27 | doc = false 28 | 29 | [[bin]] 30 | name = "rangemap_inclusive_coalesce" 31 | path = "fuzz_targets/rangemap_inclusive_coalesce.rs" 32 | test = false 33 | doc = false 34 | 35 | [[bin]] 36 | name = "rangemap_gaps" 37 | path = "fuzz_targets/rangemap_gaps.rs" 38 | test = false 39 | doc = false 40 | 41 | [[bin]] 42 | name = "rangemap_inclusive_gaps" 43 | path = "fuzz_targets/rangemap_inclusive_gaps.rs" 44 | test = false 45 | doc = false 46 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/rangemap_coalesce.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use arbitrary::Arbitrary; 5 | use rangemap::RangeMap; 6 | use std::ops::Range; 7 | 8 | #[derive(Clone, Debug, Arbitrary)] 9 | enum Op { 10 | Insert(Range, u8), 11 | Remove(Range), 12 | } 13 | 14 | impl Op { 15 | fn apply(self, map: &mut RangeMap) { 16 | match self { 17 | Op::Insert(r, v) if r.start < r.end => map.insert(r, v), 18 | Op::Remove(r) if r.start < r.end => map.remove(r), 19 | _ => (), 20 | } 21 | } 22 | } 23 | 24 | fuzz_target!(|ops: Vec| { 25 | let mut map = RangeMap::new(); 26 | 27 | for op in ops { 28 | op.apply(&mut map); 29 | } 30 | 31 | let mut peek = map.iter().peekable(); 32 | while let Some((range, val)) = peek.next() { 33 | if let Some((nextrange, nextval)) = peek.peek() { 34 | if range.end == nextrange.start && val == *nextval { 35 | panic!() 36 | } 37 | } 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/rangemap_gaps.rs: -------------------------------------------------------------------------------- 1 | #![feature(array_windows)] 2 | #![no_main] 3 | use libfuzzer_sys::fuzz_target; 4 | 5 | use arbitrary::{Arbitrary, Unstructured}; 6 | use rangemap::RangeMap; 7 | use std::ops::Range; 8 | 9 | #[derive(Clone, Debug, Arbitrary)] 10 | enum Op { 11 | Insert(Range, u8), 12 | Remove(Range), 13 | } 14 | 15 | impl Op { 16 | fn apply(self, map: &mut RangeMap) { 17 | match self { 18 | Op::Insert(r, v) if r.start < r.end => map.insert(r, v), 19 | Op::Remove(r) if r.start < r.end => map.remove(r), 20 | _ => (), 21 | } 22 | } 23 | } 24 | 25 | #[derive(Clone, Debug)] 26 | struct Input { 27 | ops: Vec, 28 | outer_range: Range, 29 | } 30 | 31 | impl Arbitrary for Input { 32 | fn arbitrary(u: &mut Unstructured) -> arbitrary::Result { 33 | Ok(Self { 34 | ops: u.arbitrary()?, 35 | // Larger margins than these are too 36 | // far away from boundary conditions to be interesting. 37 | // ("Oh, the fools! If only they'd built it with 6,001 hulls." -- Philip J. Fry) 38 | // 39 | // NOTE: Not using `int_in_range` because of . 40 | outer_range: *u.choose(&[0, 1, 2, 3, 100, 101, 102, 103])? 41 | ..*u.choose(&[100, 101, 102, 103, 252, 253, 254, 255])?, 42 | }) 43 | } 44 | } 45 | 46 | fuzz_target!(|input: Input| { 47 | let Input { ops, outer_range } = input; 48 | 49 | let mut map = RangeMap::new(); 50 | 51 | for op in ops { 52 | op.apply(&mut map); 53 | } 54 | 55 | // Check that the combination of gaps and keys fills the entire outer range. 56 | let gaps: Vec> = map.gaps(&outer_range).collect(); 57 | let mut keys: Vec> = map 58 | .overlapping(&outer_range) 59 | .map(|(Range { start, end }, _key)| { 60 | // Truncate anything straddling either edge. 61 | u8::max(*start, outer_range.start)..u8::min(*end, outer_range.end) 62 | }) 63 | .filter(|range| { 64 | // Reject anything that is now empty after being truncated. 65 | !range.is_empty() 66 | }) 67 | .collect(); 68 | 69 | keys.extend(gaps.into_iter()); 70 | keys.sort_by_key(|key| key.start); 71 | 72 | if outer_range.is_empty() { 73 | // There should be no gaps or keys returned if the outer range is empty, 74 | // because empty ranges cover no values. 75 | assert!(keys.is_empty()); 76 | return; 77 | } 78 | 79 | // Gaps and keys combined should span whole outer range. 80 | assert_eq!(keys.first().unwrap().start, outer_range.start); 81 | assert_eq!(keys.last().unwrap().end, outer_range.end); 82 | 83 | // Each gap/key should start where the previous one ended. 84 | for [a, b] in keys.array_windows::<2>() { 85 | assert_eq!(a.end, b.start); 86 | } 87 | }); 88 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/rangemap_inclusive_coalesce.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use arbitrary::Arbitrary; 5 | use rangemap::RangeInclusiveMap; 6 | use std::ops::RangeInclusive; 7 | 8 | #[derive(Clone, Debug, Arbitrary)] 9 | enum Op { 10 | Insert(RangeInclusive, u8), 11 | Remove(RangeInclusive), 12 | } 13 | 14 | impl Op { 15 | fn apply(self, map: &mut RangeInclusiveMap) { 16 | match self { 17 | Op::Insert(r, v) => map.insert(r, v), 18 | Op::Remove(r) => map.remove(r), 19 | } 20 | } 21 | } 22 | 23 | fuzz_target!(|ops: Vec| { 24 | let mut map = RangeInclusiveMap::new(); 25 | 26 | for op in ops { 27 | op.apply(&mut map); 28 | } 29 | 30 | let mut peek = map.iter().peekable(); 31 | while let Some((range, val)) = peek.next() { 32 | if let Some((nextrange, nextval)) = peek.peek() { 33 | if *range.end() == nextrange.start() - 1 && val == *nextval { 34 | panic!() 35 | } 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/rangemap_inclusive_gaps.rs: -------------------------------------------------------------------------------- 1 | #![feature(array_windows)] 2 | #![no_main] 3 | use libfuzzer_sys::fuzz_target; 4 | 5 | use arbitrary::{Arbitrary, Unstructured}; 6 | use rangemap::RangeInclusiveMap; 7 | use std::ops::RangeInclusive; 8 | 9 | #[derive(Clone, Debug, Arbitrary)] 10 | enum Op { 11 | Insert(RangeInclusive, u8), 12 | Remove(RangeInclusive), 13 | } 14 | 15 | impl Op { 16 | fn apply(self, map: &mut RangeInclusiveMap) { 17 | match self { 18 | Op::Insert(r, v) => map.insert(r, v), 19 | Op::Remove(r) => map.remove(r), 20 | } 21 | } 22 | } 23 | 24 | #[derive(Clone, Debug)] 25 | struct Input { 26 | ops: Vec, 27 | outer_range: RangeInclusive, 28 | } 29 | 30 | impl Arbitrary for Input { 31 | fn arbitrary(u: &mut Unstructured) -> arbitrary::Result { 32 | Ok(Self { 33 | ops: u.arbitrary()?, 34 | // Larger margins than these are too 35 | // far away from boundary conditions to be interesting. 36 | // ("Oh, the fools! If only they'd built it with 6,001 hulls." -- Philip J. Fry) 37 | // 38 | // NOTE: Not using `int_in_range` because of . 39 | outer_range: *u.choose(&[0, 1, 2, 3, 100, 101, 102, 103])? 40 | ..=*u.choose(&[100, 101, 102, 103, 252, 253, 254, 255])?, 41 | }) 42 | } 43 | } 44 | 45 | fuzz_target!(|input: Input| { 46 | let Input { ops, outer_range } = input; 47 | 48 | let mut map = RangeInclusiveMap::new(); 49 | 50 | for op in ops { 51 | op.apply(&mut map); 52 | } 53 | 54 | // Check that the combination of gaps and keys fills the entire outer range. 55 | let gaps: Vec> = map.gaps(&outer_range).collect(); 56 | let mut keys: Vec> = map 57 | .overlapping(&outer_range) 58 | .map(|(range, _value)| { 59 | // Truncate anything straddling either edge. 60 | u8::max(*range.start(), *outer_range.start()) 61 | ..=u8::min(*range.end(), *outer_range.end()) 62 | }) 63 | .filter(|range| { 64 | // Reject anything that is now empty after being truncated. 65 | !range.is_empty() 66 | }) 67 | .collect(); 68 | keys.extend(gaps.into_iter()); 69 | keys.sort_by_key(|key| *key.start()); 70 | 71 | if outer_range.is_empty() { 72 | // There should be no gaps or keys returned if the outer range is empty, 73 | // because empty ranges cover no values. 74 | assert!(keys.is_empty()); 75 | return; 76 | } 77 | 78 | // Gaps and keys combined should span whole outer range. 79 | assert_eq!(keys.first().unwrap().start(), outer_range.start()); 80 | assert_eq!(keys.last().unwrap().end(), outer_range.end()); 81 | 82 | // Each gap/key should start where the previous one ended. 83 | for [a, b] in keys.array_windows::<2>() { 84 | assert_eq!(*a.end() + 1, *b.start()); 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /pre_commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | cargo test 6 | # For doc tests in "README.md". 7 | cargo +nightly test --features nightly 8 | # And just with serde1. 9 | cargo test --features serde1 10 | # And with const functions. 11 | cargo +nightly test --features const_fn 12 | cargo run --example roster 13 | cargo fmt 14 | cargo clippy --bins --examples --tests --benches -- -D warnings 15 | -------------------------------------------------------------------------------- /src/dense.rs: -------------------------------------------------------------------------------- 1 | use alloc::{collections::BTreeMap, vec::Vec}; 2 | use core::ops::{Range, RangeInclusive}; 3 | 4 | use super::{RangeInclusiveMap, RangeMap}; 5 | 6 | // A simple but infeasibly slow and memory-hungry 7 | // version of `RangeInclusiveMap` for testing. 8 | // 9 | // Only understands `u32` keys, so that we don't 10 | // have to be generic over `step`. This is just for 11 | // testing, so it's fine. 12 | // 13 | // Note that even though this mirrors the semantics 14 | // of `RangeInclusiveMap`, it can also be used to 15 | // test `RangeMap` just fine. 16 | #[derive(Eq, PartialEq, Debug)] 17 | pub struct DenseU32RangeMap { 18 | // Inner B-Tree map. Stores values and their keys 19 | // directly rather than as ranges. 20 | btm: BTreeMap, 21 | } 22 | 23 | impl DenseU32RangeMap 24 | where 25 | V: Eq + Clone, 26 | { 27 | pub fn new() -> DenseU32RangeMap { 28 | DenseU32RangeMap { 29 | btm: BTreeMap::new(), 30 | } 31 | } 32 | 33 | pub fn insert(&mut self, range: RangeInclusive, value: V) { 34 | for k in range { 35 | self.btm.insert(k, value.clone()); 36 | } 37 | } 38 | 39 | pub fn iter(&self) -> Iter<'_, V> { 40 | Iter { 41 | inner: self.btm.iter(), 42 | current: None, 43 | } 44 | } 45 | 46 | pub fn end_exclusive_iter(&self) -> EndExclusiveIter<'_, V> { 47 | EndExclusiveIter { inner: self.iter() } 48 | } 49 | 50 | // Vecs are easier to use for assertions than iterators, 51 | // because you don't have to consume them to compare them. 52 | pub fn to_vec(&self) -> Vec<(RangeInclusive, V)> { 53 | self.iter() 54 | .map(|(range, value)| (range, value.clone())) 55 | .collect() 56 | } 57 | 58 | pub fn to_end_exclusive_vec(&self) -> Vec<(Range, V)> { 59 | self.end_exclusive_iter() 60 | .map(|(range, value)| (range, value.clone())) 61 | .collect() 62 | } 63 | } 64 | 65 | impl From> for DenseU32RangeMap 66 | where 67 | V: Eq + Clone, 68 | { 69 | fn from(range_map: RangeMap) -> Self { 70 | let mut dense = Self::new(); 71 | for (range, value) in range_map.iter() { 72 | // Convert to inclusive end. 73 | // (This is only valid because u32 has 74 | // the "successor function".) 75 | // 76 | // NOTE: Clippy's `range_minus_one` lint is a bit overzealous here, 77 | // because we _can't_ pass an open-ended range to `insert`. 78 | #[allow(clippy::range_minus_one)] 79 | dense.insert(range.start..=(range.end - 1), value.clone()); 80 | } 81 | dense 82 | } 83 | } 84 | 85 | impl From> for DenseU32RangeMap 86 | where 87 | V: Eq + Clone, 88 | { 89 | fn from(range_inclusive_map: RangeInclusiveMap) -> Self { 90 | let mut dense = Self::new(); 91 | for (range, value) in range_inclusive_map.iter() { 92 | dense.insert(range.clone(), value.clone()); 93 | } 94 | dense 95 | } 96 | } 97 | 98 | pub struct Iter<'a, V> { 99 | inner: alloc::collections::btree_map::Iter<'a, u32, V>, 100 | // Current range being built for output. 101 | // We modify it as we iterate through the underlying 102 | // dense map. 103 | current: Option<(RangeInclusive, &'a V)>, 104 | } 105 | 106 | // Coalesce items from the underlying dense map as we go. 107 | impl<'a, V> Iterator for Iter<'a, V> 108 | where 109 | V: 'a + Eq, 110 | { 111 | type Item = (RangeInclusive, &'a V); 112 | 113 | fn next(&mut self) -> Option<(RangeInclusive, &'a V)> { 114 | if let Some(next_dense) = self.inner.next() { 115 | if let Some(current) = &mut self.current { 116 | // We're already building a range. Can we extend it? 117 | if current.0.end() + 1 == *next_dense.0 && *current.1 == *next_dense.1 { 118 | // This immediately follows the last item and the value is the same; 119 | // we can extend it. 120 | *current = (*current.0.start()..=*next_dense.0, current.1); 121 | // Recurse until we find a way to flush it. 122 | self.next() 123 | } else { 124 | // There's a gap or the value differs; flush the one we were working on and start a new one. 125 | let item_to_yield = current.clone(); 126 | *current = (*next_dense.0..=*next_dense.0, next_dense.1); 127 | Some(item_to_yield) 128 | } 129 | } else { 130 | // We're not building a range yet; start a new one. 131 | self.current = Some((*next_dense.0..=*next_dense.0, next_dense.1)); 132 | // Recurse until we find a way to flush it. 133 | self.next() 134 | } 135 | } else { 136 | // We reached the end of the underlying dense map. 137 | // Flush the item we were building, if any. 138 | self.current.take() 139 | } 140 | } 141 | } 142 | 143 | pub struct EndExclusiveIter<'a, V> { 144 | inner: Iter<'a, V>, 145 | } 146 | 147 | impl<'a, V> Iterator for EndExclusiveIter<'a, V> 148 | where 149 | V: 'a + Eq, 150 | { 151 | type Item = (Range, &'a V); 152 | 153 | fn next(&mut self) -> Option<(Range, &'a V)> { 154 | self.inner 155 | .next() 156 | .map(|(range, value)| ((*range.start())..(*range.end() + 1), value)) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/inclusive_set.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::Borrow; 2 | use core::fmt::{self, Debug}; 3 | use core::iter::{DoubleEndedIterator, FromIterator}; 4 | use core::ops::{BitAnd, BitOr, RangeInclusive}; 5 | 6 | #[cfg(feature = "serde1")] 7 | use core::marker::PhantomData; 8 | #[cfg(feature = "serde1")] 9 | use serde::{ 10 | de::{Deserialize, Deserializer, SeqAccess, Visitor}, 11 | ser::{Serialize, Serializer}, 12 | }; 13 | 14 | use crate::std_ext::*; 15 | use crate::RangeInclusiveMap; 16 | 17 | /// Intersection iterator over two [`RangeInclusiveSet`]. 18 | pub type Intersection<'a, T> = crate::operations::Intersection<'a, RangeInclusive, Iter<'a, T>>; 19 | 20 | /// Union iterator over two [`RangeInclusiveSet`]. 21 | pub type Union<'a, T> = crate::operations::Union<'a, RangeInclusive, Iter<'a, T>>; 22 | 23 | #[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord)] 24 | /// A set whose items are stored as ranges bounded 25 | /// inclusively below and above `(start..=end)`. 26 | /// 27 | /// See [`RangeInclusiveMap`]'s documentation for more details. 28 | /// 29 | /// [`RangeInclusiveMap`]: crate::RangeInclusiveMap 30 | pub struct RangeInclusiveSet { 31 | rm: RangeInclusiveMap, 32 | } 33 | 34 | impl Default for RangeInclusiveSet { 35 | fn default() -> Self { 36 | Self { 37 | rm: RangeInclusiveMap::default(), 38 | } 39 | } 40 | } 41 | 42 | #[cfg(feature = "quickcheck")] 43 | impl quickcheck::Arbitrary for RangeInclusiveSet 44 | where 45 | K: quickcheck::Arbitrary + Ord + StepLite, 46 | { 47 | fn arbitrary(g: &mut quickcheck::Gen) -> Self { 48 | Self { 49 | rm: RangeInclusiveMap::arbitrary(g), 50 | } 51 | } 52 | } 53 | 54 | impl RangeInclusiveSet 55 | where 56 | T: Ord + Clone + StepLite, 57 | { 58 | /// Makes a new empty `RangeInclusiveSet`. 59 | #[cfg(feature = "const_fn")] 60 | pub const fn new() -> Self { 61 | Self::new_with_step_fns() 62 | } 63 | 64 | /// Makes a new empty `RangeInclusiveSet`. 65 | #[cfg(not(feature = "const_fn"))] 66 | pub fn new() -> Self { 67 | Self::new_with_step_fns() 68 | } 69 | } 70 | 71 | impl RangeInclusiveSet 72 | where 73 | T: Ord + Clone, 74 | StepFnsT: StepFns, 75 | { 76 | /// Makes a new empty `RangeInclusiveSet`, specifying successor and 77 | /// predecessor functions defined separately from `T` itself. 78 | /// 79 | /// This is useful as a workaround for Rust's "orphan rules", 80 | /// which prevent you from implementing `StepLite` for `T` if `T` 81 | /// is a foreign type. 82 | /// 83 | /// **NOTE:** This will likely be deprecated and then eventually 84 | /// removed once the standard library's [Step](core::iter::Step) 85 | /// trait is stabilised, as most crates will then likely implement [Step](core::iter::Step) 86 | /// for their types where appropriate. 87 | /// 88 | /// See [this issue](https://github.com/rust-lang/rust/issues/42168) 89 | /// for details about that stabilization process. 90 | #[cfg(not(feature = "const_fn"))] 91 | pub fn new_with_step_fns() -> Self { 92 | Self { 93 | rm: RangeInclusiveMap::new_with_step_fns(), 94 | } 95 | } 96 | 97 | #[cfg(feature = "const_fn")] 98 | pub const fn new_with_step_fns() -> Self { 99 | Self { 100 | rm: RangeInclusiveMap::new_with_step_fns(), 101 | } 102 | } 103 | 104 | /// Returns a reference to the range covering the given key, if any. 105 | pub fn get(&self, value: &T) -> Option<&RangeInclusive> { 106 | self.rm.get_key_value(value).map(|(range, _)| range) 107 | } 108 | 109 | /// Returns `true` if any range in the set covers the specified value. 110 | pub fn contains(&self, value: &T) -> bool { 111 | self.rm.contains_key(value) 112 | } 113 | 114 | /// Gets an ordered iterator over all ranges, 115 | /// ordered by range. 116 | pub fn iter(&self) -> Iter<'_, T> { 117 | Iter { 118 | inner: self.rm.iter(), 119 | } 120 | } 121 | 122 | /// Clears the set, removing all elements. 123 | pub fn clear(&mut self) { 124 | self.rm.clear(); 125 | } 126 | 127 | /// Returns the number of elements in the set. 128 | pub fn len(&self) -> usize { 129 | self.rm.len() 130 | } 131 | 132 | /// Returns true if the set contains no elements. 133 | pub fn is_empty(&self) -> bool { 134 | self.rm.is_empty() 135 | } 136 | 137 | /// Insert a range into the set. 138 | /// 139 | /// If the inserted range either overlaps or is immediately adjacent 140 | /// any existing range, then the ranges will be coalesced into 141 | /// a single contiguous range. 142 | /// 143 | /// # Panics 144 | /// 145 | /// Panics if range `start > end`. 146 | pub fn insert(&mut self, range: RangeInclusive) { 147 | self.rm.insert(range, ()); 148 | } 149 | 150 | /// Removes a range from the set, if all or any of it was present. 151 | /// 152 | /// If the range to be removed _partially_ overlaps any ranges 153 | /// in the set, then those ranges will be contracted to no 154 | /// longer cover the removed range. 155 | /// 156 | /// # Panics 157 | /// 158 | /// Panics if range `start > end`. 159 | pub fn remove(&mut self, range: RangeInclusive) { 160 | self.rm.remove(range); 161 | } 162 | 163 | /// Gets an iterator over all the maximally-sized ranges 164 | /// contained in `outer_range` that are not covered by 165 | /// any range stored in the set. 166 | /// 167 | /// The iterator element type is `RangeInclusive`. 168 | pub fn gaps<'a>(&'a self, outer_range: &'a RangeInclusive) -> Gaps<'a, T, StepFnsT> { 169 | Gaps { 170 | inner: self.rm.gaps(outer_range), 171 | } 172 | } 173 | 174 | /// Gets an iterator over all the stored ranges that are 175 | /// either partially or completely overlapped by the given range. 176 | /// 177 | /// The iterator element type is `RangeInclusive`. 178 | pub fn overlapping>>(&self, range: R) -> Overlapping { 179 | Overlapping { 180 | inner: self.rm.overlapping(range), 181 | } 182 | } 183 | 184 | /// Returns `true` if any range in the set completely or partially 185 | /// overlaps the given range. 186 | pub fn overlaps(&self, range: &RangeInclusive) -> bool { 187 | self.overlapping(range).next().is_some() 188 | } 189 | 190 | /// Returns the first range in the set, if one exists. The range is the minimum range in this 191 | /// set. 192 | pub fn first(&self) -> Option<&RangeInclusive> { 193 | self.rm.first_range_value().map(|(range, _)| range) 194 | } 195 | 196 | /// Returns the last range in the set, if one exists. The range is the maximum range in this 197 | /// set. 198 | pub fn last(&self) -> Option<&RangeInclusive> { 199 | self.rm.last_range_value().map(|(range, _)| range) 200 | } 201 | 202 | /// Return an iterator over the union of two range sets. 203 | pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T> { 204 | Union::new(self.iter(), other.iter()) 205 | } 206 | 207 | /// Return an iterator over the intersection of two range sets. 208 | pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T> { 209 | Intersection::new(self.iter(), other.iter()) 210 | } 211 | } 212 | 213 | /// An iterator over the ranges of a `RangeInclusiveSet`. 214 | /// 215 | /// This `struct` is created by the [`iter`] method on [`RangeInclusiveSet`]. See its 216 | /// documentation for more. 217 | /// 218 | /// [`iter`]: RangeInclusiveSet::iter 219 | pub struct Iter<'a, T> { 220 | inner: super::inclusive_map::Iter<'a, T, ()>, 221 | } 222 | 223 | impl<'a, T> Iterator for Iter<'a, T> { 224 | type Item = &'a RangeInclusive; 225 | 226 | fn next(&mut self) -> Option { 227 | self.inner.next().map(|(range, _)| range) 228 | } 229 | 230 | fn size_hint(&self) -> (usize, Option) { 231 | self.inner.size_hint() 232 | } 233 | } 234 | 235 | impl<'a, K> DoubleEndedIterator for Iter<'a, K> 236 | where 237 | K: 'a, 238 | { 239 | fn next_back(&mut self) -> Option { 240 | self.inner.next_back().map(|(range, _)| range) 241 | } 242 | } 243 | 244 | /// An owning iterator over the ranges of a `RangeInclusiveSet`. 245 | /// 246 | /// This `struct` is created by the [`into_iter`] method on [`RangeInclusiveSet`] 247 | /// (provided by the `IntoIterator` trait). See its documentation for more. 248 | /// 249 | /// [`into_iter`]: IntoIterator::into_iter 250 | pub struct IntoIter { 251 | inner: super::inclusive_map::IntoIter, 252 | } 253 | 254 | impl IntoIterator for RangeInclusiveSet { 255 | type Item = RangeInclusive; 256 | type IntoIter = IntoIter; 257 | fn into_iter(self) -> Self::IntoIter { 258 | IntoIter { 259 | inner: self.rm.into_iter(), 260 | } 261 | } 262 | } 263 | 264 | impl Iterator for IntoIter { 265 | type Item = RangeInclusive; 266 | fn next(&mut self) -> Option> { 267 | self.inner.next().map(|(range, _)| range) 268 | } 269 | fn size_hint(&self) -> (usize, Option) { 270 | self.inner.size_hint() 271 | } 272 | } 273 | 274 | impl DoubleEndedIterator for IntoIter { 275 | fn next_back(&mut self) -> Option { 276 | self.inner.next_back().map(|(range, _)| range) 277 | } 278 | } 279 | 280 | // We can't just derive this automatically, because that would 281 | // expose irrelevant (and private) implementation details. 282 | // Instead implement it in the same way that the underlying BTreeSet does. 283 | impl Debug for RangeInclusiveSet 284 | where 285 | T: Ord + Clone + StepLite, 286 | { 287 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 288 | f.debug_set().entries(self.iter()).finish() 289 | } 290 | } 291 | 292 | impl FromIterator> for RangeInclusiveSet 293 | where 294 | T: Ord + Clone + StepLite, 295 | { 296 | fn from_iter>>(iter: I) -> Self { 297 | let mut range_set = RangeInclusiveSet::new(); 298 | range_set.extend(iter); 299 | range_set 300 | } 301 | } 302 | 303 | impl Extend> for RangeInclusiveSet 304 | where 305 | T: Ord + Clone + StepLite, 306 | { 307 | fn extend>>(&mut self, iter: I) { 308 | iter.into_iter().for_each(move |range| { 309 | self.insert(range); 310 | }) 311 | } 312 | } 313 | 314 | #[cfg(feature = "serde1")] 315 | impl Serialize for RangeInclusiveSet 316 | where 317 | T: Ord + Clone + StepLite + Serialize, 318 | { 319 | fn serialize(&self, serializer: S) -> Result 320 | where 321 | S: Serializer, 322 | { 323 | use serde::ser::SerializeSeq; 324 | let mut seq = serializer.serialize_seq(Some(self.rm.btm.len()))?; 325 | for range in self.iter() { 326 | seq.serialize_element(&(&range.start(), &range.end()))?; 327 | } 328 | seq.end() 329 | } 330 | } 331 | 332 | #[cfg(feature = "serde1")] 333 | impl<'de, T> Deserialize<'de> for RangeInclusiveSet 334 | where 335 | T: Ord + Clone + StepLite + Deserialize<'de>, 336 | { 337 | fn deserialize(deserializer: D) -> Result 338 | where 339 | D: Deserializer<'de>, 340 | { 341 | deserializer.deserialize_seq(RangeInclusiveSetVisitor::new()) 342 | } 343 | } 344 | 345 | #[cfg(feature = "serde1")] 346 | struct RangeInclusiveSetVisitor { 347 | marker: PhantomData RangeInclusiveSet>, 348 | } 349 | 350 | #[cfg(feature = "serde1")] 351 | impl RangeInclusiveSetVisitor { 352 | fn new() -> Self { 353 | RangeInclusiveSetVisitor { 354 | marker: PhantomData, 355 | } 356 | } 357 | } 358 | 359 | #[cfg(feature = "serde1")] 360 | impl<'de, T> Visitor<'de> for RangeInclusiveSetVisitor 361 | where 362 | T: Ord + Clone + StepLite + Deserialize<'de>, 363 | { 364 | type Value = RangeInclusiveSet; 365 | 366 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 367 | formatter.write_str("RangeInclusiveSet") 368 | } 369 | 370 | fn visit_seq(self, mut access: A) -> Result 371 | where 372 | A: SeqAccess<'de>, 373 | { 374 | let mut range_inclusive_set = RangeInclusiveSet::new(); 375 | while let Some((start, end)) = access.next_element()? { 376 | range_inclusive_set.insert(start..=end); 377 | } 378 | Ok(range_inclusive_set) 379 | } 380 | } 381 | 382 | /// An iterator over all ranges not covered by a `RangeInclusiveSet`. 383 | /// 384 | /// This `struct` is created by the [`gaps`] method on [`RangeInclusiveSet`]. See its 385 | /// documentation for more. 386 | /// 387 | /// [`gaps`]: RangeInclusiveSet::gaps 388 | pub struct Gaps<'a, T, StepFnsT> { 389 | inner: crate::inclusive_map::Gaps<'a, T, (), StepFnsT>, 390 | } 391 | 392 | // `Gaps` is always fused. (See definition of `next` below.) 393 | impl<'a, T, StepFnsT> core::iter::FusedIterator for Gaps<'a, T, StepFnsT> 394 | where 395 | T: Ord + Clone, 396 | StepFnsT: StepFns, 397 | { 398 | } 399 | 400 | impl<'a, T, StepFnsT> Iterator for Gaps<'a, T, StepFnsT> 401 | where 402 | T: Ord + Clone, 403 | StepFnsT: StepFns, 404 | { 405 | type Item = RangeInclusive; 406 | 407 | fn next(&mut self) -> Option { 408 | self.inner.next() 409 | } 410 | } 411 | 412 | /// An iterator over all stored ranges partially or completely 413 | /// overlapped by a given range. 414 | /// 415 | /// This `struct` is created by the [`overlapping`] method on [`RangeInclusiveSet`]. See its 416 | /// documentation for more. 417 | /// 418 | /// [`overlapping`]: RangeInclusiveSet::overlapping 419 | pub struct Overlapping<'a, T, R: Borrow> = &'a RangeInclusive> { 420 | inner: crate::inclusive_map::Overlapping<'a, T, (), R>, 421 | } 422 | 423 | // `Overlapping` is always fused. (See definition of `next` below.) 424 | impl<'a, T, R: Borrow>> core::iter::FusedIterator for Overlapping<'a, T, R> where 425 | T: Ord + Clone 426 | { 427 | } 428 | 429 | impl<'a, T, R: Borrow>> Iterator for Overlapping<'a, T, R> 430 | where 431 | T: Ord + Clone, 432 | { 433 | type Item = &'a RangeInclusive; 434 | 435 | fn next(&mut self) -> Option { 436 | self.inner.next().map(|(k, _v)| k) 437 | } 438 | } 439 | 440 | impl<'a, T, R: Borrow>> DoubleEndedIterator for Overlapping<'a, T, R> 441 | where 442 | T: Ord + Clone, 443 | { 444 | fn next_back(&mut self) -> Option { 445 | self.inner.next_back().map(|(k, _v)| k) 446 | } 447 | } 448 | 449 | impl From<[RangeInclusive; N]> 450 | for RangeInclusiveSet 451 | { 452 | fn from(value: [RangeInclusive; N]) -> Self { 453 | let mut set = Self::new(); 454 | for value in IntoIterator::into_iter(value) { 455 | set.insert(value); 456 | } 457 | set 458 | } 459 | } 460 | 461 | /// Create a [`RangeInclusiveSet`] from a list of ranges. 462 | /// 463 | /// # Example 464 | /// 465 | /// ```rust 466 | /// # use rangemap::range_inclusive_set; 467 | /// let set = range_inclusive_set![0..=100, 200..=300, 400..=500]; 468 | /// ``` 469 | #[macro_export] 470 | macro_rules! range_inclusive_set { 471 | ($($range:expr),* $(,)?) => {{ 472 | $crate::RangeInclusiveSet::from([$($range),*]) 473 | }}; 474 | } 475 | 476 | impl BitAnd for &RangeInclusiveSet { 477 | type Output = RangeInclusiveSet; 478 | 479 | fn bitand(self, other: Self) -> Self::Output { 480 | self.intersection(other).collect() 481 | } 482 | } 483 | 484 | impl BitOr for &RangeInclusiveSet { 485 | type Output = RangeInclusiveSet; 486 | 487 | fn bitor(self, other: Self) -> Self::Output { 488 | self.union(other).collect() 489 | } 490 | } 491 | 492 | #[cfg(test)] 493 | mod tests { 494 | use super::*; 495 | use alloc as std; 496 | use alloc::{format, vec, vec::Vec}; 497 | use proptest::prelude::*; 498 | use test_strategy::proptest; 499 | 500 | impl Arbitrary for RangeInclusiveSet 501 | where 502 | T: Ord + Clone + StepLite + Debug + Arbitrary + 'static, 503 | { 504 | type Parameters = (); 505 | type Strategy = BoxedStrategy; 506 | 507 | fn arbitrary_with(_parameters: Self::Parameters) -> Self::Strategy { 508 | any::>>() 509 | .prop_map(|ranges| ranges.into_iter().collect::>()) 510 | .boxed() 511 | } 512 | } 513 | 514 | #[proptest] 515 | fn test_first(set: RangeInclusiveSet) { 516 | assert_eq!(set.first(), set.iter().min_by_key(|range| range.start())); 517 | } 518 | 519 | #[proptest] 520 | #[allow(clippy::len_zero)] 521 | fn test_len(mut map: RangeInclusiveSet) { 522 | assert_eq!(map.len(), map.iter().count()); 523 | assert_eq!(map.is_empty(), map.len() == 0); 524 | map.clear(); 525 | assert_eq!(map.len(), 0); 526 | assert!(map.is_empty()); 527 | assert_eq!(map.iter().count(), 0); 528 | } 529 | 530 | #[proptest] 531 | fn test_last(set: RangeInclusiveSet) { 532 | assert_eq!(set.last(), set.iter().max_by_key(|range| range.end())); 533 | } 534 | 535 | #[proptest] 536 | fn test_iter_reversible(set: RangeInclusiveSet) { 537 | let forward: Vec<_> = set.iter().collect(); 538 | let mut backward: Vec<_> = set.iter().rev().collect(); 539 | backward.reverse(); 540 | assert_eq!(forward, backward); 541 | } 542 | 543 | #[proptest] 544 | fn test_into_iter_reversible(set: RangeInclusiveSet) { 545 | let forward: Vec<_> = set.clone().into_iter().collect(); 546 | let mut backward: Vec<_> = set.into_iter().rev().collect(); 547 | backward.reverse(); 548 | assert_eq!(forward, backward); 549 | } 550 | 551 | #[proptest] 552 | fn test_overlapping_reversible(set: RangeInclusiveSet, range: RangeInclusive) { 553 | let forward: Vec<_> = set.overlapping(&range).collect(); 554 | let mut backward: Vec<_> = set.overlapping(&range).rev().collect(); 555 | backward.reverse(); 556 | assert_eq!(forward, backward); 557 | } 558 | 559 | // neccessary due to assertion on empty ranges 560 | fn filter_ranges(ranges: Vec>) -> Vec> { 561 | ranges 562 | .into_iter() 563 | .filter(|range| range.start() != range.end()) 564 | .collect() 565 | } 566 | 567 | #[proptest] 568 | fn test_arbitrary_set_u8(ranges: Vec>) { 569 | let ranges: Vec<_> = filter_ranges(ranges); 570 | let set = ranges 571 | .iter() 572 | .fold(RangeInclusiveSet::new(), |mut set, range| { 573 | set.insert(range.clone()); 574 | set 575 | }); 576 | 577 | for value in 0..u8::MAX { 578 | assert_eq!( 579 | set.contains(&value), 580 | ranges.iter().any(|range| range.contains(&value)) 581 | ); 582 | } 583 | } 584 | 585 | #[proptest] 586 | #[allow(deprecated)] 587 | fn test_hash(left: RangeInclusiveSet, right: RangeInclusiveSet) { 588 | use core::hash::{Hash, Hasher, SipHasher}; 589 | 590 | let hash = |set: &RangeInclusiveSet<_>| { 591 | let mut hasher = SipHasher::new(); 592 | set.hash(&mut hasher); 593 | hasher.finish() 594 | }; 595 | 596 | if left == right { 597 | assert!( 598 | hash(&left) == hash(&right), 599 | "if two values are equal, their hash must be equal" 600 | ); 601 | } 602 | 603 | // if the hashes are equal the values might not be the same (collision) 604 | if hash(&left) != hash(&right) { 605 | assert!( 606 | left != right, 607 | "if two value's hashes are not equal, they must not be equal" 608 | ); 609 | } 610 | } 611 | 612 | #[proptest] 613 | fn test_ord(left: RangeInclusiveSet, right: RangeInclusiveSet) { 614 | assert_eq!( 615 | left == right, 616 | left.cmp(&right).is_eq(), 617 | "ordering and equality must match" 618 | ); 619 | assert_eq!( 620 | left.cmp(&right), 621 | left.partial_cmp(&right).unwrap(), 622 | "ordering is total for ordered parameters" 623 | ); 624 | } 625 | 626 | #[test] 627 | fn test_from_array() { 628 | let mut set = RangeInclusiveSet::new(); 629 | set.insert(0..=100); 630 | set.insert(200..=300); 631 | assert_eq!(set, RangeInclusiveSet::from([0..=100, 200..=300])); 632 | } 633 | 634 | #[test] 635 | fn test_macro() { 636 | assert_eq!(range_inclusive_set![], RangeInclusiveSet::::default()); 637 | assert_eq!( 638 | range_inclusive_set![0..=100, 200..=300, 400..=500], 639 | [0..=100, 200..=300, 400..=500].iter().cloned().collect(), 640 | ); 641 | } 642 | 643 | #[proptest] 644 | fn test_union_overlaps_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { 645 | let mut union = RangeInclusiveSet::new(); 646 | for range in left.union(&right) { 647 | // there should not be any overlaps in the ranges returned by the union 648 | assert!(union.overlapping(&range).next().is_none()); 649 | union.insert(range); 650 | } 651 | } 652 | 653 | #[proptest] 654 | fn test_union_contains_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { 655 | let union = (&left) | (&right); 656 | 657 | // value should be in the union if and only if it is in either set 658 | for value in 0..u8::MAX { 659 | assert_eq!( 660 | union.contains(&value), 661 | left.contains(&value) || right.contains(&value) 662 | ); 663 | } 664 | } 665 | 666 | #[proptest] 667 | fn test_intersection_contains_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { 668 | let intersection = (&left) & (&right); 669 | 670 | // value should be in the intersection if and only if it is in both sets 671 | for value in 0..u8::MAX { 672 | assert_eq!( 673 | intersection.contains(&value), 674 | left.contains(&value) && right.contains(&value) 675 | ); 676 | } 677 | } 678 | 679 | #[proptest] 680 | fn test_intersection_overlaps_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { 681 | let mut union = RangeInclusiveSet::new(); 682 | for range in left.intersection(&right) { 683 | // there should not be any overlaps in the ranges returned by the 684 | // intersection 685 | assert!(union.overlapping(&range).next().is_none()); 686 | union.insert(range); 687 | } 688 | } 689 | 690 | trait RangeInclusiveSetExt { 691 | fn to_vec(&self) -> Vec>; 692 | } 693 | 694 | impl RangeInclusiveSetExt for RangeInclusiveSet 695 | where 696 | T: Ord + Clone + StepLite, 697 | { 698 | fn to_vec(&self) -> Vec> { 699 | self.iter().cloned().collect() 700 | } 701 | } 702 | 703 | #[test] 704 | fn empty_set_is_empty() { 705 | let range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 706 | assert_eq!(range_set.to_vec(), vec![]); 707 | } 708 | 709 | #[test] 710 | fn insert_into_empty_map() { 711 | let mut range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 712 | range_set.insert(0..=50); 713 | assert_eq!(range_set.to_vec(), vec![0..=50]); 714 | } 715 | 716 | #[test] 717 | fn remove_partially_overlapping() { 718 | let mut range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 719 | range_set.insert(0..=50); 720 | range_set.remove(25..=75); 721 | assert_eq!(range_set.to_vec(), vec![0..=24]); 722 | } 723 | 724 | #[test] 725 | fn gaps_between_items_floating_inside_outer_range() { 726 | let mut range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 727 | // 0 1 2 3 4 5 6 7 8 9 728 | // ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ ◌ 729 | range_set.insert(5..=6); 730 | // 0 1 2 3 4 5 6 7 8 9 731 | // ◌ ◌ ●-● ◌ ◌ ◌ ◌ ◌ ◌ 732 | range_set.insert(2..=3); 733 | // 0 1 2 3 4 5 6 7 8 9 734 | // ◌ ◆-------------◆ ◌ 735 | let outer_range = 1..=8; 736 | let mut gaps = range_set.gaps(&outer_range); 737 | // Should yield gaps at start, between items, 738 | // and at end. 739 | assert_eq!(gaps.next(), Some(1..=1)); 740 | assert_eq!(gaps.next(), Some(4..=4)); 741 | assert_eq!(gaps.next(), Some(7..=8)); 742 | assert_eq!(gaps.next(), None); 743 | // Gaps iterator should be fused. 744 | assert_eq!(gaps.next(), None); 745 | assert_eq!(gaps.next(), None); 746 | } 747 | 748 | #[test] 749 | fn overlapping_partial_edges_complete_middle() { 750 | let mut range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 751 | 752 | // 0 1 2 3 4 5 6 7 8 9 753 | // ●-● ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 754 | range_set.insert(0..=1); 755 | // 0 1 2 3 4 5 6 7 8 9 756 | // ◌ ◌ ◌ ●-● ◌ ◌ ◌ ◌ ◌ 757 | range_set.insert(3..=4); 758 | // 0 1 2 3 4 5 6 7 8 9 759 | // ◌ ◌ ◌ ◌ ◌ ◌ ●-● ◌ ◌ 760 | range_set.insert(6..=7); 761 | 762 | // 0 1 2 3 4 5 6 7 8 9 763 | // ◌ ◆---------◆ ◌ ◌ ◌ 764 | let query_range = 1..=6; 765 | 766 | let mut overlapping = range_set.overlapping(&query_range); 767 | 768 | // Should yield partially overlapped range at start. 769 | assert_eq!(overlapping.next(), Some(&(0..=1))); 770 | // Should yield completely overlapped range in middle. 771 | assert_eq!(overlapping.next(), Some(&(3..=4))); 772 | // Should yield partially overlapped range at end. 773 | assert_eq!(overlapping.next(), Some(&(6..=7))); 774 | // Gaps iterator should be fused. 775 | assert_eq!(overlapping.next(), None); 776 | assert_eq!(overlapping.next(), None); 777 | } 778 | 779 | /// 780 | /// impl Debug 781 | /// 782 | 783 | #[test] 784 | fn set_debug_repr_looks_right() { 785 | let mut set: RangeInclusiveSet = RangeInclusiveSet::new(); 786 | 787 | // Empty 788 | assert_eq!(format!("{:?}", set), "{}"); 789 | 790 | // One entry 791 | set.insert(2..=5); 792 | assert_eq!(format!("{:?}", set), "{2..=5}"); 793 | 794 | // Many entries 795 | set.insert(7..=8); 796 | set.insert(10..=11); 797 | assert_eq!(format!("{:?}", set), "{2..=5, 7..=8, 10..=11}"); 798 | } 799 | 800 | // impl Default where T: ?Default 801 | 802 | #[test] 803 | fn always_default() { 804 | struct NoDefault; 805 | RangeInclusiveSet::::default(); 806 | } 807 | 808 | // impl Serialize 809 | 810 | #[cfg(feature = "serde1")] 811 | #[test] 812 | fn serialization() { 813 | let mut range_set: RangeInclusiveSet = RangeInclusiveSet::new(); 814 | // 0 1 2 3 4 5 6 7 8 9 815 | // ◌ ◆---◆ ◌ ◌ ◌ ◌ ◌ ◌ 816 | range_set.insert(1..=3); 817 | // 0 1 2 3 4 5 6 7 8 9 818 | // ◌ ◌ ◌ ◌ ◌ ◆---◆ ◌ ◌ 819 | range_set.insert(5..=7); 820 | let output = serde_json::to_string(&range_set).expect("Failed to serialize"); 821 | assert_eq!(output, "[[1,3],[5,7]]"); 822 | } 823 | 824 | // impl Deserialize 825 | 826 | #[cfg(feature = "serde1")] 827 | #[test] 828 | fn deserialization() { 829 | let input = "[[1,3],[5,7]]"; 830 | let range_set: RangeInclusiveSet = 831 | serde_json::from_str(input).expect("Failed to deserialize"); 832 | let reserialized = serde_json::to_string(&range_set).expect("Failed to re-serialize"); 833 | assert_eq!(reserialized, input); 834 | } 835 | 836 | // const fn 837 | 838 | #[cfg(feature = "const_fn")] 839 | const _SET: RangeInclusiveSet = RangeInclusiveSet::new(); 840 | #[cfg(feature = "const_fn")] 841 | const _SET2: RangeInclusiveSet = RangeInclusiveSet::new_with_step_fns(); 842 | 843 | #[cfg(feature = "quickcheck")] 844 | quickcheck::quickcheck! { 845 | fn prop(xs: RangeInclusiveSet) -> bool { 846 | xs == xs 847 | } 848 | } 849 | } 850 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | [`RangeMap`] and [`RangeInclusiveMap`] are map data structures whose keys 3 | are stored as ranges. Contiguous and overlapping ranges that map to the same 4 | value are coalesced into a single range. 5 | 6 | Corresponding [`RangeSet`] and [`RangeInclusiveSet`] structures are also provided. 7 | 8 | 9 | # Different kinds of ranges 10 | 11 | `RangeMap` and `RangeInclusiveMap` correspond to the [`Range`] 12 | and [`RangeInclusive`] types from the standard library respectively. 13 | For some applications the choice of range type may be obvious, 14 | or even be dictated by pre-existing design decisions. For other applications 15 | the choice may seem arbitrary, and be guided instead by convenience or 16 | aesthetic preference. 17 | 18 | If the choice is not obvious in your case, consider these differences: 19 | 20 | - If your key type `K` represents points on a continuum (e.g. `f64`), 21 | and the choice of which of two adjacent ranges "owns" the value 22 | where they touch is largely arbitrary, then it may be more natural 23 | to work with half-open `Range`s like `0.0..1.0` and `1.0..2.0`. If you 24 | were to use closed `RangeInclusive`s here instead, then to represent two such adjacent 25 | ranges you would need to subtract some infinitesimal (which may depend, 26 | as it does in the case of `f64`, on the specific value of `K`) 27 | from the end of the earlier range. (See the last point below for more 28 | on this problem.) 29 | - If you need to represent ranges that _include_ the maximum 30 | value in the key domain (e.g. `255u8`) then you will 31 | probably want to use `RangeInclusive`s like `128u8..=255u8`. Sometimes 32 | it may be possible to instead work around this by using a wider key 33 | type than the values you are actually trying to represent (`K=u16` 34 | even though you are only trying to represent ranges covering `u8`) 35 | but in these cases the key domain often represents discrete objects 36 | rather than points on a continuum, and so `RangeInclusive` may 37 | be a more natural way to express these ranges anyway. 38 | - If you are using `RangeInclusive`, then it must be possible to define 39 | _successor_ and _predecessor_ functions for your key type `K`, 40 | because adjacent ranges can not be detected (and thereby coalesced) 41 | simply by testing their ends for equality. For key types that represent 42 | points on a continuum, defining these functions may be awkward and error-prone. 43 | For key types that represent discrete objects, this is usually much 44 | more straightforward. 45 | 46 | 47 | # Example: use with Chrono 48 | 49 | ```rust 50 | use chrono::offset::TimeZone; 51 | use chrono::{Duration, Utc}; 52 | use rangemap::RangeMap; 53 | 54 | let people = ["Alice", "Bob", "Carol"]; 55 | let mut roster = RangeMap::new(); 56 | 57 | // Set up initial roster. 58 | let start_of_roster = Utc.ymd(2019, 1, 7); 59 | let mut week_start = start_of_roster; 60 | for _ in 0..3 { 61 | for person in &people { 62 | let next_week = week_start + Duration::weeks(1); 63 | roster.insert(week_start..next_week, person); 64 | week_start = next_week; 65 | } 66 | } 67 | 68 | // Bob is covering Alice's second shift (the fourth shift overall). 69 | let fourth_shift_start = start_of_roster + Duration::weeks(3); 70 | let fourth_shift_end = fourth_shift_start + Duration::weeks(1); 71 | roster.insert(fourth_shift_start..fourth_shift_end, &"Bob"); 72 | 73 | for (range, person) in roster.iter() { 74 | println!("{} ({}): {}", range.start, range.end - range.start, person); 75 | } 76 | 77 | // Output: 78 | // 2019-01-07UTC (P7D): Alice 79 | // 2019-01-14UTC (P7D): Bob 80 | // 2019-01-21UTC (P7D): Carol 81 | // 2019-01-28UTC (P14D): Bob 82 | // 2019-02-11UTC (P7D): Carol 83 | // 2019-02-18UTC (P7D): Alice 84 | // 2019-02-25UTC (P7D): Bob 85 | // 2019-03-04UTC (P7D): Carol 86 | ``` 87 | 88 | 89 | ## Crate features 90 | 91 | By default this crate has no dependencies on other crates. 92 | 93 | If you enable the **serde1** feature it will introduce a dependency on 94 | the _serde_ crate and provide `Serialize` and `Deserialize` 95 | implementations for all map and set types in this crate. 96 | 97 | You can enable the **serde1** feature in your _Cargo.toml_ file like so: 98 | 99 | ```toml 100 | [dependencies] 101 | rangemap = { version = "1", features = ["serde1"] } 102 | ``` 103 | 104 | You can similarly enable support for _quickcheck_ by enabling 105 | the **quickcheck** feature. 106 | 107 | 108 | ## Building without the Rust standard library 109 | 110 | This crate can work without the full standard library available 111 | (e.g. when running on bare metal without an operating system) 112 | but relies on the presence of a global allocator — 113 | i.e. it links the `core` and `alloc` crates, but not `std`. 114 | 115 | Presently there is no functionality in the crate that require 116 | the standard library. Such functionality will likely be 117 | introduced in the future, and will be gated behind a default-on 118 | `std` feature. 119 | 120 | See [The Rust Programming Language](https://doc.rust-lang.org/1.7.0/book/no-stdlib.html) 121 | book for general information about operating without the standard library. 122 | 123 | 124 | 125 | [`RangeMap`]: crate::RangeMap 126 | [`RangeInclusiveMap`]: crate::RangeInclusiveMap 127 | [`RangeSet`]: crate::RangeSet 128 | [`RangeInclusiveSet`]: crate::RangeInclusiveSet 129 | [`Range`]: core::ops::Range 130 | [`RangeInclusive`]: core::ops::RangeInclusive 131 | 132 | */ 133 | 134 | #![no_std] 135 | extern crate alloc; 136 | 137 | pub mod inclusive_map; 138 | pub mod inclusive_set; 139 | pub mod map; 140 | pub(crate) mod operations; 141 | pub mod set; 142 | 143 | #[cfg(test)] 144 | mod dense; 145 | mod range_wrapper; 146 | mod std_ext; 147 | 148 | pub use inclusive_map::RangeInclusiveMap; 149 | pub use inclusive_set::RangeInclusiveSet; 150 | pub use map::RangeMap; 151 | pub use set::RangeSet; 152 | pub use std_ext::{StepFns, StepLite}; 153 | 154 | // Doc tests for README. 155 | #[cfg(feature = "nightly")] 156 | mod readme; 157 | -------------------------------------------------------------------------------- /src/map.rs: -------------------------------------------------------------------------------- 1 | use super::range_wrapper::RangeStartWrapper; 2 | use crate::range_wrapper::RangeEndWrapper; 3 | use crate::std_ext::*; 4 | use alloc::collections::BTreeMap; 5 | use core::borrow::Borrow; 6 | use core::cmp::Ordering; 7 | use core::fmt::{self, Debug}; 8 | use core::hash::Hash; 9 | use core::iter::{DoubleEndedIterator, FromIterator}; 10 | use core::ops::{Bound, Range}; 11 | use core::prelude::v1::*; 12 | 13 | #[cfg(feature = "serde1")] 14 | use core::marker::PhantomData; 15 | #[cfg(feature = "serde1")] 16 | use serde::{ 17 | de::{Deserialize, Deserializer, SeqAccess, Visitor}, 18 | ser::{Serialize, Serializer}, 19 | }; 20 | 21 | /// A map whose keys are stored as (half-open) ranges bounded 22 | /// inclusively below and exclusively above `(start..end)`. 23 | /// 24 | /// Contiguous and overlapping ranges that map to the same value 25 | /// are coalesced into a single range. 26 | #[derive(Clone, Eq)] 27 | pub struct RangeMap { 28 | // Wrap ranges so that they are `Ord`. 29 | // See `range_wrapper.rs` for explanation. 30 | pub(crate) btm: BTreeMap, V>, 31 | } 32 | 33 | impl Default for RangeMap { 34 | fn default() -> Self { 35 | Self { 36 | btm: BTreeMap::default(), 37 | } 38 | } 39 | } 40 | 41 | impl Hash for RangeMap 42 | where 43 | K: Hash, 44 | V: Hash, 45 | { 46 | fn hash(&self, state: &mut H) { 47 | state.write_usize(self.btm.len()); 48 | for elt in self.iter() { 49 | elt.hash(state); 50 | } 51 | } 52 | } 53 | 54 | impl PartialEq for RangeMap 55 | where 56 | K: PartialEq, 57 | V: PartialEq, 58 | { 59 | fn eq(&self, other: &RangeMap) -> bool { 60 | self.iter().eq(other.iter()) 61 | } 62 | } 63 | 64 | impl PartialOrd for RangeMap 65 | where 66 | K: PartialOrd, 67 | V: PartialOrd, 68 | { 69 | #[inline] 70 | fn partial_cmp(&self, other: &RangeMap) -> Option { 71 | self.expanded_iter().partial_cmp(other.expanded_iter()) 72 | } 73 | } 74 | 75 | impl Ord for RangeMap 76 | where 77 | K: Ord, 78 | V: Ord, 79 | { 80 | #[inline] 81 | fn cmp(&self, other: &RangeMap) -> Ordering { 82 | self.expanded_iter().cmp(other.expanded_iter()) 83 | } 84 | } 85 | 86 | #[cfg(feature = "quickcheck")] 87 | impl quickcheck::Arbitrary for RangeMap 88 | where 89 | K: quickcheck::Arbitrary + Ord, 90 | V: quickcheck::Arbitrary + Eq, 91 | { 92 | fn arbitrary(g: &mut quickcheck::Gen) -> Self { 93 | // REVISIT: allocation could be avoided if Gen::gen_size were public (https://github.com/BurntSushi/quickcheck/issues/326#issue-2653601170) 94 | , _)>>::arbitrary(g) 95 | .into_iter() 96 | .filter(|(range, _)| !range.is_empty()) 97 | .collect() 98 | } 99 | } 100 | 101 | impl RangeMap { 102 | /// Makes a new empty `RangeMap`. 103 | #[cfg(feature = "const_fn")] 104 | pub const fn new() -> Self { 105 | RangeMap { 106 | btm: BTreeMap::new(), 107 | } 108 | } 109 | 110 | /// Makes a new empty `RangeMap`. 111 | #[cfg(not(feature = "const_fn"))] 112 | pub fn new() -> Self { 113 | RangeMap { 114 | btm: BTreeMap::new(), 115 | } 116 | } 117 | 118 | /// Gets an iterator over all pairs of key range and value, 119 | /// ordered by key range. 120 | /// 121 | /// The iterator element type is `(&'a Range, &'a V)`. 122 | pub fn iter(&self) -> Iter<'_, K, V> { 123 | Iter { 124 | inner: self.btm.iter(), 125 | } 126 | } 127 | 128 | /// Clears the map, removing all elements. 129 | pub fn clear(&mut self) { 130 | self.btm.clear(); 131 | } 132 | 133 | /// Returns the number of elements in the map. 134 | pub fn len(&self) -> usize { 135 | self.btm.len() 136 | } 137 | 138 | /// Returns true if the map contains no elements. 139 | pub fn is_empty(&self) -> bool { 140 | self.btm.is_empty() 141 | } 142 | 143 | /// Returns an iterator that includes both ends of the key range. 144 | /// 145 | /// Mainly used for comparisons. 146 | fn expanded_iter(&self) -> impl Iterator { 147 | self.btm.iter().map(|(k, v)| (&k.start, &k.end, v)) 148 | } 149 | } 150 | 151 | impl RangeMap 152 | where 153 | K: Ord + Clone, 154 | { 155 | /// Returns a reference to the value corresponding to the given key, 156 | /// if the key is covered by any range in the map. 157 | pub fn get(&self, key: &K) -> Option<&V> { 158 | self.get_key_value(key).map(|(_range, value)| value) 159 | } 160 | 161 | /// Returns the range-value pair (as a pair of references) corresponding 162 | /// to the given key, if the key is covered by any range in the map. 163 | pub fn get_key_value(&self, key: &K) -> Option<(&Range, &V)> { 164 | // The only stored range that could contain the given key is the 165 | // last stored range whose start is less than or equal to this key. 166 | let key_as_start = RangeStartWrapper::new(key.clone()..key.clone()); 167 | self.btm 168 | .range((Bound::Unbounded, Bound::Included(key_as_start))) 169 | .next_back() 170 | .filter(|(start_wrapper, _value)| { 171 | // Does the only candidate range contain 172 | // the requested key? 173 | start_wrapper.end_wrapper.range.contains(key) 174 | }) 175 | .map(|(start_wrapper, value)| (&start_wrapper.end_wrapper.range, value)) 176 | } 177 | 178 | /// Returns `true` if any range in the map covers the specified key. 179 | pub fn contains_key(&self, key: &K) -> bool { 180 | self.get(key).is_some() 181 | } 182 | 183 | /// Gets an iterator over all the maximally-sized ranges 184 | /// contained in `outer_range` that are not covered by 185 | /// any range stored in the map. 186 | /// 187 | /// If the start and end of the outer range are the same 188 | /// and it does not overlap any stored range, then a single 189 | /// empty gap will be returned. 190 | /// 191 | /// The iterator element type is `Range`. 192 | pub fn gaps<'a>(&'a self, outer_range: &'a Range) -> Gaps<'a, K, V> { 193 | let overlap_iter = self.overlapping(outer_range); 194 | Gaps { 195 | candidate_start: &outer_range.start, 196 | query_end: &outer_range.end, 197 | btm_range_iter: overlap_iter.btm_range_iter, 198 | } 199 | } 200 | 201 | /// Gets an iterator over all the stored ranges that are 202 | /// either partially or completely overlapped by the given range. 203 | pub fn overlapping>>(&self, range: R) -> Overlapping { 204 | // Find the first matching stored range by its _end_, 205 | // using sneaky layering and `Borrow` implementation. (See `range_wrappers` module.) 206 | let start_sliver = 207 | RangeEndWrapper::new(range.borrow().start.clone()..range.borrow().start.clone()); 208 | let btm_range_iter = self 209 | .btm 210 | .range::, (Bound<&RangeEndWrapper>, Bound<_>)>(( 211 | Bound::Excluded(&start_sliver), 212 | Bound::Unbounded, 213 | )); 214 | Overlapping { 215 | query_range: range, 216 | btm_range_iter, 217 | } 218 | } 219 | 220 | /// Returns `true` if any range in the map completely or partially 221 | /// overlaps the given range. 222 | pub fn overlaps(&self, range: &Range) -> bool { 223 | self.overlapping(range).next().is_some() 224 | } 225 | 226 | /// Returns the first range-value pair in this map, if one exists. The range in this pair is the 227 | /// minimum range in the map. 228 | pub fn first_range_value(&self) -> Option<(&Range, &V)> { 229 | self.btm 230 | .first_key_value() 231 | .map(|(range, value)| (&range.end_wrapper.range, value)) 232 | } 233 | 234 | /// Returns the last range-value pair in this map, if one exists. The range in this pair is the 235 | /// maximum range in the map. 236 | pub fn last_range_value(&self) -> Option<(&Range, &V)> { 237 | self.btm 238 | .last_key_value() 239 | .map(|(range, value)| (&range.end_wrapper.range, value)) 240 | } 241 | } 242 | 243 | impl RangeMap 244 | where 245 | K: Ord + Clone, 246 | V: Eq + Clone, 247 | { 248 | /// Insert a pair of key range and value into the map. 249 | /// 250 | /// If the inserted range partially or completely overlaps any 251 | /// existing range in the map, then the existing range (or ranges) will be 252 | /// partially or completely replaced by the inserted range. 253 | /// 254 | /// If the inserted range either overlaps or is immediately adjacent 255 | /// any existing range _mapping to the same value_, then the ranges 256 | /// will be coalesced into a single contiguous range. 257 | /// 258 | /// # Panics 259 | /// 260 | /// Panics if range `start >= end`. 261 | pub fn insert(&mut self, range: Range, value: V) { 262 | // We don't want to have to make empty ranges make sense; 263 | // they don't represent anything meaningful in this structure. 264 | assert!(range.start < range.end); 265 | 266 | // Wrap up the given range so that we can "borrow" 267 | // it as a wrapper reference to either its start or end. 268 | // See `range_wrapper.rs` for explanation of these hacks. 269 | let mut new_start_wrapper: RangeStartWrapper = RangeStartWrapper::new(range); 270 | let new_value = value; 271 | 272 | // Is there a stored range either overlapping the start of 273 | // the range to insert or immediately preceding it? 274 | // 275 | // If there is any such stored range, it will be the last 276 | // whose start is less than or equal to the start of the range to insert, 277 | // or the one before that if both of the above cases exist. 278 | let mut candidates = self 279 | .btm 280 | .range::, (Bound<&RangeStartWrapper>, Bound<&RangeStartWrapper>)>(( 281 | Bound::Unbounded, 282 | Bound::Included(&new_start_wrapper), 283 | )) 284 | .rev() 285 | .take(2) 286 | .filter(|(stored_start_wrapper, _stored_value)| { 287 | // Does the candidate range either overlap 288 | // or immediately precede the range to insert? 289 | // (Remember that it might actually cover the _whole_ 290 | // range to insert and then some.) 291 | stored_start_wrapper 292 | .end_wrapper 293 | .range 294 | .touches(&new_start_wrapper.end_wrapper.range) 295 | }); 296 | if let Some(mut candidate) = candidates.next() { 297 | // Or the one before it if both cases described above exist. 298 | if let Some(another_candidate) = candidates.next() { 299 | candidate = another_candidate; 300 | } 301 | let (stored_start_wrapper, stored_value) = (candidate.0.clone(), candidate.1.clone()); 302 | self.adjust_touching_ranges_for_insert( 303 | stored_start_wrapper, 304 | stored_value, 305 | &mut new_start_wrapper.end_wrapper.range, 306 | &new_value, 307 | ); 308 | } 309 | 310 | // Are there any stored ranges whose heads overlap or immediately 311 | // follow the range to insert? 312 | // 313 | // If there are any such stored ranges (that weren't already caught above), 314 | // their starts will fall somewhere after the start of the range to insert, 315 | // and on or before its end. 316 | // 317 | // This time around, if the latter holds, it also implies 318 | // the former so we don't need to check here if they touch. 319 | // 320 | // REVISIT: Possible micro-optimisation: `impl Borrow for RangeStartWrapper` 321 | // and use that to search here, to avoid constructing another `RangeStartWrapper`. 322 | let new_range_end_as_start = RangeStartWrapper::new( 323 | new_start_wrapper.end_wrapper.range.end.clone() 324 | ..new_start_wrapper.end_wrapper.range.end.clone(), 325 | ); 326 | while let Some((stored_start_wrapper, stored_value)) = self 327 | .btm 328 | .range::, (Bound<&RangeStartWrapper>, Bound<&RangeStartWrapper>)>(( 329 | Bound::Included(&new_start_wrapper), 330 | Bound::Included(&new_range_end_as_start), 331 | )) 332 | .next() 333 | { 334 | // One extra exception: if we have different values, 335 | // and the stored range starts at the end of the range to insert, 336 | // then we don't want to keep looping forever trying to find more! 337 | #[allow(clippy::suspicious_operation_groupings)] 338 | if stored_start_wrapper.end_wrapper.range.start 339 | == new_start_wrapper.end_wrapper.range.end 340 | && *stored_value != new_value 341 | { 342 | // We're beyond the last stored range that could be relevant. 343 | // Avoid wasting time on irrelevant ranges, or even worse, looping forever. 344 | // (`adjust_touching_ranges_for_insert` below assumes that the given range 345 | // is relevant, and behaves very poorly if it is handed a range that it 346 | // shouldn't be touching.) 347 | break; 348 | } 349 | 350 | let stored_start_wrapper = stored_start_wrapper.clone(); 351 | let stored_value = stored_value.clone(); 352 | 353 | self.adjust_touching_ranges_for_insert( 354 | stored_start_wrapper, 355 | stored_value, 356 | &mut new_start_wrapper.end_wrapper.range, 357 | &new_value, 358 | ); 359 | } 360 | 361 | // Insert the (possibly expanded) new range, and we're done! 362 | self.btm.insert(new_start_wrapper, new_value); 363 | } 364 | 365 | /// Removes a range from the map, if all or any of it was present. 366 | /// 367 | /// If the range to be removed _partially_ overlaps any ranges 368 | /// in the map, then those ranges will be contracted to no 369 | /// longer cover the removed range. 370 | /// 371 | /// 372 | /// # Panics 373 | /// 374 | /// Panics if range `start >= end`. 375 | pub fn remove(&mut self, range: Range) { 376 | // We don't want to have to make empty ranges make sense; 377 | // they don't represent anything meaningful in this structure. 378 | assert!(range.start < range.end); 379 | 380 | let start_wrapper: RangeStartWrapper = RangeStartWrapper::new(range); 381 | let range = &start_wrapper.end_wrapper.range; 382 | 383 | // Is there a stored range overlapping the start of 384 | // the range to insert? 385 | // 386 | // If there is any such stored range, it will be the last 387 | // whose start is less than or equal to the start of the range to insert. 388 | if let Some((stored_start_wrapper, stored_value)) = self 389 | .btm 390 | .range::, (Bound<&RangeStartWrapper>, Bound<&RangeStartWrapper>)>((Bound::Unbounded, Bound::Included(&start_wrapper))) 391 | .next_back() 392 | .filter(|(stored_start_wrapper, _stored_value)| { 393 | // Does the only candidate range overlap 394 | // the range to insert? 395 | stored_start_wrapper 396 | .end_wrapper 397 | .range 398 | .overlaps(range) 399 | }) 400 | .map(|(stored_start_wrapper, stored_value)| { 401 | (stored_start_wrapper.clone(), stored_value.clone()) 402 | }) 403 | { 404 | self.adjust_overlapping_ranges_for_remove( 405 | stored_start_wrapper, 406 | stored_value, 407 | range, 408 | ); 409 | } 410 | 411 | // Are there any stored ranges whose heads overlap the range to insert? 412 | // 413 | // If there are any such stored ranges (that weren't already caught above), 414 | // their starts will fall somewhere after the start of the range to insert, 415 | // and before its end. 416 | // 417 | // REVISIT: Possible micro-optimisation: `impl Borrow for RangeStartWrapper` 418 | // and use that to search here, to avoid constructing another `RangeStartWrapper`. 419 | let new_range_end_as_start = RangeStartWrapper::new(range.end.clone()..range.end.clone()); 420 | while let Some((stored_start_wrapper, stored_value)) = self 421 | .btm 422 | .range::, (Bound<&RangeStartWrapper>, Bound<&RangeStartWrapper>)>(( 423 | Bound::Excluded(&start_wrapper), 424 | Bound::Excluded(&new_range_end_as_start), 425 | )) 426 | .next() 427 | .map(|(stored_start_wrapper, stored_value)| { 428 | (stored_start_wrapper.clone(), stored_value.clone()) 429 | }) 430 | { 431 | self.adjust_overlapping_ranges_for_remove( 432 | stored_start_wrapper, 433 | stored_value, 434 | range, 435 | ); 436 | } 437 | } 438 | 439 | fn adjust_touching_ranges_for_insert( 440 | &mut self, 441 | stored_start_wrapper: RangeStartWrapper, 442 | stored_value: V, 443 | new_range: &mut Range, 444 | new_value: &V, 445 | ) { 446 | use core::cmp::{max, min}; 447 | 448 | if stored_value == *new_value { 449 | // The ranges have the same value, so we can "adopt" 450 | // the stored range. 451 | // 452 | // This means that no matter how big or where the stored range is, 453 | // we will expand the new range's bounds to subsume it, 454 | // and then delete the stored range. 455 | new_range.start = min(&new_range.start, &stored_start_wrapper.start).clone(); 456 | new_range.end = max(&new_range.end, &stored_start_wrapper.end).clone(); 457 | self.btm.remove(&stored_start_wrapper); 458 | } else { 459 | // The ranges have different values. 460 | if new_range.overlaps(&stored_start_wrapper.range) { 461 | // The ranges overlap. This is a little bit more complicated. 462 | // Delete the stored range, and then add back between 463 | // 0 and 2 subranges at the ends of the range to insert. 464 | self.btm.remove(&stored_start_wrapper); 465 | if stored_start_wrapper.start < new_range.start { 466 | // Insert the piece left of the range to insert. 467 | self.btm.insert( 468 | RangeStartWrapper::new( 469 | stored_start_wrapper.end_wrapper.range.start..new_range.start.clone(), 470 | ), 471 | stored_value.clone(), 472 | ); 473 | } 474 | if stored_start_wrapper.end_wrapper.range.end > new_range.end { 475 | // Insert the piece right of the range to insert. 476 | self.btm.insert( 477 | RangeStartWrapper::new( 478 | new_range.end.clone()..stored_start_wrapper.end_wrapper.range.end, 479 | ), 480 | stored_value, 481 | ); 482 | } 483 | } else { 484 | // No-op; they're not overlapping, 485 | // so we can just keep both ranges as they are. 486 | } 487 | } 488 | } 489 | 490 | fn adjust_overlapping_ranges_for_remove( 491 | &mut self, 492 | stored: RangeStartWrapper, 493 | stored_value: V, 494 | range_to_remove: &Range, 495 | ) { 496 | // Delete the stored range, and then add back between 497 | // 0 and 2 subranges at the ends of the range to insert. 498 | self.btm.remove(&stored); 499 | let stored_range = stored.end_wrapper; 500 | if stored_range.start < range_to_remove.start { 501 | // Insert the piece left of the range to insert. 502 | self.btm.insert( 503 | RangeStartWrapper::new(stored_range.range.start..range_to_remove.start.clone()), 504 | stored_value.clone(), 505 | ); 506 | } 507 | if stored_range.range.end > range_to_remove.end { 508 | // Insert the piece right of the range to insert. 509 | self.btm.insert( 510 | RangeStartWrapper::new(range_to_remove.end.clone()..stored_range.range.end), 511 | stored_value, 512 | ); 513 | } 514 | } 515 | } 516 | 517 | /// An iterator over the entries of a `RangeMap`, ordered by key range. 518 | /// 519 | /// The iterator element type is `(&'a Range, &'a V)`. 520 | /// 521 | /// This `struct` is created by the [`iter`] method on [`RangeMap`]. See its 522 | /// documentation for more. 523 | /// 524 | /// [`iter`]: RangeMap::iter 525 | pub struct Iter<'a, K, V> { 526 | inner: alloc::collections::btree_map::Iter<'a, RangeStartWrapper, V>, 527 | } 528 | 529 | impl<'a, K, V> Iterator for Iter<'a, K, V> 530 | where 531 | K: 'a, 532 | V: 'a, 533 | { 534 | type Item = (&'a Range, &'a V); 535 | 536 | fn next(&mut self) -> Option { 537 | self.inner 538 | .next() 539 | .map(|(by_start, v)| (&by_start.end_wrapper.range, v)) 540 | } 541 | 542 | fn size_hint(&self) -> (usize, Option) { 543 | self.inner.size_hint() 544 | } 545 | } 546 | 547 | impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> 548 | where 549 | K: 'a, 550 | V: 'a, 551 | { 552 | fn next_back(&mut self) -> Option { 553 | self.inner 554 | .next_back() 555 | .map(|(range, value)| (&range.end_wrapper.range, value)) 556 | } 557 | } 558 | 559 | /// An owning iterator over the entries of a `RangeMap`, ordered by key range. 560 | /// 561 | /// The iterator element type is `(Range, V)`. 562 | /// 563 | /// This `struct` is created by the [`into_iter`] method on [`RangeMap`] 564 | /// (provided by the `IntoIterator` trait). See its documentation for more. 565 | /// 566 | /// [`into_iter`]: IntoIterator::into_iter 567 | pub struct IntoIter { 568 | inner: alloc::collections::btree_map::IntoIter, V>, 569 | } 570 | 571 | impl IntoIterator for RangeMap { 572 | type Item = (Range, V); 573 | type IntoIter = IntoIter; 574 | fn into_iter(self) -> Self::IntoIter { 575 | IntoIter { 576 | inner: self.btm.into_iter(), 577 | } 578 | } 579 | } 580 | 581 | impl Iterator for IntoIter { 582 | type Item = (Range, V); 583 | fn next(&mut self) -> Option<(Range, V)> { 584 | self.inner 585 | .next() 586 | .map(|(by_start, v)| (by_start.end_wrapper.range, v)) 587 | } 588 | fn size_hint(&self) -> (usize, Option) { 589 | self.inner.size_hint() 590 | } 591 | } 592 | 593 | impl DoubleEndedIterator for IntoIter { 594 | fn next_back(&mut self) -> Option { 595 | self.inner 596 | .next_back() 597 | .map(|(range, value)| (range.end_wrapper.range, value)) 598 | } 599 | } 600 | 601 | // We can't just derive this automatically, because that would 602 | // expose irrelevant (and private) implementation details. 603 | // Instead implement it in the same way that the underlying BTreeMap does. 604 | impl Debug for RangeMap { 605 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 606 | f.debug_map().entries(self.iter()).finish() 607 | } 608 | } 609 | 610 | impl FromIterator<(Range, V)> for RangeMap 611 | where 612 | K: Ord + Clone, 613 | V: Eq + Clone, 614 | { 615 | fn from_iter, V)>>(iter: T) -> Self { 616 | let mut range_map = RangeMap::new(); 617 | range_map.extend(iter); 618 | range_map 619 | } 620 | } 621 | 622 | impl Extend<(Range, V)> for RangeMap 623 | where 624 | K: Ord + Clone, 625 | V: Eq + Clone, 626 | { 627 | fn extend, V)>>(&mut self, iter: T) { 628 | iter.into_iter().for_each(move |(k, v)| { 629 | self.insert(k, v); 630 | }) 631 | } 632 | } 633 | 634 | #[cfg(feature = "serde1")] 635 | impl Serialize for RangeMap 636 | where 637 | K: Serialize, 638 | V: Serialize, 639 | { 640 | fn serialize(&self, serializer: S) -> Result 641 | where 642 | S: Serializer, 643 | { 644 | use serde::ser::SerializeSeq; 645 | let mut seq = serializer.serialize_seq(Some(self.btm.len()))?; 646 | for (k, v) in self.iter() { 647 | seq.serialize_element(&((&k.start, &k.end), &v))?; 648 | } 649 | seq.end() 650 | } 651 | } 652 | 653 | #[cfg(feature = "serde1")] 654 | impl<'de, K, V> Deserialize<'de> for RangeMap 655 | where 656 | K: Ord + Clone + Deserialize<'de>, 657 | V: Eq + Clone + Deserialize<'de>, 658 | { 659 | fn deserialize(deserializer: D) -> Result 660 | where 661 | D: Deserializer<'de>, 662 | { 663 | deserializer.deserialize_seq(RangeMapVisitor::new()) 664 | } 665 | } 666 | 667 | #[cfg(feature = "serde1")] 668 | struct RangeMapVisitor { 669 | marker: PhantomData RangeMap>, 670 | } 671 | 672 | #[cfg(feature = "serde1")] 673 | impl RangeMapVisitor { 674 | fn new() -> Self { 675 | RangeMapVisitor { 676 | marker: PhantomData, 677 | } 678 | } 679 | } 680 | 681 | #[cfg(feature = "serde1")] 682 | impl<'de, K, V> Visitor<'de> for RangeMapVisitor 683 | where 684 | K: Ord + Clone + Deserialize<'de>, 685 | V: Eq + Clone + Deserialize<'de>, 686 | { 687 | type Value = RangeMap; 688 | 689 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 690 | formatter.write_str("RangeMap") 691 | } 692 | 693 | fn visit_seq(self, mut access: A) -> Result 694 | where 695 | A: SeqAccess<'de>, 696 | { 697 | let mut range_map = RangeMap::new(); 698 | while let Some(((start, end), value)) = access.next_element()? { 699 | range_map.insert(start..end, value); 700 | } 701 | Ok(range_map) 702 | } 703 | } 704 | 705 | /// An iterator over all ranges not covered by a `RangeMap`. 706 | /// 707 | /// The iterator element type is `Range`. 708 | /// 709 | /// This `struct` is created by the [`gaps`] method on [`RangeMap`]. See its 710 | /// documentation for more. 711 | /// 712 | /// [`gaps`]: RangeMap::gaps 713 | pub struct Gaps<'a, K, V> { 714 | candidate_start: &'a K, 715 | query_end: &'a K, 716 | btm_range_iter: alloc::collections::btree_map::Range<'a, RangeStartWrapper, V>, 717 | } 718 | 719 | // `Gaps` is always fused. (See definition of `next` below.) 720 | impl<'a, K, V> core::iter::FusedIterator for Gaps<'a, K, V> where K: Ord + Clone {} 721 | 722 | impl<'a, K, V> Iterator for Gaps<'a, K, V> 723 | where 724 | K: Ord + Clone, 725 | { 726 | type Item = Range; 727 | 728 | fn next(&mut self) -> Option { 729 | // Keep track of the next range in the map beyond the current returned range. 730 | for overlap in self.btm_range_iter.by_ref() { 731 | let overlap = &overlap.0.range; 732 | 733 | // If the range in the map has advanced beyond the query range, return 734 | // any tail gap. 735 | if *self.query_end <= overlap.start { 736 | break; 737 | } 738 | 739 | let original_start = core::mem::replace(&mut self.candidate_start, &overlap.end); 740 | 741 | // The query range overhangs to the left, return a gap. 742 | if *original_start < overlap.start { 743 | let gap = original_start.clone()..overlap.start.clone(); 744 | return Some(gap); 745 | } 746 | 747 | // The remaining query range starts within the current 748 | // mapped range. 749 | self.candidate_start = &overlap.end; 750 | } 751 | 752 | // Now that we've run out of items, the only other possible 753 | // gap is at the end of the query range. 754 | if *self.candidate_start < *self.query_end { 755 | let gap = self.candidate_start.clone()..self.query_end.clone(); 756 | self.candidate_start = self.query_end; 757 | return Some(gap); 758 | } 759 | 760 | None 761 | } 762 | } 763 | 764 | /// An iterator over all stored ranges partially or completely 765 | /// overlapped by a given range. 766 | /// 767 | /// The iterator element type is `(&'a Range, &'a V)`. 768 | /// 769 | /// This `struct` is created by the [`overlapping`] method on [`RangeMap`]. See its 770 | /// documentation for more. 771 | /// 772 | /// [`overlapping`]: RangeMap::overlapping 773 | pub struct Overlapping<'a, K, V, R: Borrow> = &'a Range> { 774 | query_range: R, 775 | btm_range_iter: alloc::collections::btree_map::Range<'a, RangeStartWrapper, V>, 776 | } 777 | 778 | // `Overlapping` is always fused. (See definition of `next` below.) 779 | impl<'a, K, V, R: Borrow>> core::iter::FusedIterator for Overlapping<'a, K, V, R> where 780 | K: Ord 781 | { 782 | } 783 | 784 | impl<'a, K, V, R: Borrow>> Iterator for Overlapping<'a, K, V, R> 785 | where 786 | K: Ord, 787 | { 788 | type Item = (&'a Range, &'a V); 789 | 790 | fn next(&mut self) -> Option { 791 | if let Some((k, v)) = self.btm_range_iter.next() { 792 | if k.start < self.query_range.borrow().end { 793 | Some((&k.range, v)) 794 | } else { 795 | // The rest of the items in the underlying iterator 796 | // are past the query range. We can keep taking items 797 | // from that iterator and this will remain true, 798 | // so this is enough to make the iterator fused. 799 | None 800 | } 801 | } else { 802 | None 803 | } 804 | } 805 | } 806 | 807 | impl<'a, K, V, R: Borrow>> DoubleEndedIterator for Overlapping<'a, K, V, R> 808 | where 809 | K: Ord, 810 | { 811 | fn next_back(&mut self) -> Option { 812 | while let Some((k, v)) = self.btm_range_iter.next_back() { 813 | if k.start < self.query_range.borrow().end { 814 | return Some((&k.range, v)); 815 | } 816 | } 817 | 818 | None 819 | } 820 | } 821 | 822 | impl From<[(Range, V); N]> for RangeMap { 823 | fn from(value: [(Range, V); N]) -> Self { 824 | let mut map = Self::new(); 825 | for (range, value) in IntoIterator::into_iter(value) { 826 | map.insert(range, value); 827 | } 828 | map 829 | } 830 | } 831 | 832 | /// Create a [`RangeMap`] from key-value pairs. 833 | /// 834 | /// # Example 835 | /// 836 | /// ```rust 837 | /// # use rangemap::range_map; 838 | /// let map = range_map!{ 839 | /// 0..100 => "abc", 840 | /// 100..200 => "def", 841 | /// 200..300 => "ghi" 842 | /// }; 843 | /// ``` 844 | #[macro_export] 845 | macro_rules! range_map { 846 | ($($k:expr => $v:expr),* $(,)?) => {{ 847 | $crate::RangeMap::from([$(($k, $v)),*]) 848 | }}; 849 | } 850 | 851 | #[cfg(test)] 852 | mod tests { 853 | use super::*; 854 | use alloc as std; 855 | use alloc::{format, string::String, vec, vec::Vec}; 856 | use proptest::prelude::*; 857 | use test_strategy::proptest; 858 | 859 | impl Arbitrary for RangeMap 860 | where 861 | K: Ord + Clone + Debug + Arbitrary + 'static, 862 | V: Clone + Eq + Arbitrary + 'static, 863 | { 864 | type Parameters = (); 865 | type Strategy = BoxedStrategy; 866 | 867 | fn arbitrary_with(_parameters: Self::Parameters) -> Self::Strategy { 868 | any::, V)>>() 869 | .prop_map(|ranges| ranges.into_iter().collect::>()) 870 | .boxed() 871 | } 872 | } 873 | 874 | #[proptest] 875 | fn test_first(set: RangeMap) { 876 | assert_eq!( 877 | set.first_range_value(), 878 | set.iter().min_by_key(|(range, _)| range.start) 879 | ); 880 | } 881 | 882 | #[proptest] 883 | #[allow(clippy::len_zero)] 884 | fn test_len(mut map: RangeMap) { 885 | assert_eq!(map.len(), map.iter().count()); 886 | assert_eq!(map.is_empty(), map.len() == 0); 887 | map.clear(); 888 | assert_eq!(map.len(), 0); 889 | assert!(map.is_empty()); 890 | assert_eq!(map.iter().count(), 0); 891 | } 892 | 893 | #[proptest] 894 | fn test_last(set: RangeMap) { 895 | assert_eq!( 896 | set.last_range_value(), 897 | set.iter().max_by_key(|(range, _)| range.end) 898 | ); 899 | } 900 | 901 | #[proptest] 902 | fn test_iter_reversible(set: RangeMap) { 903 | let forward: Vec<_> = set.iter().collect(); 904 | let mut backward: Vec<_> = set.iter().rev().collect(); 905 | backward.reverse(); 906 | assert_eq!(forward, backward); 907 | } 908 | 909 | #[proptest] 910 | fn test_into_iter_reversible(set: RangeMap) { 911 | let forward: Vec<_> = set.clone().into_iter().collect(); 912 | let mut backward: Vec<_> = set.into_iter().rev().collect(); 913 | backward.reverse(); 914 | assert_eq!(forward, backward); 915 | } 916 | 917 | #[proptest] 918 | fn test_overlapping_reversible(set: RangeMap, range: Range) { 919 | let forward: Vec<_> = set.overlapping(&range).collect(); 920 | let mut backward: Vec<_> = set.overlapping(&range).rev().collect(); 921 | backward.reverse(); 922 | assert_eq!(forward, backward); 923 | } 924 | 925 | #[proptest] 926 | fn test_arbitrary_map_u8(ranges: Vec<(Range, String)>) { 927 | let ranges: Vec<_> = ranges 928 | .into_iter() 929 | .filter(|(range, _value)| range.start != range.end) 930 | .collect(); 931 | let set = ranges 932 | .iter() 933 | .fold(RangeMap::new(), |mut set, (range, value)| { 934 | set.insert(range.clone(), value.clone()); 935 | set 936 | }); 937 | 938 | for value in 0..u8::MAX { 939 | assert_eq!( 940 | set.get(&value), 941 | ranges 942 | .iter() 943 | .rev() 944 | .find(|(range, _value)| range.contains(&value)) 945 | .map(|(_range, value)| value) 946 | ); 947 | } 948 | } 949 | 950 | #[proptest] 951 | #[allow(deprecated)] 952 | fn test_hash(left: RangeMap, right: RangeMap) { 953 | use core::hash::{Hash, Hasher, SipHasher}; 954 | 955 | let hash = |set: &RangeMap<_, _>| { 956 | let mut hasher = SipHasher::new(); 957 | set.hash(&mut hasher); 958 | hasher.finish() 959 | }; 960 | 961 | if left == right { 962 | assert!( 963 | hash(&left) == hash(&right), 964 | "if two values are equal, their hash must be equal" 965 | ); 966 | } 967 | 968 | // if the hashes are equal the values might not be the same (collision) 969 | if hash(&left) != hash(&right) { 970 | assert!( 971 | left != right, 972 | "if two value's hashes are not equal, they must not be equal" 973 | ); 974 | } 975 | } 976 | 977 | #[proptest] 978 | fn test_ord(left: RangeMap, right: RangeMap) { 979 | assert_eq!( 980 | left == right, 981 | left.cmp(&right).is_eq(), 982 | "ordering and equality must match" 983 | ); 984 | assert_eq!( 985 | left.cmp(&right), 986 | left.partial_cmp(&right).unwrap(), 987 | "ordering is total for ordered parameters" 988 | ); 989 | } 990 | 991 | #[test] 992 | fn test_from_array() { 993 | let mut map = RangeMap::new(); 994 | map.insert(0..100, "hello"); 995 | map.insert(200..300, "world"); 996 | assert_eq!( 997 | map, 998 | RangeMap::from([(0..100, "hello"), (200..300, "world")]) 999 | ); 1000 | } 1001 | 1002 | #[test] 1003 | fn test_macro() { 1004 | assert_eq!(range_map![], RangeMap::::default()); 1005 | assert_eq!( 1006 | range_map!(0..100 => "abc", 100..200 => "def", 200..300 => "ghi"), 1007 | [(0..100, "abc"), (100..200, "def"), (200..300, "ghi")] 1008 | .iter() 1009 | .cloned() 1010 | .collect(), 1011 | ); 1012 | } 1013 | 1014 | trait RangeMapExt { 1015 | fn to_vec(&self) -> Vec<(Range, V)>; 1016 | } 1017 | 1018 | impl RangeMapExt for RangeMap 1019 | where 1020 | K: Ord + Clone, 1021 | V: Eq + Clone, 1022 | { 1023 | fn to_vec(&self) -> Vec<(Range, V)> { 1024 | self.iter().map(|(kr, v)| (kr.clone(), v.clone())).collect() 1025 | } 1026 | } 1027 | 1028 | // 1029 | // Insertion tests 1030 | // 1031 | 1032 | #[test] 1033 | fn empty_map_is_empty() { 1034 | let range_map: RangeMap = RangeMap::new(); 1035 | assert_eq!(range_map.to_vec(), vec![]); 1036 | } 1037 | 1038 | #[test] 1039 | fn insert_into_empty_map() { 1040 | let mut range_map: RangeMap = RangeMap::new(); 1041 | range_map.insert(0..50, false); 1042 | assert_eq!(range_map.to_vec(), vec![(0..50, false)]); 1043 | } 1044 | 1045 | #[test] 1046 | fn new_same_value_immediately_following_stored() { 1047 | let mut range_map: RangeMap = RangeMap::new(); 1048 | // 0 1 2 3 4 5 6 7 8 9 1049 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1050 | range_map.insert(1..3, false); 1051 | // 0 1 2 3 4 5 6 7 8 9 1052 | // ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ 1053 | range_map.insert(3..5, false); 1054 | // 0 1 2 3 4 5 6 7 8 9 1055 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1056 | assert_eq!(range_map.to_vec(), vec![(1..5, false)]); 1057 | } 1058 | 1059 | #[test] 1060 | fn new_different_value_immediately_following_stored() { 1061 | let mut range_map: RangeMap = RangeMap::new(); 1062 | // 0 1 2 3 4 5 6 7 8 9 1063 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1064 | range_map.insert(1..3, false); 1065 | // 0 1 2 3 4 5 6 7 8 9 1066 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1067 | range_map.insert(3..5, true); 1068 | // 0 1 2 3 4 5 6 7 8 9 1069 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1070 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1071 | assert_eq!(range_map.to_vec(), vec![(1..3, false), (3..5, true)]); 1072 | } 1073 | 1074 | #[test] 1075 | fn new_same_value_overlapping_end_of_stored() { 1076 | let mut range_map: RangeMap = RangeMap::new(); 1077 | // 0 1 2 3 4 5 6 7 8 9 1078 | // ◌ ●-----◌ ◌ ◌ ◌ ◌ ◌ 1079 | range_map.insert(1..4, false); 1080 | // 0 1 2 3 4 5 6 7 8 9 1081 | // ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ 1082 | range_map.insert(3..5, false); 1083 | // 0 1 2 3 4 5 6 7 8 9 1084 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1085 | assert_eq!(range_map.to_vec(), vec![(1..5, false)]); 1086 | } 1087 | 1088 | #[test] 1089 | fn new_different_value_overlapping_end_of_stored() { 1090 | let mut range_map: RangeMap = RangeMap::new(); 1091 | // 0 1 2 3 4 5 6 7 8 9 1092 | // ◌ ●-----◌ ◌ ◌ ◌ ◌ ◌ 1093 | range_map.insert(1..4, false); 1094 | // 0 1 2 3 4 5 6 7 8 9 1095 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1096 | range_map.insert(3..5, true); 1097 | // 0 1 2 3 4 5 6 7 8 9 1098 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1099 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1100 | assert_eq!(range_map.to_vec(), vec![(1..3, false), (3..5, true)]); 1101 | } 1102 | 1103 | #[test] 1104 | fn new_same_value_immediately_preceding_stored() { 1105 | let mut range_map: RangeMap = RangeMap::new(); 1106 | // 0 1 2 3 4 5 6 7 8 9 1107 | // ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ 1108 | range_map.insert(3..5, false); 1109 | // 0 1 2 3 4 5 6 7 8 9 1110 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1111 | range_map.insert(1..3, false); 1112 | // 0 1 2 3 4 5 6 7 8 9 1113 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1114 | assert_eq!(range_map.to_vec(), vec![(1..5, false)]); 1115 | } 1116 | 1117 | #[test] 1118 | fn new_different_value_immediately_preceding_stored() { 1119 | let mut range_map: RangeMap = RangeMap::new(); 1120 | // 0 1 2 3 4 5 6 7 8 9 1121 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1122 | range_map.insert(3..5, true); 1123 | // 0 1 2 3 4 5 6 7 8 9 1124 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1125 | range_map.insert(1..3, false); 1126 | // 0 1 2 3 4 5 6 7 8 9 1127 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1128 | // ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ 1129 | assert_eq!(range_map.to_vec(), vec![(1..3, false), (3..5, true)]); 1130 | } 1131 | 1132 | #[test] 1133 | fn new_same_value_wholly_inside_stored() { 1134 | let mut range_map: RangeMap = RangeMap::new(); 1135 | // 0 1 2 3 4 5 6 7 8 9 1136 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1137 | range_map.insert(1..5, false); 1138 | // 0 1 2 3 4 5 6 7 8 9 1139 | // ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1140 | range_map.insert(2..4, false); 1141 | // 0 1 2 3 4 5 6 7 8 9 1142 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1143 | assert_eq!(range_map.to_vec(), vec![(1..5, false)]); 1144 | } 1145 | 1146 | #[test] 1147 | fn new_different_value_wholly_inside_stored() { 1148 | let mut range_map: RangeMap = RangeMap::new(); 1149 | // 0 1 2 3 4 5 6 7 8 9 1150 | // ◌ ◆-------◇ ◌ ◌ ◌ ◌ 1151 | range_map.insert(1..5, true); 1152 | // 0 1 2 3 4 5 6 7 8 9 1153 | // ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1154 | range_map.insert(2..4, false); 1155 | // 0 1 2 3 4 5 6 7 8 9 1156 | // ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 1157 | // ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ ◌ 1158 | // ◌ ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ 1159 | assert_eq!( 1160 | range_map.to_vec(), 1161 | vec![(1..2, true), (2..4, false), (4..5, true)] 1162 | ); 1163 | } 1164 | 1165 | #[test] 1166 | fn replace_at_end_of_existing_range_should_coalesce() { 1167 | let mut range_map: RangeMap = RangeMap::new(); 1168 | // 0 1 2 3 4 5 6 7 8 9 1169 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1170 | range_map.insert(1..3, false); 1171 | // 0 1 2 3 4 5 6 7 8 9 1172 | // ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ 1173 | range_map.insert(3..5, true); 1174 | // 0 1 2 3 4 5 6 7 8 9 1175 | // ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ ◌ 1176 | range_map.insert(3..5, false); 1177 | // 0 1 2 3 4 5 6 7 8 9 1178 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1179 | assert_eq!(range_map.to_vec(), vec![(1..5, false)]); 1180 | } 1181 | 1182 | #[test] 1183 | // Test every permutation of a bunch of touching and overlapping ranges. 1184 | fn lots_of_interesting_ranges() { 1185 | use crate::dense::DenseU32RangeMap; 1186 | use permutator::Permutation; 1187 | 1188 | let mut ranges_with_values = [ 1189 | (2..3, false), 1190 | // A duplicate duplicates 1191 | (2..3, false), 1192 | // Almost a duplicate, but with a different value 1193 | (2..3, true), 1194 | // A few small ranges, some of them overlapping others, 1195 | // some of them touching others 1196 | (3..5, true), 1197 | (4..6, true), 1198 | (5..7, true), 1199 | // A really big range 1200 | (2..6, true), 1201 | ]; 1202 | 1203 | ranges_with_values.permutation().for_each(|permutation| { 1204 | let mut range_map: RangeMap = RangeMap::new(); 1205 | let mut dense: DenseU32RangeMap = DenseU32RangeMap::new(); 1206 | 1207 | for (k, v) in permutation { 1208 | // Insert it into both maps. 1209 | range_map.insert(k.clone(), v); 1210 | // NOTE: Clippy's `range_minus_one` lint is a bit overzealous here, 1211 | // because we _can't_ pass an open-ended range to `insert`. 1212 | #[allow(clippy::range_minus_one)] 1213 | dense.insert(k.start..=(k.end - 1), v); 1214 | 1215 | // At every step, both maps should contain the same stuff. 1216 | let sparse = range_map.to_vec(); 1217 | let dense = dense.to_end_exclusive_vec(); 1218 | assert_eq!(sparse, dense); 1219 | } 1220 | }); 1221 | } 1222 | 1223 | // 1224 | // Get* tests 1225 | // 1226 | 1227 | #[test] 1228 | fn get() { 1229 | let mut range_map: RangeMap = RangeMap::new(); 1230 | range_map.insert(0..50, false); 1231 | assert_eq!(range_map.get(&49), Some(&false)); 1232 | assert_eq!(range_map.get(&50), None); 1233 | } 1234 | 1235 | #[test] 1236 | fn get_key_value() { 1237 | let mut range_map: RangeMap = RangeMap::new(); 1238 | range_map.insert(0..50, false); 1239 | assert_eq!(range_map.get_key_value(&49), Some((&(0..50), &false))); 1240 | assert_eq!(range_map.get_key_value(&50), None); 1241 | } 1242 | 1243 | // 1244 | // Removal tests 1245 | // 1246 | 1247 | #[test] 1248 | fn remove_from_empty_map() { 1249 | let mut range_map: RangeMap = RangeMap::new(); 1250 | range_map.remove(0..50); 1251 | assert_eq!(range_map.to_vec(), vec![]); 1252 | } 1253 | 1254 | #[test] 1255 | fn remove_non_covered_range_before_stored() { 1256 | let mut range_map: RangeMap = RangeMap::new(); 1257 | range_map.insert(25..75, false); 1258 | range_map.remove(0..25); 1259 | assert_eq!(range_map.to_vec(), vec![(25..75, false)]); 1260 | } 1261 | 1262 | #[test] 1263 | fn remove_non_covered_range_after_stored() { 1264 | let mut range_map: RangeMap = RangeMap::new(); 1265 | range_map.insert(25..75, false); 1266 | range_map.remove(75..100); 1267 | assert_eq!(range_map.to_vec(), vec![(25..75, false)]); 1268 | } 1269 | 1270 | #[test] 1271 | fn remove_overlapping_start_of_stored() { 1272 | let mut range_map: RangeMap = RangeMap::new(); 1273 | range_map.insert(25..75, false); 1274 | range_map.remove(0..30); 1275 | assert_eq!(range_map.to_vec(), vec![(30..75, false)]); 1276 | } 1277 | 1278 | #[test] 1279 | fn remove_middle_of_stored() { 1280 | let mut range_map: RangeMap = RangeMap::new(); 1281 | range_map.insert(25..75, false); 1282 | range_map.remove(30..70); 1283 | assert_eq!(range_map.to_vec(), vec![(25..30, false), (70..75, false)]); 1284 | } 1285 | 1286 | #[test] 1287 | fn remove_overlapping_end_of_stored() { 1288 | let mut range_map: RangeMap = RangeMap::new(); 1289 | range_map.insert(25..75, false); 1290 | range_map.remove(70..100); 1291 | assert_eq!(range_map.to_vec(), vec![(25..70, false)]); 1292 | } 1293 | 1294 | #[test] 1295 | fn remove_exactly_stored() { 1296 | let mut range_map: RangeMap = RangeMap::new(); 1297 | range_map.insert(25..75, false); 1298 | range_map.remove(25..75); 1299 | assert_eq!(range_map.to_vec(), vec![]); 1300 | } 1301 | 1302 | #[test] 1303 | fn remove_superset_of_stored() { 1304 | let mut range_map: RangeMap = RangeMap::new(); 1305 | range_map.insert(25..75, false); 1306 | range_map.remove(0..100); 1307 | assert_eq!(range_map.to_vec(), vec![]); 1308 | } 1309 | 1310 | // Gaps tests 1311 | 1312 | #[test] 1313 | fn whole_range_is_a_gap() { 1314 | // 0 1 2 3 4 5 6 7 8 9 1315 | // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 1316 | let range_map: RangeMap = RangeMap::new(); 1317 | // 0 1 2 3 4 5 6 7 8 9 1318 | // ◌ ◆-------------◇ ◌ 1319 | let outer_range = 1..8; 1320 | let mut gaps = range_map.gaps(&outer_range); 1321 | // Should yield the entire outer range. 1322 | assert_eq!(gaps.next(), Some(1..8)); 1323 | assert_eq!(gaps.next(), None); 1324 | // Gaps iterator should be fused. 1325 | assert_eq!(gaps.next(), None); 1326 | assert_eq!(gaps.next(), None); 1327 | } 1328 | 1329 | #[test] 1330 | fn whole_range_is_covered_exactly() { 1331 | let mut range_map: RangeMap = RangeMap::new(); 1332 | // 0 1 2 3 4 5 6 7 8 9 1333 | // ◌ ●---------◌ ◌ ◌ ◌ 1334 | range_map.insert(1..6, ()); 1335 | // 0 1 2 3 4 5 6 7 8 9 1336 | // ◌ ◆---------◇ ◌ ◌ ◌ 1337 | let outer_range = 1..6; 1338 | let mut gaps = range_map.gaps(&outer_range); 1339 | // Should yield no gaps. 1340 | assert_eq!(gaps.next(), None); 1341 | // Gaps iterator should be fused. 1342 | assert_eq!(gaps.next(), None); 1343 | assert_eq!(gaps.next(), None); 1344 | } 1345 | 1346 | #[test] 1347 | fn item_before_outer_range() { 1348 | let mut range_map: RangeMap = RangeMap::new(); 1349 | // 0 1 2 3 4 5 6 7 8 9 1350 | // ◌ ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ 1351 | range_map.insert(1..3, ()); 1352 | // 0 1 2 3 4 5 6 7 8 9 1353 | // ◌ ◌ ◌ ◌ ◌ ◆-----◇ ◌ 1354 | let outer_range = 5..8; 1355 | let mut gaps = range_map.gaps(&outer_range); 1356 | // Should yield the entire outer range. 1357 | assert_eq!(gaps.next(), Some(5..8)); 1358 | assert_eq!(gaps.next(), None); 1359 | // Gaps iterator should be fused. 1360 | assert_eq!(gaps.next(), None); 1361 | assert_eq!(gaps.next(), None); 1362 | } 1363 | 1364 | #[test] 1365 | fn item_touching_start_of_outer_range() { 1366 | let mut range_map: RangeMap = RangeMap::new(); 1367 | // 0 1 2 3 4 5 6 7 8 9 1368 | // ◌ ●-------◌ ◌ ◌ ◌ ◌ 1369 | range_map.insert(1..5, ()); 1370 | // 0 1 2 3 4 5 6 7 8 9 1371 | // ◌ ◌ ◌ ◌ ◌ ◆-----◇ ◌ 1372 | let outer_range = 5..8; 1373 | let mut gaps = range_map.gaps(&outer_range); 1374 | // Should yield the entire outer range. 1375 | assert_eq!(gaps.next(), Some(5..8)); 1376 | assert_eq!(gaps.next(), None); 1377 | // Gaps iterator should be fused. 1378 | assert_eq!(gaps.next(), None); 1379 | assert_eq!(gaps.next(), None); 1380 | } 1381 | 1382 | #[test] 1383 | fn item_overlapping_start_of_outer_range() { 1384 | let mut range_map: RangeMap = RangeMap::new(); 1385 | // 0 1 2 3 4 5 6 7 8 9 1386 | // ◌ ●---------◌ ◌ ◌ ◌ 1387 | range_map.insert(1..6, ()); 1388 | // 0 1 2 3 4 5 6 7 8 9 1389 | // ◌ ◌ ◌ ◌ ◌ ◆-----◇ ◌ 1390 | let outer_range = 5..8; 1391 | let mut gaps = range_map.gaps(&outer_range); 1392 | // Should yield from the end of the stored item 1393 | // to the end of the outer range. 1394 | assert_eq!(gaps.next(), Some(6..8)); 1395 | assert_eq!(gaps.next(), None); 1396 | // Gaps iterator should be fused. 1397 | assert_eq!(gaps.next(), None); 1398 | assert_eq!(gaps.next(), None); 1399 | } 1400 | 1401 | #[test] 1402 | fn item_starting_at_start_of_outer_range() { 1403 | let mut range_map: RangeMap = RangeMap::new(); 1404 | // 0 1 2 3 4 5 6 7 8 9 1405 | // ◌ ◌ ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ 1406 | range_map.insert(5..6, ()); 1407 | // 0 1 2 3 4 5 6 7 8 9 1408 | // ◌ ◌ ◌ ◌ ◌ ◆-----◇ ◌ 1409 | let outer_range = 5..8; 1410 | let mut gaps = range_map.gaps(&outer_range); 1411 | // Should yield from the item onwards. 1412 | assert_eq!(gaps.next(), Some(6..8)); 1413 | assert_eq!(gaps.next(), None); 1414 | // Gaps iterator should be fused. 1415 | assert_eq!(gaps.next(), None); 1416 | assert_eq!(gaps.next(), None); 1417 | } 1418 | 1419 | #[test] 1420 | fn items_floating_inside_outer_range() { 1421 | let mut range_map: RangeMap = RangeMap::new(); 1422 | // 0 1 2 3 4 5 6 7 8 9 1423 | // ◌ ◌ ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ 1424 | range_map.insert(5..6, ()); 1425 | // 0 1 2 3 4 5 6 7 8 9 1426 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 1427 | range_map.insert(3..4, ()); 1428 | // 0 1 2 3 4 5 6 7 8 9 1429 | // ◌ ◆-------------◇ ◌ 1430 | let outer_range = 1..8; 1431 | let mut gaps = range_map.gaps(&outer_range); 1432 | // Should yield gaps at start, between items, 1433 | // and at end. 1434 | assert_eq!(gaps.next(), Some(1..3)); 1435 | assert_eq!(gaps.next(), Some(4..5)); 1436 | assert_eq!(gaps.next(), Some(6..8)); 1437 | assert_eq!(gaps.next(), None); 1438 | // Gaps iterator should be fused. 1439 | assert_eq!(gaps.next(), None); 1440 | assert_eq!(gaps.next(), None); 1441 | } 1442 | 1443 | #[test] 1444 | fn item_ending_at_end_of_outer_range() { 1445 | let mut range_map: RangeMap = RangeMap::new(); 1446 | // 0 1 2 3 4 5 6 7 8 9 1447 | // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ●-◌ ◌ 1448 | range_map.insert(7..8, ()); 1449 | // 0 1 2 3 4 5 6 7 8 9 1450 | // ◌ ◌ ◌ ◌ ◌ ◆-----◇ ◌ 1451 | let outer_range = 5..8; 1452 | let mut gaps = range_map.gaps(&outer_range); 1453 | // Should yield from the start of the outer range 1454 | // up to the start of the stored item. 1455 | assert_eq!(gaps.next(), Some(5..7)); 1456 | assert_eq!(gaps.next(), None); 1457 | // Gaps iterator should be fused. 1458 | assert_eq!(gaps.next(), None); 1459 | assert_eq!(gaps.next(), None); 1460 | } 1461 | 1462 | #[test] 1463 | fn item_overlapping_end_of_outer_range() { 1464 | let mut range_map: RangeMap = RangeMap::new(); 1465 | // 0 1 2 3 4 5 6 7 8 9 1466 | // ◌ ◌ ◌ ◌ ●---◌ ◌ ◌ ◌ 1467 | range_map.insert(4..6, ()); 1468 | // 0 1 2 3 4 5 6 7 8 9 1469 | // ◌ ◌ ◆-----◇ ◌ ◌ ◌ ◌ 1470 | let outer_range = 2..5; 1471 | let mut gaps = range_map.gaps(&outer_range); 1472 | // Should yield from the start of the outer range 1473 | // up to the start of the stored item. 1474 | assert_eq!(gaps.next(), Some(2..4)); 1475 | assert_eq!(gaps.next(), None); 1476 | // Gaps iterator should be fused. 1477 | assert_eq!(gaps.next(), None); 1478 | assert_eq!(gaps.next(), None); 1479 | } 1480 | 1481 | #[test] 1482 | fn item_touching_end_of_outer_range() { 1483 | let mut range_map: RangeMap = RangeMap::new(); 1484 | // 0 1 2 3 4 5 6 7 8 9 1485 | // ◌ ◌ ◌ ◌ ●-------◌ ◌ 1486 | range_map.insert(4..8, ()); 1487 | // 0 1 2 3 4 5 6 7 8 9 1488 | // ◌ ◆-----◇ ◌ ◌ ◌ ◌ ◌ 1489 | let outer_range = 1..4; 1490 | let mut gaps = range_map.gaps(&outer_range); 1491 | // Should yield the entire outer range. 1492 | assert_eq!(gaps.next(), Some(1..4)); 1493 | assert_eq!(gaps.next(), None); 1494 | // Gaps iterator should be fused. 1495 | assert_eq!(gaps.next(), None); 1496 | assert_eq!(gaps.next(), None); 1497 | } 1498 | 1499 | #[test] 1500 | fn item_after_outer_range() { 1501 | let mut range_map: RangeMap = RangeMap::new(); 1502 | // 0 1 2 3 4 5 6 7 8 9 1503 | // ◌ ◌ ◌ ◌ ◌ ◌ ●---◌ ◌ 1504 | range_map.insert(6..7, ()); 1505 | // 0 1 2 3 4 5 6 7 8 9 1506 | // ◌ ◆-----◇ ◌ ◌ ◌ ◌ ◌ 1507 | let outer_range = 1..4; 1508 | let mut gaps = range_map.gaps(&outer_range); 1509 | // Should yield the entire outer range. 1510 | assert_eq!(gaps.next(), Some(1..4)); 1511 | assert_eq!(gaps.next(), None); 1512 | // Gaps iterator should be fused. 1513 | assert_eq!(gaps.next(), None); 1514 | assert_eq!(gaps.next(), None); 1515 | } 1516 | 1517 | #[test] 1518 | fn empty_outer_range_with_items_away_from_both_sides() { 1519 | let mut range_map: RangeMap = RangeMap::new(); 1520 | // 0 1 2 3 4 5 6 7 8 9 1521 | // ◌ ◆---◇ ◌ ◌ ◌ ◌ ◌ ◌ 1522 | range_map.insert(1..3, ()); 1523 | // 0 1 2 3 4 5 6 7 8 9 1524 | // ◌ ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ 1525 | range_map.insert(5..7, ()); 1526 | // 0 1 2 3 4 5 6 7 8 9 1527 | // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ 1528 | let outer_range = 4..4; 1529 | let mut gaps = range_map.gaps(&outer_range); 1530 | // Should not yield any gaps, because a zero-width outer range covers no values. 1531 | assert_eq!(gaps.next(), None); 1532 | // Gaps iterator should be fused. 1533 | assert_eq!(gaps.next(), None); 1534 | } 1535 | 1536 | #[test] 1537 | fn empty_outer_range_with_items_touching_both_sides() { 1538 | let mut range_map: RangeMap = RangeMap::new(); 1539 | // 0 1 2 3 4 5 6 7 8 9 1540 | // ◌ ◌ ◆---◇ ◌ ◌ ◌ ◌ ◌ ◌ 1541 | range_map.insert(2..4, ()); 1542 | // 0 1 2 3 4 5 6 7 8 9 1543 | // ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ ◌ 1544 | range_map.insert(4..6, ()); 1545 | // 0 1 2 3 4 5 6 7 8 9 1546 | // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ 1547 | let outer_range = 4..4; 1548 | let mut gaps = range_map.gaps(&outer_range); 1549 | // Should yield no gaps. 1550 | assert_eq!(gaps.next(), None); 1551 | // Gaps iterator should be fused. 1552 | assert_eq!(gaps.next(), None); 1553 | assert_eq!(gaps.next(), None); 1554 | } 1555 | 1556 | #[test] 1557 | fn empty_outer_range_with_item_straddling() { 1558 | let mut range_map: RangeMap = RangeMap::new(); 1559 | // 0 1 2 3 4 5 6 7 8 9 1560 | // ◌ ◌ ◆-----◇ ◌ ◌ ◌ ◌ ◌ 1561 | range_map.insert(2..5, ()); 1562 | // 0 1 2 3 4 5 6 7 8 9 1563 | // ◌ ◌ ◌ ◌ ◆ ◌ ◌ ◌ ◌ ◌ 1564 | let outer_range = 4..4; 1565 | let mut gaps = range_map.gaps(&outer_range); 1566 | // Should yield no gaps. 1567 | assert_eq!(gaps.next(), None); 1568 | // Gaps iterator should be fused. 1569 | assert_eq!(gaps.next(), None); 1570 | assert_eq!(gaps.next(), None); 1571 | } 1572 | 1573 | #[test] 1574 | fn no_empty_gaps() { 1575 | // Make two ranges different values so they don't 1576 | // get coalesced. 1577 | let mut range_map: RangeMap = RangeMap::new(); 1578 | // 0 1 2 3 4 5 6 7 8 9 1579 | // ◌ ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ 1580 | range_map.insert(4..5, true); 1581 | // 0 1 2 3 4 5 6 7 8 9 1582 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 1583 | range_map.insert(3..4, false); 1584 | // 0 1 2 3 4 5 6 7 8 9 1585 | // ◌ ◆-------------◇ ◌ 1586 | let outer_range = 1..8; 1587 | let mut gaps = range_map.gaps(&outer_range); 1588 | // Should yield gaps at start and end, but not between the 1589 | // two touching items. (4 is covered, so there should be no gap.) 1590 | assert_eq!(gaps.next(), Some(1..3)); 1591 | assert_eq!(gaps.next(), Some(5..8)); 1592 | assert_eq!(gaps.next(), None); 1593 | // Gaps iterator should be fused. 1594 | assert_eq!(gaps.next(), None); 1595 | assert_eq!(gaps.next(), None); 1596 | } 1597 | 1598 | #[test] 1599 | fn adjacent_small_items() { 1600 | // Items two items next to each other at the start, and at the end. 1601 | let mut range_map: RangeMap = RangeMap::new(); 1602 | range_map.insert(0..1, false); 1603 | range_map.insert(1..2, true); 1604 | range_map.insert(253..254, false); 1605 | range_map.insert(254..255, true); 1606 | 1607 | let outer_range = 0..255; 1608 | let mut gaps = range_map.gaps(&outer_range); 1609 | // Should yield one big gap in the middle. 1610 | assert_eq!(gaps.next(), Some(2..253)); 1611 | // Gaps iterator should be fused. 1612 | assert_eq!(gaps.next(), None); 1613 | assert_eq!(gaps.next(), None); 1614 | } 1615 | 1616 | // This test fails in v1.0.2 1617 | #[test] 1618 | fn outer_range_lies_within_first_of_two_stored_ranges() { 1619 | let mut range_map: RangeMap = RangeMap::new(); 1620 | // 0 1 2 3 4 5 6 7 8 9 1621 | // ◆----------◇ ◌ ◌ ◌ ◌ 1622 | range_map.insert(0..5, ()); 1623 | // 0 1 2 3 4 5 6 7 8 9 1624 | // ◌ ◌ ◌ ◌◌ ◌ ◆---◇ ◌ 1625 | range_map.insert(6..8, ()); 1626 | // 0 1 2 3 4 5 6 7 8 9 1627 | // ◌ ◆--◇ ◌ ◌ ◌ ◌ ◌ 1628 | let outer_range: Range = 1..3; 1629 | let mut gaps = range_map.gaps(&outer_range); 1630 | assert_eq!(gaps.next(), None); 1631 | } 1632 | 1633 | // Overlapping tests 1634 | 1635 | #[test] 1636 | fn overlapping_with_empty_map() { 1637 | // 0 1 2 3 4 5 6 7 8 9 1638 | // ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 1639 | let range_map: RangeMap = RangeMap::new(); 1640 | // 0 1 2 3 4 5 6 7 8 9 1641 | // ◌ ◆-------------◇ ◌ 1642 | let query_range = 1..8; 1643 | let mut overlapping = range_map.overlapping(&query_range); 1644 | // Should not yield any items. 1645 | assert_eq!(overlapping.next(), None); 1646 | // Gaps iterator should be fused. 1647 | assert_eq!(overlapping.next(), None); 1648 | } 1649 | 1650 | #[test] 1651 | fn overlapping_partial_edges_complete_middle() { 1652 | let mut range_map: RangeMap = RangeMap::new(); 1653 | 1654 | // 0 1 2 3 4 5 6 7 8 9 1655 | // ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 1656 | range_map.insert(0..2, ()); 1657 | // 0 1 2 3 4 5 6 7 8 9 1658 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 1659 | range_map.insert(3..4, ()); 1660 | // 0 1 2 3 4 5 6 7 8 9 1661 | // ◌ ◌ ◌ ◌ ◌ ●---◌ ◌ ◌ 1662 | range_map.insert(5..7, ()); 1663 | 1664 | // 0 1 2 3 4 5 6 7 8 9 1665 | // ◌ ◆---------◇ ◌ ◌ ◌ 1666 | let query_range = 1..6; 1667 | 1668 | let mut overlapping = range_map.overlapping(&query_range); 1669 | 1670 | // Should yield partially overlapped range at start. 1671 | assert_eq!(overlapping.next(), Some((&(0..2), &()))); 1672 | // Should yield completely overlapped range in middle. 1673 | assert_eq!(overlapping.next(), Some((&(3..4), &()))); 1674 | // Should yield partially overlapped range at end. 1675 | assert_eq!(overlapping.next(), Some((&(5..7), &()))); 1676 | // Gaps iterator should be fused. 1677 | assert_eq!(overlapping.next(), None); 1678 | assert_eq!(overlapping.next(), None); 1679 | } 1680 | 1681 | #[test] 1682 | fn overlapping_non_overlapping_edges_complete_middle() { 1683 | let mut range_map: RangeMap = RangeMap::new(); 1684 | 1685 | // 0 1 2 3 4 5 6 7 8 9 1686 | // ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 1687 | range_map.insert(0..2, ()); 1688 | // 0 1 2 3 4 5 6 7 8 9 1689 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 1690 | range_map.insert(3..4, ()); 1691 | // 0 1 2 3 4 5 6 7 8 9 1692 | // ◌ ◌ ◌ ◌ ◌ ●---◌ ◌ ◌ 1693 | range_map.insert(5..7, ()); 1694 | 1695 | // 0 1 2 3 4 5 6 7 8 9 1696 | // ◌ ◌ ◆-----◇ ◌ ◌ ◌ ◌ 1697 | let query_range = 2..5; 1698 | 1699 | let mut overlapping = range_map.overlapping(&query_range); 1700 | 1701 | // Should only yield the completely overlapped range in middle. 1702 | // (Not the ranges that are touched by not covered to either side.) 1703 | assert_eq!(overlapping.next(), Some((&(3..4), &()))); 1704 | // Gaps iterator should be fused. 1705 | assert_eq!(overlapping.next(), None); 1706 | assert_eq!(overlapping.next(), None); 1707 | } 1708 | 1709 | /// 1710 | /// impl Debug 1711 | /// 1712 | 1713 | #[test] 1714 | fn map_debug_repr_looks_right() { 1715 | let mut map: RangeMap = RangeMap::new(); 1716 | 1717 | // Empty 1718 | assert_eq!(format!("{:?}", map), "{}"); 1719 | 1720 | // One entry 1721 | map.insert(2..5, ()); 1722 | assert_eq!(format!("{:?}", map), "{2..5: ()}"); 1723 | 1724 | // Many entries 1725 | map.insert(6..7, ()); 1726 | map.insert(8..9, ()); 1727 | assert_eq!(format!("{:?}", map), "{2..5: (), 6..7: (), 8..9: ()}"); 1728 | } 1729 | 1730 | // impl Default where T: ?Default 1731 | 1732 | #[test] 1733 | fn always_default() { 1734 | struct NoDefault; 1735 | RangeMap::::default(); 1736 | } 1737 | 1738 | // Iterator Tests 1739 | 1740 | #[test] 1741 | fn into_iter_matches_iter() { 1742 | // Just use vec since that's the same implementation we'd expect 1743 | let mut range_map: RangeMap = RangeMap::new(); 1744 | range_map.insert(1..3, false); 1745 | range_map.insert(3..5, true); 1746 | 1747 | let cloned = range_map.to_vec(); 1748 | let consumed = range_map.into_iter().collect::>(); 1749 | 1750 | // Correct value 1751 | assert_eq!(cloned, vec![(1..3, false), (3..5, true)]); 1752 | 1753 | // Equality 1754 | assert_eq!(cloned, consumed); 1755 | } 1756 | 1757 | // Equality 1758 | #[test] 1759 | fn eq() { 1760 | let mut a: RangeMap = RangeMap::new(); 1761 | a.insert(1..3, false); 1762 | 1763 | let mut b: RangeMap = RangeMap::new(); 1764 | b.insert(1..4, false); 1765 | 1766 | let mut c: RangeMap = RangeMap::new(); 1767 | c.insert(1..3, false); 1768 | 1769 | assert_ne!(a, b); 1770 | assert_ne!(b, a); 1771 | 1772 | assert_eq!(a, c); 1773 | assert_eq!(c, a); 1774 | assert_eq!(a, a); 1775 | } 1776 | 1777 | // Ord 1778 | #[test] 1779 | fn partial_ord() { 1780 | let mut a: RangeMap = RangeMap::new(); 1781 | a.insert(1..3, false); 1782 | 1783 | let mut b: RangeMap = RangeMap::new(); 1784 | b.insert(1..4, false); 1785 | 1786 | assert_eq!(a.partial_cmp(&a), Some(Ordering::Equal)); 1787 | 1788 | assert_eq!(a.partial_cmp(&b), Some(Ordering::Less)); 1789 | assert_eq!(b.partial_cmp(&a), Some(Ordering::Greater)); 1790 | } 1791 | 1792 | #[test] 1793 | fn ord() { 1794 | let mut a: RangeMap = RangeMap::new(); 1795 | a.insert(1..3, false); 1796 | 1797 | let mut b: RangeMap = RangeMap::new(); 1798 | b.insert(1..4, false); 1799 | 1800 | assert_eq!(a.cmp(&a), Ordering::Equal); 1801 | 1802 | assert_eq!(a.cmp(&b), Ordering::Less); 1803 | assert_eq!(b.cmp(&a), Ordering::Greater); 1804 | } 1805 | 1806 | // impl Serialize 1807 | 1808 | #[cfg(feature = "serde1")] 1809 | #[test] 1810 | fn serialization() { 1811 | let mut range_map: RangeMap = RangeMap::new(); 1812 | // 0 1 2 3 4 5 6 7 8 9 1813 | // ◌ ◆---◇ ◌ ◌ ◌ ◌ ◌ ◌ 1814 | range_map.insert(1..3, false); 1815 | // 0 1 2 3 4 5 6 7 8 9 1816 | // ◌ ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ 1817 | range_map.insert(5..7, true); 1818 | let output = serde_json::to_string(&range_map).expect("Failed to serialize"); 1819 | assert_eq!(output, "[[[1,3],false],[[5,7],true]]"); 1820 | } 1821 | 1822 | // impl Deserialize 1823 | 1824 | #[cfg(feature = "serde1")] 1825 | #[test] 1826 | fn deserialization() { 1827 | let input = "[[[1,3],false],[[5,7],true]]"; 1828 | let range_map: RangeMap = 1829 | serde_json::from_str(input).expect("Failed to deserialize"); 1830 | let reserialized = serde_json::to_string(&range_map).expect("Failed to re-serialize"); 1831 | assert_eq!(reserialized, input); 1832 | } 1833 | 1834 | // const fn 1835 | 1836 | #[cfg(feature = "const_fn")] 1837 | const _MAP: RangeMap = RangeMap::new(); 1838 | 1839 | #[cfg(feature = "quickcheck")] 1840 | quickcheck::quickcheck! { 1841 | fn prop(xs: RangeMap) -> bool { 1842 | xs == xs 1843 | } 1844 | } 1845 | } 1846 | -------------------------------------------------------------------------------- /src/operations.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::Ordering; 2 | use core::iter::{FusedIterator, Peekable}; 3 | use core::ops::{Range, RangeInclusive}; 4 | 5 | /// Trait to determine the ordering of the start and end of a range. 6 | trait RangeOrder { 7 | /// Ordering of start value 8 | fn order_start(&self, other: &Self) -> Ordering; 9 | 10 | /// Ordering of end value 11 | fn order_end(&self, other: &Self) -> Ordering; 12 | } 13 | 14 | impl RangeOrder for Range { 15 | fn order_start(&self, other: &Self) -> Ordering { 16 | self.start.cmp(&other.start) 17 | } 18 | 19 | fn order_end(&self, other: &Self) -> Ordering { 20 | self.end.cmp(&other.end) 21 | } 22 | } 23 | 24 | impl RangeOrder for RangeInclusive { 25 | fn order_start(&self, other: &Self) -> Ordering { 26 | self.start().cmp(other.start()) 27 | } 28 | 29 | fn order_end(&self, other: &Self) -> Ordering { 30 | self.end().cmp(other.end()) 31 | } 32 | } 33 | 34 | /// Range which can be merged with a next range if they overlap. 35 | trait RangeMerge: Sized { 36 | /// Merges this range and the next range, if they overlap. 37 | fn merge(&mut self, next: &Self) -> bool; 38 | } 39 | 40 | impl RangeMerge for Range { 41 | fn merge(&mut self, other: &Self) -> bool { 42 | if !self.contains(&other.start) { 43 | return false; 44 | } 45 | 46 | if other.end > self.end { 47 | self.end = other.end.clone(); 48 | } 49 | 50 | true 51 | } 52 | } 53 | 54 | impl RangeMerge for RangeInclusive { 55 | fn merge(&mut self, other: &Self) -> bool { 56 | if !self.contains(other.start()) { 57 | return false; 58 | } 59 | 60 | if other.end() > self.end() { 61 | *self = RangeInclusive::new(self.start().clone(), other.end().clone()); 62 | } 63 | 64 | true 65 | } 66 | } 67 | 68 | /// Range which can be merged with a next range if they overlap. 69 | trait RangeIntersect: Sized { 70 | /// Attempt to merge the next range into the current range, if they overlap. 71 | fn intersect(&self, next: &Self) -> Option; 72 | } 73 | 74 | impl RangeIntersect for Range { 75 | fn intersect(&self, other: &Self) -> Option { 76 | let start = (&self.start).max(&other.start); 77 | let end = (&self.end).min(&other.end); 78 | 79 | if start >= end { 80 | return None; 81 | } 82 | 83 | Some(start.clone()..end.clone()) 84 | } 85 | } 86 | 87 | impl RangeIntersect for RangeInclusive { 88 | fn intersect(&self, other: &Self) -> Option { 89 | let start = self.start().max(other.start()); 90 | let end = self.end().min(other.end()); 91 | 92 | if start > end { 93 | return None; 94 | } 95 | 96 | Some(start.clone()..=end.clone()) 97 | } 98 | } 99 | 100 | #[test] 101 | fn test_intersect() { 102 | assert_eq!((0..5).intersect(&(0..3)), Some(0..3)); 103 | assert_eq!((0..3).intersect(&(0..5)), Some(0..3)); 104 | assert_eq!((0..3).intersect(&(3..3)), None); 105 | } 106 | 107 | /// Iterator that produces the union of two iterators of sorted ranges. 108 | pub struct Union<'a, T, L, R = L> 109 | where 110 | T: 'a, 111 | L: Iterator, 112 | R: Iterator, 113 | { 114 | left: Peekable, 115 | right: Peekable, 116 | } 117 | 118 | impl<'a, T, L, R> Union<'a, T, L, R> 119 | where 120 | T: 'a, 121 | L: Iterator, 122 | R: Iterator, 123 | { 124 | /// Create new Union iterator. 125 | /// 126 | /// Requires that the two iterators produce sorted ranges. 127 | pub fn new(left: L, right: R) -> Self { 128 | Self { 129 | left: left.peekable(), 130 | right: right.peekable(), 131 | } 132 | } 133 | } 134 | 135 | impl<'a, R, I> Iterator for Union<'a, R, I> 136 | where 137 | R: RangeOrder + RangeMerge + Clone, 138 | I: Iterator, 139 | { 140 | type Item = R; 141 | 142 | fn next(&mut self) -> Option { 143 | // get start range 144 | let mut range = match (self.left.peek(), self.right.peek()) { 145 | // if there is only one possible range, pick that 146 | (Some(_), None) => self.left.next().unwrap(), 147 | (None, Some(_)) => self.right.next().unwrap(), 148 | // when there are two ranges, pick the one with the earlier start 149 | (Some(left), Some(right)) => { 150 | if left.order_start(right).is_lt() { 151 | self.left.next().unwrap() 152 | } else { 153 | self.right.next().unwrap() 154 | } 155 | } 156 | // otherwise we are done 157 | (None, None) => return None, 158 | } 159 | .clone(); 160 | 161 | // peek into next value of iterator and merge if it is contiguous 162 | let mut join = |iter: &mut Peekable| { 163 | if let Some(next) = iter.peek() { 164 | if range.merge(next) { 165 | iter.next().unwrap(); 166 | return true; 167 | } 168 | } 169 | false 170 | }; 171 | 172 | // keep merging ranges as long as we can 173 | loop { 174 | if !(join(&mut self.left) || join(&mut self.right)) { 175 | break; 176 | } 177 | } 178 | 179 | Some(range) 180 | } 181 | } 182 | 183 | impl<'a, R, I> FusedIterator for Union<'a, R, I> 184 | where 185 | R: RangeOrder + RangeMerge + Clone, 186 | I: Iterator, 187 | { 188 | } 189 | 190 | /// Iterator that produces the union of two iterators of sorted ranges. 191 | pub struct Intersection<'a, T, L, R = L> 192 | where 193 | T: 'a, 194 | L: Iterator, 195 | R: Iterator, 196 | { 197 | left: Peekable, 198 | right: Peekable, 199 | } 200 | 201 | impl<'a, T, L, R> Intersection<'a, T, L, R> 202 | where 203 | T: 'a, 204 | L: Iterator, 205 | R: Iterator, 206 | { 207 | /// Create new Intersection iterator. 208 | /// 209 | /// Requires that the two iterators produce sorted ranges. 210 | pub fn new(left: L, right: R) -> Self { 211 | Self { 212 | left: left.peekable(), 213 | right: right.peekable(), 214 | } 215 | } 216 | } 217 | 218 | impl<'a, R, I> Iterator for Intersection<'a, R, I> 219 | where 220 | R: RangeOrder + RangeIntersect + Clone, 221 | I: Iterator, 222 | { 223 | type Item = R; 224 | 225 | fn next(&mut self) -> Option { 226 | loop { 227 | // if we don't have at least two ranges, there cannot be an intersection 228 | let (Some(left), Some(right)) = (self.left.peek(), self.right.peek()) else { 229 | return None; 230 | }; 231 | 232 | let intersection = left.intersect(right); 233 | 234 | // pop the range that ends earlier 235 | if left.order_end(right).is_lt() { 236 | self.left.next(); 237 | } else { 238 | self.right.next(); 239 | } 240 | 241 | if let Some(intersection) = intersection { 242 | return Some(intersection); 243 | } 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/range_wrapper.rs: -------------------------------------------------------------------------------- 1 | // Wrappers to allow storing (and sorting/searching) 2 | // ranges as the keys of a `BTreeMap`. 3 | // 4 | // This wraps the range in two layers: one that lets us 5 | // order ranges by their start (`RangeStartWrapper`), 6 | // and then within that, one that lets us order them by 7 | // their end (`RangeEndWrapper`). Ordinarily we'll use 8 | // the former, but there are a couple of cases where we 9 | // want to be able to do the latter for performance/convenience. 10 | // 11 | // This is made possible by a sneaky `Borrow` implementation 12 | // which skirts the law about the borrowed representation 13 | // having identical implementations of `Ord` etc., but shouldn't 14 | // be a problem in practice because users of the crate can't 15 | // access these special wrappers, and we are careful to uphold 16 | // invariants that prevent observing any states where the 17 | // differing implementations would produce different results. 18 | // 19 | // Specifically, we maintain the invariants 20 | // that the order of range starts is the same as the order 21 | // of range ends, and that no two stored ranges have the 22 | // same start or end as each other. 23 | // 24 | // NOTE: Be very careful not to accidentally use these 25 | // if you really do want to compare equality of the 26 | // inner range! 27 | 28 | use core::cmp::Ordering; 29 | use core::ops::{Deref, Range, RangeInclusive}; 30 | 31 | // 32 | // Range start wrapper 33 | // 34 | 35 | #[derive(Debug, Clone)] 36 | pub struct RangeStartWrapper { 37 | pub end_wrapper: RangeEndWrapper, 38 | } 39 | 40 | impl RangeStartWrapper { 41 | pub fn new(range: Range) -> RangeStartWrapper { 42 | RangeStartWrapper { 43 | end_wrapper: RangeEndWrapper::new(range), 44 | } 45 | } 46 | } 47 | 48 | impl PartialEq for RangeStartWrapper 49 | where 50 | T: PartialEq, 51 | { 52 | fn eq(&self, other: &RangeStartWrapper) -> bool { 53 | self.start == other.start 54 | } 55 | } 56 | 57 | impl Eq for RangeStartWrapper where T: Eq {} 58 | 59 | impl Ord for RangeStartWrapper 60 | where 61 | T: Ord, 62 | { 63 | fn cmp(&self, other: &RangeStartWrapper) -> Ordering { 64 | self.start.cmp(&other.start) 65 | } 66 | } 67 | 68 | impl PartialOrd for RangeStartWrapper 69 | where 70 | T: PartialOrd, 71 | { 72 | fn partial_cmp(&self, other: &RangeStartWrapper) -> Option { 73 | self.start.partial_cmp(&other.start) 74 | } 75 | } 76 | 77 | impl core::borrow::Borrow> for RangeStartWrapper { 78 | fn borrow(&self) -> &RangeEndWrapper { 79 | &self.end_wrapper 80 | } 81 | } 82 | 83 | // Avoid the need to tediously plumb through the layers of wrapper structs 84 | // when you're just trying to access members of the inner range itself. 85 | impl Deref for RangeStartWrapper { 86 | type Target = RangeEndWrapper; 87 | 88 | fn deref(&self) -> &Self::Target { 89 | &self.end_wrapper 90 | } 91 | } 92 | 93 | // 94 | // Range end wrapper 95 | // 96 | 97 | #[derive(Debug, Clone)] 98 | pub struct RangeEndWrapper { 99 | pub range: Range, 100 | } 101 | 102 | impl RangeEndWrapper { 103 | pub fn new(range: Range) -> RangeEndWrapper { 104 | RangeEndWrapper { range } 105 | } 106 | } 107 | 108 | impl PartialEq for RangeEndWrapper 109 | where 110 | T: PartialEq, 111 | { 112 | fn eq(&self, other: &RangeEndWrapper) -> bool { 113 | self.end == other.end 114 | } 115 | } 116 | 117 | impl Eq for RangeEndWrapper where T: Eq {} 118 | 119 | impl Ord for RangeEndWrapper 120 | where 121 | T: Ord, 122 | { 123 | fn cmp(&self, other: &RangeEndWrapper) -> Ordering { 124 | self.end.cmp(&other.end) 125 | } 126 | } 127 | 128 | impl PartialOrd for RangeEndWrapper 129 | where 130 | T: PartialOrd, 131 | { 132 | fn partial_cmp(&self, other: &RangeEndWrapper) -> Option { 133 | self.end.partial_cmp(&other.end) 134 | } 135 | } 136 | 137 | // Avoid the need to tediously plumb through the layers of wrapper structs 138 | // when you're just trying to access members of the inner range itself. 139 | impl Deref for RangeEndWrapper { 140 | type Target = Range; 141 | 142 | fn deref(&self) -> &Self::Target { 143 | &self.range 144 | } 145 | } 146 | 147 | // 148 | // RangeInclusive start wrapper 149 | // 150 | 151 | #[derive(Eq, Debug, Clone)] 152 | pub struct RangeInclusiveStartWrapper { 153 | pub end_wrapper: RangeInclusiveEndWrapper, 154 | } 155 | 156 | impl RangeInclusiveStartWrapper { 157 | pub fn new(range: RangeInclusive) -> RangeInclusiveStartWrapper { 158 | RangeInclusiveStartWrapper { 159 | end_wrapper: RangeInclusiveEndWrapper::new(range), 160 | } 161 | } 162 | } 163 | 164 | impl PartialEq for RangeInclusiveStartWrapper 165 | where 166 | T: PartialEq, 167 | { 168 | fn eq(&self, other: &RangeInclusiveStartWrapper) -> bool { 169 | self.start() == other.start() 170 | } 171 | } 172 | 173 | impl Ord for RangeInclusiveStartWrapper 174 | where 175 | T: Ord, 176 | { 177 | fn cmp(&self, other: &RangeInclusiveStartWrapper) -> Ordering { 178 | self.start().cmp(other.start()) 179 | } 180 | } 181 | 182 | impl PartialOrd for RangeInclusiveStartWrapper 183 | where 184 | T: PartialOrd, 185 | { 186 | fn partial_cmp(&self, other: &RangeInclusiveStartWrapper) -> Option { 187 | self.start().partial_cmp(other.start()) 188 | } 189 | } 190 | 191 | impl core::borrow::Borrow> for RangeInclusiveStartWrapper { 192 | fn borrow(&self) -> &RangeInclusiveEndWrapper { 193 | &self.end_wrapper 194 | } 195 | } 196 | 197 | // Avoid the need to tediously plumb through the layers of wrapper structs 198 | // when you're just trying to access members of the inner range itself. 199 | impl Deref for RangeInclusiveStartWrapper { 200 | type Target = RangeInclusiveEndWrapper; 201 | 202 | fn deref(&self) -> &Self::Target { 203 | &self.end_wrapper 204 | } 205 | } 206 | 207 | // 208 | // RangeInclusive end wrapper 209 | // 210 | 211 | #[derive(Eq, Debug, Clone)] 212 | pub struct RangeInclusiveEndWrapper { 213 | pub range: RangeInclusive, 214 | } 215 | 216 | impl RangeInclusiveEndWrapper { 217 | pub fn new(range: RangeInclusive) -> RangeInclusiveEndWrapper { 218 | RangeInclusiveEndWrapper { range } 219 | } 220 | } 221 | 222 | impl PartialEq for RangeInclusiveEndWrapper 223 | where 224 | T: PartialEq, 225 | { 226 | fn eq(&self, other: &RangeInclusiveEndWrapper) -> bool { 227 | self.end() == other.end() 228 | } 229 | } 230 | 231 | impl Ord for RangeInclusiveEndWrapper 232 | where 233 | T: Ord, 234 | { 235 | fn cmp(&self, other: &RangeInclusiveEndWrapper) -> Ordering { 236 | self.end().cmp(other.end()) 237 | } 238 | } 239 | 240 | impl PartialOrd for RangeInclusiveEndWrapper 241 | where 242 | T: PartialOrd, 243 | { 244 | fn partial_cmp(&self, other: &RangeInclusiveEndWrapper) -> Option { 245 | self.end().partial_cmp(other.end()) 246 | } 247 | } 248 | 249 | // Avoid the need to tediously plumb through the layers of wrapper structs 250 | // when you're just trying to access members of the inner range itself. 251 | impl Deref for RangeInclusiveEndWrapper { 252 | type Target = RangeInclusive; 253 | 254 | fn deref(&self) -> &Self::Target { 255 | &self.range 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/readme.rs: -------------------------------------------------------------------------------- 1 | #[doc = include_str!("../README.md")] 2 | struct _Readme {} 3 | -------------------------------------------------------------------------------- /src/set.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::Borrow; 2 | use core::fmt::{self, Debug}; 3 | use core::iter::FromIterator; 4 | use core::ops::{BitAnd, BitOr, Range}; 5 | use core::prelude::v1::*; 6 | 7 | #[cfg(feature = "serde1")] 8 | use core::marker::PhantomData; 9 | #[cfg(feature = "serde1")] 10 | use serde::{ 11 | de::{Deserialize, Deserializer, SeqAccess, Visitor}, 12 | ser::{Serialize, Serializer}, 13 | }; 14 | 15 | use crate::RangeMap; 16 | 17 | /// Intersection iterator over two [`RangeSet`]. 18 | pub type Intersection<'a, T> = crate::operations::Intersection<'a, Range, Iter<'a, T>>; 19 | 20 | /// Union iterator over two [`RangeSet`]. 21 | pub type Union<'a, T> = crate::operations::Union<'a, Range, Iter<'a, T>>; 22 | 23 | #[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord)] 24 | /// A set whose items are stored as (half-open) ranges bounded 25 | /// inclusively below and exclusively above `(start..end)`. 26 | /// 27 | /// See [`RangeMap`]'s documentation for more details. 28 | /// 29 | /// [`RangeMap`]: crate::RangeMap 30 | pub struct RangeSet { 31 | rm: RangeMap, 32 | } 33 | 34 | impl Default for RangeSet { 35 | fn default() -> Self { 36 | Self { 37 | rm: RangeMap::default(), 38 | } 39 | } 40 | } 41 | 42 | #[cfg(feature = "quickcheck")] 43 | impl quickcheck::Arbitrary for RangeSet 44 | where 45 | K: quickcheck::Arbitrary + Ord, 46 | { 47 | fn arbitrary(g: &mut quickcheck::Gen) -> Self { 48 | Self { 49 | rm: RangeMap::arbitrary(g), 50 | } 51 | } 52 | } 53 | 54 | impl RangeSet 55 | where 56 | T: Ord + Clone, 57 | { 58 | /// Makes a new empty `RangeSet`. 59 | #[cfg(feature = "const_fn")] 60 | pub const fn new() -> Self { 61 | RangeSet { 62 | rm: RangeMap::new(), 63 | } 64 | } 65 | 66 | /// Makes a new empty `RangeSet`. 67 | #[cfg(not(feature = "const_fn"))] 68 | pub fn new() -> Self { 69 | RangeSet { 70 | rm: RangeMap::new(), 71 | } 72 | } 73 | 74 | /// Returns a reference to the range covering the given key, if any. 75 | pub fn get(&self, value: &T) -> Option<&Range> { 76 | self.rm.get_key_value(value).map(|(range, _)| range) 77 | } 78 | 79 | /// Returns `true` if any range in the set covers the specified value. 80 | pub fn contains(&self, value: &T) -> bool { 81 | self.rm.contains_key(value) 82 | } 83 | 84 | /// Gets an ordered iterator over all ranges, 85 | /// ordered by range. 86 | pub fn iter(&self) -> Iter<'_, T> { 87 | Iter { 88 | inner: self.rm.iter(), 89 | } 90 | } 91 | 92 | /// Clears the set, removing all elements. 93 | pub fn clear(&mut self) { 94 | self.rm.clear(); 95 | } 96 | 97 | /// Returns the number of elements in the set. 98 | pub fn len(&self) -> usize { 99 | self.rm.len() 100 | } 101 | 102 | /// Returns true if the set contains no elements. 103 | pub fn is_empty(&self) -> bool { 104 | self.rm.is_empty() 105 | } 106 | 107 | /// Return an iterator over the intersection of two range sets. 108 | pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T> { 109 | Intersection::new(self.iter(), other.iter()) 110 | } 111 | 112 | /// Return an iterator over the union of two range sets. 113 | pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T> { 114 | Union::new(self.iter(), other.iter()) 115 | } 116 | 117 | /// Insert a range into the set. 118 | /// 119 | /// If the inserted range either overlaps or is immediately adjacent 120 | /// any existing range, then the ranges will be coalesced into 121 | /// a single contiguous range. 122 | /// 123 | /// # Panics 124 | /// 125 | /// Panics if range `start >= end`. 126 | pub fn insert(&mut self, range: Range) { 127 | self.rm.insert(range, ()); 128 | } 129 | 130 | /// Removes a range from the set, if all or any of it was present. 131 | /// 132 | /// If the range to be removed _partially_ overlaps any ranges 133 | /// in the set, then those ranges will be contracted to no 134 | /// longer cover the removed range. 135 | /// 136 | /// # Panics 137 | /// 138 | /// Panics if range `start >= end`. 139 | pub fn remove(&mut self, range: Range) { 140 | self.rm.remove(range); 141 | } 142 | 143 | /// Gets an iterator over all the maximally-sized ranges 144 | /// contained in `outer_range` that are not covered by 145 | /// any range stored in the set. 146 | /// 147 | /// If the start and end of the outer range are the same 148 | /// and it does not overlap any stored range, then a single 149 | /// empty gap will be returned. 150 | /// 151 | /// The iterator element type is `Range`. 152 | pub fn gaps<'a>(&'a self, outer_range: &'a Range) -> Gaps<'a, T> { 153 | Gaps { 154 | inner: self.rm.gaps(outer_range), 155 | } 156 | } 157 | 158 | /// Gets an iterator over all the stored ranges that are 159 | /// either partially or completely overlapped by the given range. 160 | /// 161 | /// The iterator element type is `&Range`. 162 | pub fn overlapping>>(&self, range: R) -> Overlapping { 163 | Overlapping { 164 | inner: self.rm.overlapping(range), 165 | } 166 | } 167 | 168 | /// Returns `true` if any range in the set completely or partially 169 | /// overlaps the given range. 170 | pub fn overlaps(&self, range: &Range) -> bool { 171 | self.overlapping(range).next().is_some() 172 | } 173 | 174 | /// Returns the first range in the set, if one exists. The range is the minimum range in this 175 | /// set. 176 | pub fn first(&self) -> Option<&Range> { 177 | self.rm.first_range_value().map(|(range, _)| range) 178 | } 179 | 180 | /// Returns the last range in the set, if one exists. The range is the maximum range in this 181 | /// set. 182 | pub fn last(&self) -> Option<&Range> { 183 | self.rm.last_range_value().map(|(range, _)| range) 184 | } 185 | } 186 | 187 | /// An iterator over the ranges of a `RangeSet`. 188 | /// 189 | /// This `struct` is created by the [`iter`] method on [`RangeSet`]. See its 190 | /// documentation for more. 191 | /// 192 | /// [`iter`]: RangeSet::iter 193 | pub struct Iter<'a, T> { 194 | inner: super::map::Iter<'a, T, ()>, 195 | } 196 | 197 | impl<'a, T> Iterator for Iter<'a, T> { 198 | type Item = &'a Range; 199 | 200 | fn next(&mut self) -> Option { 201 | self.inner.next().map(|(range, _)| range) 202 | } 203 | 204 | fn size_hint(&self) -> (usize, Option) { 205 | self.inner.size_hint() 206 | } 207 | } 208 | 209 | impl<'a, K> DoubleEndedIterator for Iter<'a, K> 210 | where 211 | K: 'a, 212 | { 213 | fn next_back(&mut self) -> Option { 214 | self.inner.next_back().map(|(range, _)| range) 215 | } 216 | } 217 | 218 | /// An owning iterator over the ranges of a `RangeSet`. 219 | /// 220 | /// This `struct` is created by the [`into_iter`] method on [`RangeSet`] 221 | /// (provided by the `IntoIterator` trait). See its documentation for more. 222 | /// 223 | /// [`into_iter`]: IntoIterator::into_iter 224 | pub struct IntoIter { 225 | inner: super::map::IntoIter, 226 | } 227 | 228 | impl IntoIterator for RangeSet { 229 | type Item = Range; 230 | type IntoIter = IntoIter; 231 | fn into_iter(self) -> Self::IntoIter { 232 | IntoIter { 233 | inner: self.rm.into_iter(), 234 | } 235 | } 236 | } 237 | 238 | impl Iterator for IntoIter { 239 | type Item = Range; 240 | fn next(&mut self) -> Option> { 241 | self.inner.next().map(|(range, _)| range) 242 | } 243 | fn size_hint(&self) -> (usize, Option) { 244 | self.inner.size_hint() 245 | } 246 | } 247 | 248 | impl DoubleEndedIterator for IntoIter { 249 | fn next_back(&mut self) -> Option { 250 | self.inner.next_back().map(|(range, _)| range) 251 | } 252 | } 253 | 254 | // We can't just derive this automatically, because that would 255 | // expose irrelevant (and private) implementation details. 256 | // Instead implement it in the same way that the underlying BTreeSet does. 257 | impl Debug for RangeSet 258 | where 259 | T: Ord + Clone, 260 | { 261 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 262 | f.debug_set().entries(self.iter()).finish() 263 | } 264 | } 265 | 266 | impl FromIterator> for RangeSet 267 | where 268 | T: Ord + Clone, 269 | { 270 | fn from_iter>>(iter: I) -> Self { 271 | let mut range_set = RangeSet::new(); 272 | range_set.extend(iter); 273 | range_set 274 | } 275 | } 276 | 277 | impl Extend> for RangeSet 278 | where 279 | T: Ord + Clone, 280 | { 281 | fn extend>>(&mut self, iter: I) { 282 | iter.into_iter().for_each(move |range| { 283 | self.insert(range); 284 | }) 285 | } 286 | } 287 | 288 | #[cfg(feature = "serde1")] 289 | impl Serialize for RangeSet 290 | where 291 | T: Ord + Clone + Serialize, 292 | { 293 | fn serialize(&self, serializer: S) -> Result 294 | where 295 | S: Serializer, 296 | { 297 | use serde::ser::SerializeSeq; 298 | let mut seq = serializer.serialize_seq(Some(self.rm.btm.len()))?; 299 | for range in self.iter() { 300 | seq.serialize_element(&(&range.start, &range.end))?; 301 | } 302 | seq.end() 303 | } 304 | } 305 | 306 | #[cfg(feature = "serde1")] 307 | impl<'de, T> Deserialize<'de> for RangeSet 308 | where 309 | T: Ord + Clone + Deserialize<'de>, 310 | { 311 | fn deserialize(deserializer: D) -> Result 312 | where 313 | D: Deserializer<'de>, 314 | { 315 | deserializer.deserialize_seq(RangeSetVisitor::new()) 316 | } 317 | } 318 | 319 | #[cfg(feature = "serde1")] 320 | struct RangeSetVisitor { 321 | marker: PhantomData RangeSet>, 322 | } 323 | 324 | #[cfg(feature = "serde1")] 325 | impl RangeSetVisitor { 326 | fn new() -> Self { 327 | RangeSetVisitor { 328 | marker: PhantomData, 329 | } 330 | } 331 | } 332 | 333 | #[cfg(feature = "serde1")] 334 | impl<'de, T> Visitor<'de> for RangeSetVisitor 335 | where 336 | T: Ord + Clone + Deserialize<'de>, 337 | { 338 | type Value = RangeSet; 339 | 340 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 341 | formatter.write_str("RangeSet") 342 | } 343 | 344 | fn visit_seq(self, mut access: A) -> Result 345 | where 346 | A: SeqAccess<'de>, 347 | { 348 | let mut range_set = RangeSet::new(); 349 | while let Some((start, end)) = access.next_element()? { 350 | range_set.insert(start..end); 351 | } 352 | Ok(range_set) 353 | } 354 | } 355 | 356 | /// An iterator over all ranges not covered by a `RangeSet`. 357 | /// 358 | /// This `struct` is created by the [`gaps`] method on [`RangeSet`]. See its 359 | /// documentation for more. 360 | /// 361 | /// [`gaps`]: RangeSet::gaps 362 | pub struct Gaps<'a, T> { 363 | inner: crate::map::Gaps<'a, T, ()>, 364 | } 365 | 366 | // `Gaps` is always fused. (See definition of `next` below.) 367 | impl<'a, T> core::iter::FusedIterator for Gaps<'a, T> where T: Ord + Clone {} 368 | 369 | impl<'a, T> Iterator for Gaps<'a, T> 370 | where 371 | T: Ord + Clone, 372 | { 373 | type Item = Range; 374 | 375 | fn next(&mut self) -> Option { 376 | self.inner.next() 377 | } 378 | } 379 | 380 | /// An iterator over all stored ranges partially or completely 381 | /// overlapped by a given range. 382 | /// 383 | /// This `struct` is created by the [`overlapping`] method on [`RangeSet`]. See its 384 | /// documentation for more. 385 | /// 386 | /// [`overlapping`]: RangeSet::overlapping 387 | pub struct Overlapping<'a, T, R: Borrow> = &'a Range> { 388 | inner: crate::map::Overlapping<'a, T, (), R>, 389 | } 390 | 391 | // `Overlapping` is always fused. (See definition of `next` below.) 392 | impl<'a, T, R: Borrow>> core::iter::FusedIterator for Overlapping<'a, T, R> where 393 | T: Ord + Clone 394 | { 395 | } 396 | 397 | impl<'a, T, R: Borrow>> Iterator for Overlapping<'a, T, R> 398 | where 399 | T: Ord + Clone, 400 | { 401 | type Item = &'a Range; 402 | 403 | fn next(&mut self) -> Option { 404 | self.inner.next().map(|(k, _v)| k) 405 | } 406 | } 407 | 408 | impl<'a, T, R: Borrow>> DoubleEndedIterator for Overlapping<'a, T, R> 409 | where 410 | T: Ord + Clone, 411 | { 412 | fn next_back(&mut self) -> Option { 413 | self.inner.next_back().map(|(k, _v)| k) 414 | } 415 | } 416 | 417 | impl BitAnd for &RangeSet { 418 | type Output = RangeSet; 419 | 420 | fn bitand(self, other: Self) -> Self::Output { 421 | self.intersection(other).collect() 422 | } 423 | } 424 | 425 | impl BitOr for &RangeSet { 426 | type Output = RangeSet; 427 | 428 | fn bitor(self, other: Self) -> Self::Output { 429 | self.union(other).collect() 430 | } 431 | } 432 | 433 | impl From<[Range; N]> for RangeSet { 434 | fn from(value: [Range; N]) -> Self { 435 | let mut set = Self::new(); 436 | for value in IntoIterator::into_iter(value) { 437 | set.insert(value); 438 | } 439 | set 440 | } 441 | } 442 | 443 | /// Create a [`RangeSet`] from a list of ranges. 444 | /// 445 | /// # Example 446 | /// 447 | /// ```rust 448 | /// # use rangemap::range_set; 449 | /// let set = range_set![0..100, 200..300, 400..500]; 450 | /// ``` 451 | #[macro_export] 452 | macro_rules! range_set { 453 | ($($range:expr),* $(,)?) => {{ 454 | $crate::RangeSet::from([$($range),*]) 455 | }}; 456 | } 457 | 458 | #[cfg(test)] 459 | mod tests { 460 | use super::*; 461 | use alloc as std; 462 | use alloc::{format, vec, vec::Vec}; 463 | use proptest::prelude::*; 464 | use test_strategy::proptest; 465 | 466 | impl Arbitrary for RangeSet 467 | where 468 | T: Ord + Clone + Debug + Arbitrary + 'static, 469 | { 470 | type Parameters = (); 471 | type Strategy = BoxedStrategy; 472 | 473 | fn arbitrary_with(_parameters: Self::Parameters) -> Self::Strategy { 474 | any::>>() 475 | .prop_map(|ranges| { 476 | ranges 477 | .into_iter() 478 | .filter(|range| range.start != range.end) 479 | .collect::>() 480 | }) 481 | .boxed() 482 | } 483 | } 484 | 485 | #[proptest] 486 | fn test_first(set: RangeSet) { 487 | assert_eq!(set.first(), set.iter().min_by_key(|range| range.start)); 488 | } 489 | 490 | #[proptest] 491 | #[allow(clippy::len_zero)] 492 | fn test_len(mut map: RangeSet) { 493 | assert_eq!(map.len(), map.iter().count()); 494 | assert_eq!(map.is_empty(), map.len() == 0); 495 | map.clear(); 496 | assert_eq!(map.len(), 0); 497 | assert!(map.is_empty()); 498 | assert_eq!(map.iter().count(), 0); 499 | } 500 | 501 | #[proptest] 502 | fn test_last(set: RangeSet) { 503 | assert_eq!(set.last(), set.iter().max_by_key(|range| range.end)); 504 | } 505 | 506 | #[proptest] 507 | fn test_iter_reversible(set: RangeSet) { 508 | let forward: Vec<_> = set.iter().collect(); 509 | let mut backward: Vec<_> = set.iter().rev().collect(); 510 | backward.reverse(); 511 | assert_eq!(forward, backward); 512 | } 513 | 514 | #[proptest] 515 | fn test_into_iter_reversible(set: RangeSet) { 516 | let forward: Vec<_> = set.clone().into_iter().collect(); 517 | let mut backward: Vec<_> = set.into_iter().rev().collect(); 518 | backward.reverse(); 519 | assert_eq!(forward, backward); 520 | } 521 | 522 | #[proptest] 523 | fn test_overlapping_reversible(set: RangeSet, range: Range) { 524 | let forward: Vec<_> = set.overlapping(&range).collect(); 525 | let mut backward: Vec<_> = set.overlapping(&range).rev().collect(); 526 | backward.reverse(); 527 | assert_eq!(forward, backward); 528 | } 529 | 530 | // neccessary due to assertion on empty ranges 531 | fn filter_ranges(ranges: Vec>) -> Vec> { 532 | ranges 533 | .into_iter() 534 | .filter(|range| range.start != range.end) 535 | .collect() 536 | } 537 | 538 | #[proptest] 539 | fn test_arbitrary_set_u8(ranges: Vec>) { 540 | let ranges = filter_ranges(ranges); 541 | let set = ranges.iter().fold(RangeSet::new(), |mut set, range| { 542 | set.insert(range.clone()); 543 | set 544 | }); 545 | 546 | for value in 0..u8::MAX { 547 | assert_eq!( 548 | set.contains(&value), 549 | ranges.iter().any(|range| range.contains(&value)) 550 | ); 551 | } 552 | } 553 | 554 | #[proptest] 555 | #[allow(deprecated)] 556 | fn test_hash(left: RangeSet, right: RangeSet) { 557 | use core::hash::{Hash, Hasher, SipHasher}; 558 | 559 | let hash = |set: &RangeSet<_>| { 560 | let mut hasher = SipHasher::new(); 561 | set.hash(&mut hasher); 562 | hasher.finish() 563 | }; 564 | 565 | if left == right { 566 | assert!( 567 | hash(&left) == hash(&right), 568 | "if two values are equal, their hash must be equal" 569 | ); 570 | } 571 | 572 | // if the hashes are equal the values might not be the same (collision) 573 | if hash(&left) != hash(&right) { 574 | assert!( 575 | left != right, 576 | "if two value's hashes are not equal, they must not be equal" 577 | ); 578 | } 579 | } 580 | 581 | #[proptest] 582 | fn test_ord(left: RangeSet, right: RangeSet) { 583 | assert_eq!( 584 | left == right, 585 | left.cmp(&right).is_eq(), 586 | "ordering and equality must match" 587 | ); 588 | assert_eq!( 589 | left.cmp(&right), 590 | left.partial_cmp(&right).unwrap(), 591 | "ordering is total for ordered parameters" 592 | ); 593 | } 594 | 595 | #[test] 596 | fn test_from_array() { 597 | let mut set = RangeSet::new(); 598 | set.insert(0..100); 599 | set.insert(200..300); 600 | assert_eq!(set, RangeSet::from([0..100, 200..300])); 601 | } 602 | 603 | #[test] 604 | fn test_macro() { 605 | assert_eq!(range_set![], RangeSet::::new()); 606 | assert_eq!( 607 | range_set![0..100, 200..300, 400..500], 608 | [0..100, 200..300, 400..500].iter().cloned().collect(), 609 | ); 610 | } 611 | 612 | #[proptest] 613 | fn test_union_overlaps_u8(left: RangeSet, right: RangeSet) { 614 | let mut union = RangeSet::new(); 615 | for range in left.union(&right) { 616 | // there should not be any overlaps in the ranges returned by the union 617 | assert!(union.overlapping(&range).next().is_none()); 618 | union.insert(range); 619 | } 620 | } 621 | 622 | #[proptest] 623 | fn test_union_contains_u8(left: RangeSet, right: RangeSet) { 624 | let union = (&left) | (&right); 625 | 626 | // value should be in the union if and only if it is in either set 627 | for value in 0..u8::MAX { 628 | assert_eq!( 629 | union.contains(&value), 630 | left.contains(&value) || right.contains(&value) 631 | ); 632 | } 633 | } 634 | 635 | #[proptest] 636 | fn test_intersection_contains_u8(left: RangeSet, right: RangeSet) { 637 | let intersection = (&left) & (&right); 638 | 639 | // value should be in the intersection if and only if it is in both sets 640 | for value in 0..u8::MAX { 641 | assert_eq!( 642 | intersection.contains(&value), 643 | left.contains(&value) && right.contains(&value) 644 | ); 645 | } 646 | } 647 | 648 | #[proptest] 649 | fn test_intersection_overlaps_u8(left: RangeSet, right: RangeSet) { 650 | let mut union = RangeSet::new(); 651 | for range in left.intersection(&right) { 652 | // there should not be any overlaps in the ranges returned by the 653 | // intersection 654 | assert!(union.overlapping(&range).next().is_none()); 655 | union.insert(range); 656 | } 657 | } 658 | 659 | trait RangeSetExt { 660 | fn to_vec(&self) -> Vec>; 661 | } 662 | 663 | impl RangeSetExt for RangeSet 664 | where 665 | T: Ord + Clone, 666 | { 667 | fn to_vec(&self) -> Vec> { 668 | self.iter().cloned().collect() 669 | } 670 | } 671 | 672 | #[test] 673 | fn empty_set_is_empty() { 674 | let range_set: RangeSet = RangeSet::new(); 675 | assert_eq!(range_set.to_vec(), vec![]); 676 | } 677 | 678 | #[test] 679 | fn insert_into_empty_map() { 680 | let mut range_set: RangeSet = RangeSet::new(); 681 | range_set.insert(0..50); 682 | assert_eq!(range_set.to_vec(), vec![0..50]); 683 | } 684 | 685 | #[test] 686 | fn remove_partially_overlapping() { 687 | let mut range_set: RangeSet = RangeSet::new(); 688 | range_set.insert(0..50); 689 | range_set.remove(25..75); 690 | assert_eq!(range_set.to_vec(), vec![0..25]); 691 | } 692 | 693 | #[test] 694 | fn gaps_between_items_floating_inside_outer_range() { 695 | let mut range_set: RangeSet = RangeSet::new(); 696 | // 0 1 2 3 4 5 6 7 8 9 697 | // ◌ ◌ ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ 698 | range_set.insert(5..6); 699 | // 0 1 2 3 4 5 6 7 8 9 700 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 701 | range_set.insert(3..4); 702 | // 0 1 2 3 4 5 6 7 8 9 703 | // ◌ ◆-------------◇ ◌ 704 | let outer_range = 1..8; 705 | let mut gaps = range_set.gaps(&outer_range); 706 | // Should yield gaps at start, between items, 707 | // and at end. 708 | assert_eq!(gaps.next(), Some(1..3)); 709 | assert_eq!(gaps.next(), Some(4..5)); 710 | assert_eq!(gaps.next(), Some(6..8)); 711 | assert_eq!(gaps.next(), None); 712 | // Gaps iterator should be fused. 713 | assert_eq!(gaps.next(), None); 714 | assert_eq!(gaps.next(), None); 715 | } 716 | 717 | #[test] 718 | fn overlapping_partial_edges_complete_middle() { 719 | let mut range_map: RangeSet = RangeSet::new(); 720 | 721 | // 0 1 2 3 4 5 6 7 8 9 722 | // ●---◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ 723 | range_map.insert(0..2); 724 | // 0 1 2 3 4 5 6 7 8 9 725 | // ◌ ◌ ◌ ●-◌ ◌ ◌ ◌ ◌ ◌ 726 | range_map.insert(3..4); 727 | // 0 1 2 3 4 5 6 7 8 9 728 | // ◌ ◌ ◌ ◌ ◌ ●---◌ ◌ ◌ 729 | range_map.insert(5..7); 730 | 731 | // 0 1 2 3 4 5 6 7 8 9 732 | // ◌ ◆---------◇ ◌ ◌ ◌ 733 | let query_range = 1..6; 734 | 735 | let mut overlapping = range_map.overlapping(&query_range); 736 | 737 | // Should yield partially overlapped range at start. 738 | assert_eq!(overlapping.next(), Some(&(0..2))); 739 | // Should yield completely overlapped range in middle. 740 | assert_eq!(overlapping.next(), Some(&(3..4))); 741 | // Should yield partially overlapped range at end. 742 | assert_eq!(overlapping.next(), Some(&(5..7))); 743 | // Gaps iterator should be fused. 744 | assert_eq!(overlapping.next(), None); 745 | assert_eq!(overlapping.next(), None); 746 | } 747 | 748 | /// 749 | /// impl Debug 750 | /// 751 | 752 | #[test] 753 | fn set_debug_repr_looks_right() { 754 | let mut set: RangeSet = RangeSet::new(); 755 | 756 | // Empty 757 | assert_eq!(format!("{:?}", set), "{}"); 758 | 759 | // One entry 760 | set.insert(2..5); 761 | assert_eq!(format!("{:?}", set), "{2..5}"); 762 | 763 | // Many entries 764 | set.insert(7..8); 765 | set.insert(10..11); 766 | assert_eq!(format!("{:?}", set), "{2..5, 7..8, 10..11}"); 767 | } 768 | 769 | // impl Default where T: ?Default 770 | 771 | #[test] 772 | fn always_default() { 773 | struct NoDefault; 774 | RangeSet::::default(); 775 | } 776 | 777 | // impl Serialize 778 | 779 | #[cfg(feature = "serde1")] 780 | #[test] 781 | fn serialization() { 782 | let mut range_set: RangeSet = RangeSet::new(); 783 | // 0 1 2 3 4 5 6 7 8 9 784 | // ◌ ◆---◇ ◌ ◌ ◌ ◌ ◌ ◌ 785 | range_set.insert(1..3); 786 | // 0 1 2 3 4 5 6 7 8 9 787 | // ◌ ◌ ◌ ◌ ◌ ◆---◇ ◌ ◌ 788 | range_set.insert(5..7); 789 | let output = serde_json::to_string(&range_set).expect("Failed to serialize"); 790 | assert_eq!(output, "[[1,3],[5,7]]"); 791 | } 792 | 793 | // impl Deserialize 794 | 795 | #[cfg(feature = "serde1")] 796 | #[test] 797 | fn deserialization() { 798 | let input = "[[1,3],[5,7]]"; 799 | let range_set: RangeSet = serde_json::from_str(input).expect("Failed to deserialize"); 800 | let reserialized = serde_json::to_string(&range_set).expect("Failed to re-serialize"); 801 | assert_eq!(reserialized, input); 802 | } 803 | 804 | // const fn 805 | 806 | #[cfg(feature = "const_fn")] 807 | const _SET: RangeSet = RangeSet::new(); 808 | 809 | #[cfg(feature = "quickcheck")] 810 | quickcheck::quickcheck! { 811 | fn prop(xs: RangeSet) -> bool { 812 | xs == xs 813 | } 814 | } 815 | } 816 | -------------------------------------------------------------------------------- /src/std_ext.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Range, RangeInclusive, Sub}; 2 | 3 | pub trait RangeExt { 4 | fn overlaps(&self, other: &Self) -> bool; 5 | fn touches(&self, other: &Self) -> bool; 6 | } 7 | 8 | impl RangeExt for Range 9 | where 10 | T: Ord, 11 | { 12 | fn overlaps(&self, other: &Self) -> bool { 13 | use core::cmp::{max, min}; 14 | // Strictly less than, because ends are excluded. 15 | max(&self.start, &other.start) < min(&self.end, &other.end) 16 | } 17 | 18 | fn touches(&self, other: &Self) -> bool { 19 | use core::cmp::{max, min}; 20 | // Less-than-or-equal-to because if one end is excluded, the other is included. 21 | // I.e. the two could be joined into a single range, because they're overlapping 22 | // or immediately adjacent. 23 | max(&self.start, &other.start) <= min(&self.end, &other.end) 24 | } 25 | } 26 | 27 | pub trait RangeInclusiveExt { 28 | fn overlaps(&self, other: &Self) -> bool; 29 | fn touches(&self, other: &Self) -> bool 30 | where 31 | StepFnsT: StepFns; 32 | } 33 | 34 | impl RangeInclusiveExt for RangeInclusive 35 | where 36 | T: Ord + Clone, 37 | { 38 | fn overlaps(&self, other: &Self) -> bool { 39 | use core::cmp::{max, min}; 40 | // Less than or equal, because ends are included. 41 | max(self.start(), other.start()) <= min(self.end(), other.end()) 42 | } 43 | 44 | fn touches(&self, other: &Self) -> bool 45 | where 46 | StepFnsT: StepFns, 47 | { 48 | use core::cmp::{max, min}; 49 | 50 | // Touching for end-inclusive ranges is equivalent to touching of 51 | // slightly longer end-inclusive ranges. 52 | // 53 | // We need to do a small dance to avoid arithmetic overflow 54 | // at the extremes of the key space. And to do this without 55 | // needing to bound our key type on something like `num::Bounded` 56 | // (https://docs.rs/num/0.3.0/num/trait.Bounded.html), 57 | // we'll just extend the end of the _earlier_ range iff 58 | // its end is already earlier than the latter range's start. 59 | let max_start = max(self.start(), other.start()); 60 | let min_range_end = min(self.end(), other.end()); 61 | let min_range_end_extended = if min_range_end < max_start { 62 | StepFnsT::add_one(min_range_end) 63 | } else { 64 | min_range_end.clone() 65 | }; 66 | *max_start <= min_range_end_extended 67 | } 68 | } 69 | 70 | /// Minimal version of unstable [`Step`](core::iter::Step) trait 71 | /// from the Rust standard library. 72 | /// 73 | /// This is needed for [`RangeInclusiveMap`](crate::RangeInclusiveMap) 74 | /// because ranges stored as its keys interact with each other 75 | /// when the start of one is _adjacent_ the end of another. 76 | /// I.e. we need a concept of successor values rather than just 77 | /// equality, and that is what `Step` will 78 | /// eventually provide once it is stabilized. 79 | /// 80 | /// **NOTE:** This will likely be deprecated and then eventually 81 | /// removed once the standard library's `Step` 82 | /// trait is stabilised, as most crates will then likely implement `Step` 83 | /// for their types where appropriate. 84 | /// 85 | /// See [this issue](https://github.com/rust-lang/rust/issues/42168) 86 | /// for details about that stabilization process. 87 | pub trait StepLite { 88 | /// Returns the _successor_ of `self`. 89 | /// 90 | /// If this would overflow the range of values supported by `Self`, 91 | /// this function is allowed to panic, wrap, or saturate. 92 | /// The suggested behavior is to panic when debug assertions are enabled, 93 | /// and to wrap or saturate otherwise. 94 | fn add_one(&self) -> Self; 95 | 96 | /// Returns the _predecessor_ of `self`. 97 | /// 98 | /// If this would overflow the range of values supported by `Self`, 99 | /// this function is allowed to panic, wrap, or saturate. 100 | /// The suggested behavior is to panic when debug assertions are enabled, 101 | /// and to wrap or saturate otherwise. 102 | fn sub_one(&self) -> Self; 103 | } 104 | 105 | // Implement for all common integer types. 106 | macro_rules! impl_step_lite { 107 | ($($t:ty)*) => ($( 108 | impl StepLite for $t { 109 | #[inline] 110 | fn add_one(&self) -> Self { 111 | Add::add(*self, 1) 112 | } 113 | 114 | #[inline] 115 | fn sub_one(&self) -> Self { 116 | Sub::sub(*self, 1) 117 | } 118 | } 119 | )*) 120 | } 121 | 122 | impl_step_lite!(usize u8 u16 u32 u64 u128 i8 i16 i32 i64 i128); 123 | 124 | // TODO: When on nightly, a blanket implementation for 125 | // all types that implement `core::iter::Step` instead 126 | // of the auto-impl above. 127 | 128 | /// Successor and predecessor functions defined for `T`, 129 | /// but as free functions rather than methods on `T` itself. 130 | /// 131 | /// This is useful as a workaround for Rust's "orphan rules", 132 | /// which prevent you from implementing [`StepLite`](crate::StepLite) for `T` if `T` 133 | /// is a foreign type. 134 | /// 135 | /// **NOTE:** This will likely be deprecated and then eventually 136 | /// removed once the standard library's [`Step`](core::iter::Step) 137 | /// trait is stabilised, as most crates will then likely implement `Step` 138 | /// for their types where appropriate. 139 | /// 140 | /// See [this issue](https://github.com/rust-lang/rust/issues/42168) 141 | /// for details about that stabilization process. 142 | /// 143 | /// There is also a blanket implementation of `StepFns` for all 144 | /// types implementing `StepLite`. Consumers of this crate should 145 | /// prefer to implement `StepLite` for their own types, and only 146 | /// fall back to `StepFns` when dealing with foreign types. 147 | pub trait StepFns { 148 | /// Returns the _successor_ of value `start`. 149 | /// 150 | /// If this would overflow the range of values supported by `Self`, 151 | /// this function is allowed to panic, wrap, or saturate. 152 | /// The suggested behavior is to panic when debug assertions are enabled, 153 | /// and to wrap or saturate otherwise. 154 | fn add_one(start: &T) -> T; 155 | 156 | /// Returns the _predecessor_ of value `start`. 157 | /// 158 | /// If this would overflow the range of values supported by `Self`, 159 | /// this function is allowed to panic, wrap, or saturate. 160 | /// The suggested behavior is to panic when debug assertions are enabled, 161 | /// and to wrap or saturate otherwise. 162 | fn sub_one(start: &T) -> T; 163 | } 164 | 165 | impl StepFns for T 166 | where 167 | T: StepLite, 168 | { 169 | fn add_one(start: &T) -> T { 170 | start.add_one() 171 | } 172 | 173 | fn sub_one(start: &T) -> T { 174 | start.sub_one() 175 | } 176 | } 177 | --------------------------------------------------------------------------------