├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches └── lru.rs ├── src ├── lib.rs ├── map.rs ├── serde.rs └── set.rs └── tests ├── linked_hash_map.rs ├── linked_hash_set.rs └── serde.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ritelinked" 3 | version = "0.3.2" 4 | authors = ["DataSlime "] 5 | edition = "2021" 6 | description = "HashMap-like containers that hold their key-value pairs in a user controllable order" 7 | repository = "https://github.com/dataslime/ritelinked" 8 | documentation = "https://docs.rs/ritelinked" 9 | readme = "README.md" 10 | keywords = ["data-structures", "no_std", "linked-hash-map", "linked-hash-set", "amortized"] 11 | categories = ["data-structures", "no-std"] 12 | license = "MIT OR Apache-2.0" 13 | 14 | [features] 15 | default = ["ahash-amortized", "inline-more-amortized"] 16 | 17 | ahash-compile-time-rng = ["ahash_/compile-time-rng"] 18 | 19 | ahash = [ "ahash_", "hashbrown/ahash" ] 20 | serde = [ "serde_", "hashbrown/serde" ] 21 | inline-more = [ "hashbrown/inline-more" ] 22 | 23 | amortized = ["griddle"] 24 | ahash-amortized = [ "ahash", "amortized", "griddle/ahash" ] 25 | serde-amortized = [ "serde", "amortized", "griddle/serde" ] 26 | inline-more-amortized = [ "inline-more", "amortized", "griddle/inline-more" ] 27 | 28 | [dependencies] 29 | ahash_ = { version = "0.8.5", default-features = false, optional = true, package = "ahash" } 30 | hashbrown = { version = "0.11", default-features = false } 31 | griddle = { version = "0.5.1", default-features = false, optional = true } 32 | serde_ = { version = "1.0", default-features = false, optional = true, package = "serde" } 33 | 34 | [dev-dependencies] 35 | # test 36 | fnv = "1.0.7" 37 | serde_test = "1.0" 38 | # bench 39 | criterion = "0.3" 40 | hashlink = "0.7" 41 | linked-hash-map = "0.5" 42 | 43 | [[bench]] 44 | name = "lru" 45 | harness = false 46 | 47 | [profile.release] 48 | debug = true 49 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 DataSlime 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | RiteLinked 4 |

5 | 6 |

7 | HashMap-like containers that hold their key-value pairs in a user controllable order 8 |

9 |
10 | 11 | [![Latest Version](https://img.shields.io/crates/v/ritelinked.svg)](https://crates.io/crates/ritelinked) 12 | [![API Documentation](https://docs.rs/ritelinked/badge.svg)](https://docs.rs/ritelinked) 13 | 14 | [RiteLinked](https://crates.io/crates/ritelinked) provides more up to date versions of `LinkedHashMap` & `LinkedHashSet` . 15 | You can easily use it on `std` or `no_std` environment. 16 | 17 | Support some practical feature combinations to help you better embed them in existing code: `serde`, `inline-more` etc. 18 | Especially, it uses `griddle` by default, if you have a lot of data, it can effectively help you reduce the possible tail delay. (Of course, `hashbrown` can also be used) 19 | 20 | ## Usage 21 | 22 | Add `ritelinked` to `Cargo.toml`: 23 | 24 | ```toml 25 | ritelinked = "x.y.z" 26 | ``` 27 | 28 | Write some code like this: 29 | 30 | ``` rust 31 | let mut lru_cache = LinkedHashMap::new(); 32 | let key = "key".to_owned(); 33 | let _cached_val = lru_cache 34 | .raw_entry_mut() 35 | .from_key(&key) 36 | .or_insert_with(|| (key.clone(), 42)); 37 | ``` 38 | 39 | ## Benchmark 40 | 41 | ``` 42 | ritelinked time: [140.15 ns 141.06 ns 142.15 ns] 43 | Found 11 outliers among 100 measurements (11.00%) 44 | 8 (8.00%) high mild 45 | 3 (3.00%) high severe 46 | 47 | hashlink time: [147.01 ns 147.87 ns 148.75 ns] 48 | Found 11 outliers among 100 measurements (11.00%) 49 | 4 (4.00%) high mild 50 | 7 (7.00%) high severe 51 | 52 | linked-hash-map time: [301.44 ns 309.86 ns 319.40 ns] 53 | Found 12 outliers among 100 measurements (12.00%) 54 | 9 (9.00%) high mild 55 | 3 (3.00%) high severe 56 | ``` 57 | 58 | ## Credit 59 | 60 | It is a fork of the popular crate [hashlink](https://crates.io/crates/hashlink), but more adjustments and improvements have been made to the code . 61 | 62 | ## License 63 | 64 | This library is licensed the same as [hashlink](https://github.com/kyren/hashlink), 65 | it is licensed under either of: 66 | 67 | * MIT license [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT 68 | * Apache License 2.0 [LICENSE-APACHE](LICENSE-APACHE) or https://opensource.org/licenses/Apache-2.0 69 | 70 | at your option. 71 | -------------------------------------------------------------------------------- /benches/lru.rs: -------------------------------------------------------------------------------- 1 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; 2 | use std::collections::hash_map; 3 | 4 | struct Bar([u64; 4]); 5 | 6 | const CAP: usize = 1 << 22; 7 | 8 | fn bench_ritelinked(c: &mut Criterion) { 9 | use ritelinked::LinkedHashMap; 10 | 11 | c.bench_function("ritelinked", |b| { 12 | let mut map = LinkedHashMap::with_capacity_and_hasher(CAP, hash_map::RandomState::new()); 13 | let mut count = 0; 14 | 15 | b.iter(|| { 16 | count += 1; 17 | let bar = black_box(Bar([0x42; 4])); 18 | map.insert(count, bar); 19 | if map.len() >= CAP { 20 | map.pop_front(); 21 | } 22 | }); 23 | }); 24 | } 25 | 26 | fn bench_hashlink(c: &mut Criterion) { 27 | use hashlink::LinkedHashMap; 28 | 29 | c.bench_function("hashlink", |b| { 30 | let mut map = LinkedHashMap::with_capacity_and_hasher(CAP, hash_map::RandomState::new()); 31 | let mut count = 0; 32 | 33 | b.iter(|| { 34 | count += 1; 35 | let bar = black_box(Bar([0x42; 4])); 36 | map.insert(count, bar); 37 | if map.len() >= CAP { 38 | map.pop_front(); 39 | } 40 | }); 41 | }); 42 | } 43 | 44 | fn bench_linked_hash_map(c: &mut Criterion) { 45 | use linked_hash_map::LinkedHashMap; 46 | 47 | c.bench_function("linked-hash-map", |b| { 48 | let mut map = LinkedHashMap::with_capacity_and_hasher(CAP, hash_map::RandomState::new()); 49 | let mut count = 0; 50 | 51 | b.iter(|| { 52 | count += 1; 53 | let bar = black_box(Bar([0x42; 4])); 54 | map.insert(count, bar); 55 | if map.len() >= CAP { 56 | map.pop_front(); 57 | } 58 | }); 59 | }); 60 | } 61 | 62 | criterion_group!(lru, bench_ritelinked, bench_hashlink, bench_linked_hash_map); 63 | criterion_main!(lru); 64 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | extern crate alloc; 4 | 5 | mod map; 6 | mod set; 7 | 8 | pub mod linked_hash_map { 9 | //! A linked hash map implementation. The order of entries defaults to "insertion order". 10 | pub use crate::map::*; 11 | } 12 | pub mod linked_hash_set { 13 | //! A linked hash set implementation. The order of entries defaults to "insertion order". 14 | pub use crate::set::*; 15 | } 16 | 17 | #[cfg(feature = "serde")] 18 | pub mod serde; 19 | 20 | pub use crate::map::LinkedHashMap; 21 | pub use crate::set::LinkedHashSet; 22 | 23 | #[doc(inline)] 24 | pub use hashbrown::hash_map::DefaultHashBuilder; 25 | pub use hashbrown::TryReserveError; 26 | -------------------------------------------------------------------------------- /src/map.rs: -------------------------------------------------------------------------------- 1 | use crate::DefaultHashBuilder; 2 | use crate::TryReserveError; 3 | 4 | use alloc::boxed::Box; 5 | use core::{ 6 | borrow::Borrow, 7 | cmp::Ordering, 8 | fmt, 9 | hash::{BuildHasher, Hash, Hasher}, 10 | iter::FromIterator, 11 | marker::PhantomData, 12 | mem::{self, MaybeUninit}, 13 | ops::{Index, IndexMut}, 14 | ptr::{self, NonNull}, 15 | }; 16 | 17 | #[cfg(not(feature = "amortized"))] 18 | use hashbrown::{hash_map, HashMap}; 19 | 20 | #[cfg(feature = "amortized")] 21 | use griddle::{hash_map, HashMap}; 22 | 23 | /// A version of `HashMap` that has a user controllable order for its entries. 24 | /// 25 | /// It achieves this by keeping its entries in an internal linked list and using a `HashMap` to 26 | /// point at nodes in this linked list. 27 | /// 28 | /// The order of entries defaults to "insertion order", but the user can also modify the order of 29 | /// existing entries by manually moving them to the front or back. 30 | /// 31 | /// There are two kinds of methods that modify the order of the internal list: 32 | /// 33 | /// * Methods that have names like `to_front` and `to_back` will unsurprisingly move an existing 34 | /// entry to the front or back 35 | /// * Methods that have the word `insert` will insert a new entry ot the back of the list, and if 36 | /// that method might replace an entry, that method will *also move that existing entry to the 37 | /// back*. 38 | pub struct LinkedHashMap { 39 | map: HashMap>, (), NullHasher>, 40 | // We need to keep any custom hash builder outside of the HashMap so we can access it alongside 41 | // the entry API without mutable aliasing. 42 | hash_builder: S, 43 | // Circular linked list of nodes. If `values` is non-null, it will point to a "guard node" 44 | // which will never have an initialized key or value, `values.prev` will contain the last key / 45 | // value in the list, `values.next` will contain the first key / value in the list. 46 | values: Option>>, 47 | // *Singly* linked list of free nodes. The `prev` pointers in the free list should be assumed 48 | // invalid. 49 | free: Option>>, 50 | } 51 | 52 | #[cfg(feature = "ahash")] 53 | impl LinkedHashMap { 54 | #[cfg_attr(feature = "inline-more", inline)] 55 | pub fn new() -> Self { 56 | Self::default() 57 | } 58 | 59 | #[cfg_attr(feature = "inline-more", inline)] 60 | pub fn with_capacity(capacity: usize) -> Self { 61 | Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default()) 62 | } 63 | } 64 | 65 | impl LinkedHashMap { 66 | #[cfg_attr(feature = "inline-more", inline)] 67 | pub fn with_hasher(hash_builder: S) -> Self { 68 | Self { 69 | hash_builder, 70 | map: HashMap::with_hasher(NullHasher), 71 | values: None, 72 | free: None, 73 | } 74 | } 75 | 76 | #[cfg_attr(feature = "inline-more", inline)] 77 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { 78 | Self { 79 | hash_builder, 80 | map: HashMap::with_capacity_and_hasher(capacity, NullHasher), 81 | values: None, 82 | free: None, 83 | } 84 | } 85 | 86 | #[cfg_attr(feature = "inline-more", inline)] 87 | pub fn reserve(&mut self, additional: usize) { 88 | self.map.reserve(additional); 89 | } 90 | 91 | #[cfg_attr(feature = "inline-more", inline)] 92 | pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { 93 | self.map.try_reserve(additional) 94 | } 95 | 96 | #[cfg_attr(feature = "inline-more", inline)] 97 | pub fn shrink_to_fit(&mut self) { 98 | self.map.shrink_to_fit(); 99 | unsafe { drop_free_nodes(self.free) }; 100 | self.free = None; 101 | } 102 | 103 | #[cfg_attr(feature = "inline-more", inline)] 104 | pub fn len(&self) -> usize { 105 | self.map.len() 106 | } 107 | 108 | #[cfg_attr(feature = "inline-more", inline)] 109 | pub fn is_empty(&self) -> bool { 110 | self.len() == 0 111 | } 112 | 113 | #[cfg_attr(feature = "inline-more", inline)] 114 | pub fn clear(&mut self) { 115 | self.map.clear(); 116 | if let Some(mut values) = self.values { 117 | unsafe { 118 | drop_value_nodes(values); 119 | values.as_mut().links.value = ValueLinks { 120 | prev: values, 121 | next: values, 122 | }; 123 | } 124 | } 125 | } 126 | 127 | #[cfg_attr(feature = "inline-more", inline)] 128 | pub fn iter(&self) -> Iter { 129 | let (head, tail) = if let Some(values) = self.values { 130 | unsafe { 131 | let ValueLinks { next, prev } = values.as_ref().links.value; 132 | (next.as_ptr(), prev.as_ptr()) 133 | } 134 | } else { 135 | (ptr::null_mut(), ptr::null_mut()) 136 | }; 137 | 138 | Iter { 139 | head, 140 | tail, 141 | remaining: self.len(), 142 | marker: PhantomData, 143 | } 144 | } 145 | 146 | #[cfg_attr(feature = "inline-more", inline)] 147 | pub fn iter_mut(&mut self) -> IterMut { 148 | let (head, tail) = if let Some(values) = self.values { 149 | unsafe { 150 | let ValueLinks { next, prev } = values.as_ref().links.value; 151 | (Some(next), Some(prev)) 152 | } 153 | } else { 154 | (None, None) 155 | }; 156 | 157 | IterMut { 158 | head, 159 | tail, 160 | remaining: self.len(), 161 | marker: PhantomData, 162 | } 163 | } 164 | 165 | #[cfg_attr(feature = "inline-more", inline)] 166 | pub fn drain(&mut self) -> Drain<'_, K, V> { 167 | unsafe { 168 | let (head, tail) = if let Some(mut values) = self.values { 169 | let ValueLinks { next, prev } = values.as_ref().links.value; 170 | values.as_mut().links.value = ValueLinks { 171 | next: values, 172 | prev: values, 173 | }; 174 | (Some(next), Some(prev)) 175 | } else { 176 | (None, None) 177 | }; 178 | let len = self.len(); 179 | 180 | self.map.clear(); 181 | 182 | Drain { 183 | free: (&mut self.free).into(), 184 | head, 185 | tail, 186 | remaining: len, 187 | marker: PhantomData, 188 | } 189 | } 190 | } 191 | 192 | #[cfg_attr(feature = "inline-more", inline)] 193 | pub fn keys(&self) -> Keys { 194 | Keys { inner: self.iter() } 195 | } 196 | 197 | #[cfg_attr(feature = "inline-more", inline)] 198 | pub fn values(&self) -> Values { 199 | Values { inner: self.iter() } 200 | } 201 | 202 | #[cfg_attr(feature = "inline-more", inline)] 203 | pub fn values_mut(&mut self) -> ValuesMut { 204 | ValuesMut { 205 | inner: self.iter_mut(), 206 | } 207 | } 208 | 209 | #[cfg_attr(feature = "inline-more", inline)] 210 | pub fn front(&self) -> Option<(&K, &V)> { 211 | if self.is_empty() { 212 | return None; 213 | } 214 | unsafe { 215 | let front = (*self.values.as_ptr()).links.value.next.as_ptr(); 216 | let (key, value) = (*front).entry_ref(); 217 | Some((key, value)) 218 | } 219 | } 220 | 221 | #[cfg_attr(feature = "inline-more", inline)] 222 | pub fn back(&self) -> Option<(&K, &V)> { 223 | if self.is_empty() { 224 | return None; 225 | } 226 | unsafe { 227 | let back = &*(*self.values.as_ptr()).links.value.prev.as_ptr(); 228 | let (key, value) = (*back).entry_ref(); 229 | Some((key, value)) 230 | } 231 | } 232 | 233 | #[cfg_attr(feature = "inline-more", inline)] 234 | pub fn hasher(&self) -> &S { 235 | &self.hash_builder 236 | } 237 | 238 | #[cfg_attr(feature = "inline-more", inline)] 239 | pub fn capacity(&self) -> usize { 240 | self.map.capacity() 241 | } 242 | } 243 | 244 | impl LinkedHashMap 245 | where 246 | K: Eq + Hash, 247 | S: BuildHasher, 248 | { 249 | #[cfg_attr(feature = "inline-more", inline)] 250 | pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { 251 | match self.raw_entry_mut().from_key(&key) { 252 | RawEntryMut::Occupied(occupied) => Entry::Occupied(OccupiedEntry { 253 | key, 254 | raw_entry: occupied, 255 | }), 256 | RawEntryMut::Vacant(vacant) => Entry::Vacant(VacantEntry { 257 | key, 258 | raw_entry: vacant, 259 | }), 260 | } 261 | } 262 | 263 | #[inline] 264 | pub fn get(&self, k: &Q) -> Option<&V> 265 | where 266 | K: Borrow, 267 | Q: Hash + Eq + ?Sized, 268 | { 269 | self.raw_entry().from_key(k).map(|(_, v)| v) 270 | } 271 | 272 | #[inline] 273 | pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> 274 | where 275 | K: Borrow, 276 | Q: Hash + Eq + ?Sized, 277 | { 278 | self.raw_entry().from_key(k) 279 | } 280 | 281 | #[cfg_attr(feature = "inline-more", inline)] 282 | pub fn contains_key(&self, k: &Q) -> bool 283 | where 284 | K: Borrow, 285 | Q: Hash + Eq + ?Sized, 286 | { 287 | self.get(k).is_some() 288 | } 289 | 290 | #[cfg_attr(feature = "inline-more", inline)] 291 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 292 | where 293 | K: Borrow, 294 | Q: Hash + Eq + ?Sized, 295 | { 296 | match self.raw_entry_mut().from_key(k) { 297 | RawEntryMut::Occupied(occupied) => Some(occupied.into_mut()), 298 | RawEntryMut::Vacant(_) => None, 299 | } 300 | } 301 | 302 | #[cfg_attr(feature = "inline-more", inline)] 303 | pub fn get_refresh(&mut self, k: &Q) -> Option<&mut V> 304 | where 305 | K: Borrow, 306 | Q: Hash + Eq + ?Sized, 307 | { 308 | match self.raw_entry_mut().from_key(k) { 309 | RawEntryMut::Occupied(mut occupied) => { 310 | occupied.to_back(); 311 | Some(occupied.into_mut()) 312 | } 313 | RawEntryMut::Vacant(_) => None, 314 | } 315 | } 316 | 317 | /// Inserts the given key / value pair at the *back* of the internal linked list. 318 | /// 319 | /// Returns the previously set value, if one existed prior to this call. After this call, 320 | /// calling `LinkedHashMap::back` will return a reference to this key / value pair. 321 | #[cfg_attr(feature = "inline-more", inline)] 322 | pub fn insert(&mut self, k: K, v: V) -> Option { 323 | match self.raw_entry_mut().from_key(&k) { 324 | RawEntryMut::Occupied(mut occupied) => { 325 | occupied.to_back(); 326 | Some(occupied.replace_value(v)) 327 | } 328 | RawEntryMut::Vacant(vacant) => { 329 | vacant.insert(k, v); 330 | None 331 | } 332 | } 333 | } 334 | 335 | /// If the given key is not in this map, inserts the key / value pair at the *back* of the 336 | /// internal linked list and returns `None`, otherwise, replaces the existing value with the 337 | /// given value *without* moving the entry in the internal linked list and returns the previous 338 | /// value. 339 | #[cfg_attr(feature = "inline-more", inline)] 340 | pub fn replace(&mut self, k: K, v: V) -> Option { 341 | match self.raw_entry_mut().from_key(&k) { 342 | RawEntryMut::Occupied(mut occupied) => Some(occupied.replace_value(v)), 343 | RawEntryMut::Vacant(vacant) => { 344 | vacant.insert(k, v); 345 | None 346 | } 347 | } 348 | } 349 | 350 | #[cfg_attr(feature = "inline-more", inline)] 351 | pub fn remove(&mut self, k: &Q) -> Option 352 | where 353 | K: Borrow, 354 | Q: Hash + Eq + ?Sized, 355 | { 356 | match self.raw_entry_mut().from_key(k) { 357 | RawEntryMut::Occupied(occupied) => Some(occupied.remove()), 358 | RawEntryMut::Vacant(_) => None, 359 | } 360 | } 361 | 362 | #[cfg_attr(feature = "inline-more", inline)] 363 | pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> 364 | where 365 | K: Borrow, 366 | Q: Hash + Eq + ?Sized, 367 | { 368 | match self.raw_entry_mut().from_key(k) { 369 | RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry()), 370 | RawEntryMut::Vacant(_) => None, 371 | } 372 | } 373 | 374 | #[cfg_attr(feature = "inline-more", inline)] 375 | pub fn retain(&mut self, mut f: F) 376 | where 377 | F: FnMut(&K, &mut V) -> bool, 378 | { 379 | // We do not drop the key and value when a value is filtered from the map during the call to 380 | // `retain`. We need to be very careful not to have a live `HashMap` entry pointing to 381 | // either a dangling `Node` or a `Node` with dropped keys / values. Since the key and value 382 | // types may panic on drop, they may short-circuit the entry in the map actually being 383 | // removed. Instead, we push the removed nodes onto the free list eagerly, then try and 384 | // drop the keys and values for any newly freed nodes *after* `HashMap::retain` has 385 | // completely finished. 386 | struct DropFilteredValues<'a, K, V> { 387 | free: &'a mut Option>>, 388 | cur_free: Option>>, 389 | } 390 | 391 | impl<'a, K, V> DropFilteredValues<'a, K, V> { 392 | #[inline] 393 | fn drop_later(&mut self, node: NonNull>) { 394 | unsafe { 395 | detach_node(node); 396 | push_free(&mut self.cur_free, node); 397 | } 398 | } 399 | } 400 | 401 | impl<'a, K, V> Drop for DropFilteredValues<'a, K, V> { 402 | fn drop(&mut self) { 403 | unsafe { 404 | let end_free = self.cur_free; 405 | while self.cur_free != *self.free { 406 | let cur_free = self.cur_free.as_ptr(); 407 | (*cur_free).take_entry(); 408 | self.cur_free = (*cur_free).links.free.next; 409 | } 410 | *self.free = end_free; 411 | } 412 | } 413 | } 414 | 415 | let free = self.free; 416 | let mut drop_filtered_values = DropFilteredValues { 417 | free: &mut self.free, 418 | cur_free: free, 419 | }; 420 | 421 | if let Some(values) = self.values { 422 | unsafe { 423 | let mut cur = values.as_ref().links.value.next; 424 | while cur != values { 425 | let next = cur.as_ref().links.value.next; 426 | let (k, v) = (*cur.as_ptr()).entry_mut(); 427 | if !f(k, v) { 428 | let hash = hash_key(&self.hash_builder, k); 429 | match self 430 | .map 431 | .raw_entry_mut() 432 | .from_hash(hash, |o| (*o).as_ref().key_ref().eq(k)) 433 | { 434 | hash_map::RawEntryMut::Occupied(entry) => { 435 | entry.remove(); 436 | drop_filtered_values.drop_later(cur); 437 | } 438 | hash_map::RawEntryMut::Vacant(_) => unreachable!(), 439 | } 440 | } 441 | cur = next; 442 | } 443 | } 444 | } 445 | } 446 | 447 | #[cfg_attr(feature = "inline-more", inline)] 448 | pub fn pop_front(&mut self) -> Option<(K, V)> { 449 | if self.is_empty() { 450 | return None; 451 | } 452 | unsafe { 453 | let front = (*self.values.as_ptr()).links.value.next; 454 | match self.map.raw_entry_mut().from_hash( 455 | hash_key(&self.hash_builder, front.as_ref().key_ref()), 456 | |k| (*k).as_ref().key_ref().eq(front.as_ref().key_ref()), 457 | ) { 458 | hash_map::RawEntryMut::Occupied(occupied) => { 459 | Some(remove_node(&mut self.free, occupied.remove_entry().0)) 460 | } 461 | hash_map::RawEntryMut::Vacant(_) => None, 462 | } 463 | } 464 | } 465 | 466 | #[cfg_attr(feature = "inline-more", inline)] 467 | pub fn pop_back(&mut self) -> Option<(K, V)> { 468 | if self.is_empty() { 469 | return None; 470 | } 471 | unsafe { 472 | let back = (*self.values.as_ptr()).links.value.prev; 473 | match self 474 | .map 475 | .raw_entry_mut() 476 | .from_hash(hash_key(&self.hash_builder, back.as_ref().key_ref()), |k| { 477 | (*k).as_ref().key_ref().eq(back.as_ref().key_ref()) 478 | }) { 479 | hash_map::RawEntryMut::Occupied(occupied) => { 480 | Some(remove_node(&mut self.free, occupied.remove_entry().0)) 481 | } 482 | hash_map::RawEntryMut::Vacant(_) => None, 483 | } 484 | } 485 | } 486 | 487 | /// If an entry with this key exists, move it to the front of the list and return a reference to 488 | /// the value. 489 | #[cfg_attr(feature = "inline-more", inline)] 490 | #[allow(clippy::wrong_self_convention)] 491 | pub fn to_front(&mut self, k: &Q) -> Option<&mut V> 492 | where 493 | K: Borrow, 494 | Q: Hash + Eq + ?Sized, 495 | { 496 | match self.raw_entry_mut().from_key(k) { 497 | RawEntryMut::Occupied(mut occupied) => { 498 | occupied.to_front(); 499 | Some(occupied.into_mut()) 500 | } 501 | RawEntryMut::Vacant(_) => None, 502 | } 503 | } 504 | 505 | /// If an entry with this key exists, move it to the back of the list and return a reference to 506 | /// the value. 507 | #[cfg_attr(feature = "inline-more", inline)] 508 | #[allow(clippy::wrong_self_convention)] 509 | pub fn to_back(&mut self, k: &Q) -> Option<&mut V> 510 | where 511 | K: Borrow, 512 | Q: Hash + Eq + ?Sized, 513 | { 514 | match self.raw_entry_mut().from_key(k) { 515 | RawEntryMut::Occupied(mut occupied) => { 516 | occupied.to_back(); 517 | Some(occupied.into_mut()) 518 | } 519 | RawEntryMut::Vacant(_) => None, 520 | } 521 | } 522 | } 523 | 524 | impl LinkedHashMap 525 | where 526 | S: BuildHasher, 527 | { 528 | #[cfg_attr(feature = "inline-more", inline)] 529 | pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { 530 | RawEntryBuilder { 531 | hash_builder: &self.hash_builder, 532 | entry: self.map.raw_entry(), 533 | } 534 | } 535 | 536 | #[cfg_attr(feature = "inline-more", inline)] 537 | pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { 538 | RawEntryBuilderMut { 539 | hash_builder: &self.hash_builder, 540 | values: &mut self.values, 541 | free: &mut self.free, 542 | entry: self.map.raw_entry_mut(), 543 | } 544 | } 545 | } 546 | 547 | impl Default for LinkedHashMap 548 | where 549 | S: Default, 550 | { 551 | #[cfg_attr(feature = "inline-more", inline)] 552 | fn default() -> Self { 553 | Self::with_hasher(S::default()) 554 | } 555 | } 556 | 557 | impl FromIterator<(K, V)> for LinkedHashMap { 558 | #[cfg_attr(feature = "inline-more", inline)] 559 | fn from_iter>(iter: I) -> Self { 560 | let iter = iter.into_iter(); 561 | let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default()); 562 | map.extend(iter); 563 | map 564 | } 565 | } 566 | 567 | impl fmt::Debug for LinkedHashMap 568 | where 569 | K: fmt::Debug, 570 | V: fmt::Debug, 571 | { 572 | #[cfg_attr(feature = "inline-more", inline)] 573 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 574 | f.debug_map().entries(self).finish() 575 | } 576 | } 577 | 578 | impl PartialEq for LinkedHashMap { 579 | #[cfg_attr(feature = "inline-more", inline)] 580 | fn eq(&self, other: &Self) -> bool { 581 | self.len() == other.len() && self.iter().eq(other) 582 | } 583 | } 584 | 585 | impl Eq for LinkedHashMap {} 586 | 587 | impl PartialOrd 588 | for LinkedHashMap 589 | { 590 | #[cfg_attr(feature = "inline-more", inline)] 591 | fn partial_cmp(&self, other: &Self) -> Option { 592 | self.iter().partial_cmp(other) 593 | } 594 | 595 | #[cfg_attr(feature = "inline-more", inline)] 596 | fn lt(&self, other: &Self) -> bool { 597 | self.iter().lt(other) 598 | } 599 | 600 | #[cfg_attr(feature = "inline-more", inline)] 601 | fn le(&self, other: &Self) -> bool { 602 | self.iter().le(other) 603 | } 604 | 605 | #[cfg_attr(feature = "inline-more", inline)] 606 | fn ge(&self, other: &Self) -> bool { 607 | self.iter().ge(other) 608 | } 609 | 610 | #[cfg_attr(feature = "inline-more", inline)] 611 | fn gt(&self, other: &Self) -> bool { 612 | self.iter().gt(other) 613 | } 614 | } 615 | 616 | impl Ord for LinkedHashMap { 617 | #[cfg_attr(feature = "inline-more", inline)] 618 | fn cmp(&self, other: &Self) -> Ordering { 619 | self.iter().cmp(other) 620 | } 621 | } 622 | 623 | impl Hash for LinkedHashMap { 624 | #[cfg_attr(feature = "inline-more", inline)] 625 | fn hash(&self, h: &mut H) { 626 | for e in self.iter() { 627 | e.hash(h); 628 | } 629 | } 630 | } 631 | 632 | impl Drop for LinkedHashMap { 633 | #[cfg_attr(feature = "inline-more", inline)] 634 | fn drop(&mut self) { 635 | unsafe { 636 | if let Some(values) = self.values { 637 | drop_value_nodes(values); 638 | Box::from_raw(values.as_ptr()); 639 | } 640 | drop_free_nodes(self.free); 641 | } 642 | } 643 | } 644 | 645 | unsafe impl Send for LinkedHashMap {} 646 | unsafe impl Sync for LinkedHashMap {} 647 | 648 | impl<'a, K, V, S, Q> Index<&'a Q> for LinkedHashMap 649 | where 650 | K: Hash + Eq + Borrow, 651 | S: BuildHasher, 652 | Q: Eq + Hash + ?Sized, 653 | { 654 | type Output = V; 655 | 656 | #[cfg_attr(feature = "inline-more", inline)] 657 | fn index(&self, index: &'a Q) -> &V { 658 | self.get(index).expect("no entry found for key") 659 | } 660 | } 661 | 662 | impl<'a, K, V, S, Q> IndexMut<&'a Q> for LinkedHashMap 663 | where 664 | K: Hash + Eq + Borrow, 665 | S: BuildHasher, 666 | Q: Eq + Hash + ?Sized, 667 | { 668 | #[cfg_attr(feature = "inline-more", inline)] 669 | fn index_mut(&mut self, index: &'a Q) -> &mut V { 670 | self.get_mut(index).expect("no entry found for key") 671 | } 672 | } 673 | 674 | impl Clone for LinkedHashMap { 675 | #[cfg_attr(feature = "inline-more", inline)] 676 | fn clone(&self) -> Self { 677 | let mut map = Self::with_hasher(self.hash_builder.clone()); 678 | map.extend(self.iter().map(|(k, v)| (k.clone(), v.clone()))); 679 | map 680 | } 681 | } 682 | 683 | impl Extend<(K, V)> for LinkedHashMap { 684 | #[cfg_attr(feature = "inline-more", inline)] 685 | fn extend>(&mut self, iter: I) { 686 | for (k, v) in iter { 687 | self.insert(k, v); 688 | } 689 | } 690 | } 691 | 692 | impl<'a, K, V, S> Extend<(&'a K, &'a V)> for LinkedHashMap 693 | where 694 | K: 'a + Hash + Eq + Copy, 695 | V: 'a + Copy, 696 | S: BuildHasher, 697 | { 698 | #[cfg_attr(feature = "inline-more", inline)] 699 | fn extend>(&mut self, iter: I) { 700 | for (&k, &v) in iter { 701 | self.insert(k, v); 702 | } 703 | } 704 | } 705 | 706 | pub enum Entry<'a, K, V, S> { 707 | Occupied(OccupiedEntry<'a, K, V>), 708 | Vacant(VacantEntry<'a, K, V, S>), 709 | } 710 | 711 | impl fmt::Debug for Entry<'_, K, V, S> { 712 | #[cfg_attr(feature = "inline-more", inline)] 713 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 714 | match *self { 715 | Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), 716 | Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), 717 | } 718 | } 719 | } 720 | 721 | impl<'a, K, V, S> Entry<'a, K, V, S> { 722 | /// If this entry is vacant, inserts a new entry with the given value and returns a reference to 723 | /// it. 724 | /// 725 | /// If this entry is occupied, this method *moves the occupied entry to the back of the internal 726 | /// linked list* and returns a reference to the existing value. 727 | #[cfg_attr(feature = "inline-more", inline)] 728 | pub fn or_insert(self, default: V) -> &'a mut V 729 | where 730 | K: Hash, 731 | S: BuildHasher, 732 | { 733 | match self { 734 | Entry::Occupied(mut entry) => { 735 | entry.to_back(); 736 | entry.into_mut() 737 | } 738 | Entry::Vacant(entry) => entry.insert(default), 739 | } 740 | } 741 | 742 | /// Similar to `Entry::or_insert`, but accepts a function to construct a new value if this entry 743 | /// is vacant. 744 | #[cfg_attr(feature = "inline-more", inline)] 745 | pub fn or_insert_with V>(self, default: F) -> &'a mut V 746 | where 747 | K: Hash, 748 | S: BuildHasher, 749 | { 750 | match self { 751 | Entry::Occupied(mut entry) => { 752 | entry.to_back(); 753 | entry.into_mut() 754 | } 755 | Entry::Vacant(entry) => entry.insert(default()), 756 | } 757 | } 758 | 759 | #[cfg_attr(feature = "inline-more", inline)] 760 | pub fn key(&self) -> &K { 761 | match *self { 762 | Entry::Occupied(ref entry) => entry.key(), 763 | Entry::Vacant(ref entry) => entry.key(), 764 | } 765 | } 766 | 767 | #[cfg_attr(feature = "inline-more", inline)] 768 | pub fn and_modify(self, f: F) -> Self 769 | where 770 | F: FnOnce(&mut V), 771 | { 772 | match self { 773 | Entry::Occupied(mut entry) => { 774 | f(entry.get_mut()); 775 | Entry::Occupied(entry) 776 | } 777 | Entry::Vacant(entry) => Entry::Vacant(entry), 778 | } 779 | } 780 | } 781 | 782 | pub struct OccupiedEntry<'a, K, V> { 783 | key: K, 784 | raw_entry: RawOccupiedEntryMut<'a, K, V>, 785 | } 786 | 787 | impl fmt::Debug for OccupiedEntry<'_, K, V> { 788 | #[cfg_attr(feature = "inline-more", inline)] 789 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 790 | f.debug_struct("OccupiedEntry") 791 | .field("key", self.key()) 792 | .field("value", self.get()) 793 | .finish() 794 | } 795 | } 796 | 797 | impl<'a, K, V> OccupiedEntry<'a, K, V> { 798 | #[cfg_attr(feature = "inline-more", inline)] 799 | pub fn key(&self) -> &K { 800 | self.raw_entry.key() 801 | } 802 | 803 | #[cfg_attr(feature = "inline-more", inline)] 804 | pub fn remove_entry(self) -> (K, V) { 805 | self.raw_entry.remove_entry() 806 | } 807 | 808 | #[cfg_attr(feature = "inline-more", inline)] 809 | pub fn get(&self) -> &V { 810 | self.raw_entry.get() 811 | } 812 | 813 | #[cfg_attr(feature = "inline-more", inline)] 814 | pub fn get_mut(&mut self) -> &mut V { 815 | self.raw_entry.get_mut() 816 | } 817 | 818 | #[cfg_attr(feature = "inline-more", inline)] 819 | pub fn into_mut(self) -> &'a mut V { 820 | self.raw_entry.into_mut() 821 | } 822 | 823 | #[cfg_attr(feature = "inline-more", inline)] 824 | #[allow(clippy::wrong_self_convention)] 825 | pub fn to_back(&mut self) { 826 | self.raw_entry.to_back() 827 | } 828 | 829 | #[cfg_attr(feature = "inline-more", inline)] 830 | #[allow(clippy::wrong_self_convention)] 831 | pub fn to_front(&mut self) { 832 | self.raw_entry.to_front() 833 | } 834 | 835 | /// Replaces this entry's value with the provided value. 836 | /// 837 | /// Similarly to `LinkedHashMap::insert`, this moves the existing entry to the back of the 838 | /// internal linked list. 839 | #[cfg_attr(feature = "inline-more", inline)] 840 | pub fn insert(&mut self, value: V) -> V { 841 | self.raw_entry.to_back(); 842 | self.raw_entry.replace_value(value) 843 | } 844 | 845 | #[cfg_attr(feature = "inline-more", inline)] 846 | pub fn remove(self) -> V { 847 | self.raw_entry.remove() 848 | } 849 | 850 | /// Similar to `OccupiedEntry::replace_entry`, but *does* move the entry to the back of the 851 | /// internal linked list. 852 | #[cfg_attr(feature = "inline-more", inline)] 853 | pub fn insert_entry(mut self, value: V) -> (K, V) { 854 | self.raw_entry.to_back(); 855 | self.replace_entry(value) 856 | } 857 | 858 | /// Replaces the entry's key with the key provided to `LinkedHashMap::entry`, and replaces the 859 | /// entry's value with the given `value` parameter. 860 | /// 861 | /// Does *not* move the entry to the back of the internal linked list. 862 | pub fn replace_entry(mut self, value: V) -> (K, V) { 863 | let old_key = mem::replace(self.raw_entry.key_mut(), self.key); 864 | let old_value = mem::replace(self.raw_entry.get_mut(), value); 865 | (old_key, old_value) 866 | } 867 | 868 | /// Replaces this entry's key with the key provided to `LinkedHashMap::entry`. 869 | /// 870 | /// Does *not* move the entry to the back of the internal linked list. 871 | #[cfg_attr(feature = "inline-more", inline)] 872 | pub fn replace_key(mut self) -> K { 873 | mem::replace(self.raw_entry.key_mut(), self.key) 874 | } 875 | } 876 | 877 | pub struct VacantEntry<'a, K, V, S> { 878 | key: K, 879 | raw_entry: RawVacantEntryMut<'a, K, V, S>, 880 | } 881 | 882 | impl fmt::Debug for VacantEntry<'_, K, V, S> { 883 | #[cfg_attr(feature = "inline-more", inline)] 884 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 885 | f.debug_tuple("VacantEntry").field(self.key()).finish() 886 | } 887 | } 888 | 889 | impl<'a, K, V, S> VacantEntry<'a, K, V, S> { 890 | #[cfg_attr(feature = "inline-more", inline)] 891 | pub fn key(&self) -> &K { 892 | &self.key 893 | } 894 | 895 | #[cfg_attr(feature = "inline-more", inline)] 896 | pub fn into_key(self) -> K { 897 | self.key 898 | } 899 | 900 | /// Insert's the key for this vacant entry paired with the given value as a new entry at the 901 | /// *back* of the internal linked list. 902 | #[cfg_attr(feature = "inline-more", inline)] 903 | pub fn insert(self, value: V) -> &'a mut V 904 | where 905 | K: Hash, 906 | S: BuildHasher, 907 | { 908 | self.raw_entry.insert(self.key, value).1 909 | } 910 | } 911 | 912 | pub struct RawEntryBuilder<'a, K, V, S> { 913 | hash_builder: &'a S, 914 | entry: hash_map::RawEntryBuilder<'a, NonNull>, (), NullHasher>, 915 | } 916 | 917 | impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> 918 | where 919 | S: BuildHasher, 920 | { 921 | #[cfg_attr(feature = "inline-more", inline)] 922 | #[allow(clippy::wrong_self_convention)] 923 | pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> 924 | where 925 | K: Borrow, 926 | Q: Hash + Eq + ?Sized, 927 | { 928 | let hash = hash_key(self.hash_builder, k); 929 | self.from_key_hashed_nocheck(hash, k) 930 | } 931 | 932 | #[inline] 933 | #[allow(clippy::wrong_self_convention)] 934 | pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> 935 | where 936 | K: Borrow, 937 | Q: Hash + Eq + ?Sized, 938 | { 939 | self.from_hash(hash, move |o| k.eq(o.borrow())) 940 | } 941 | 942 | #[cfg_attr(feature = "inline-more", inline)] 943 | #[allow(clippy::wrong_self_convention)] 944 | pub fn from_hash( 945 | self, 946 | hash: u64, 947 | mut is_match: impl FnMut(&K) -> bool, 948 | ) -> Option<(&'a K, &'a V)> { 949 | unsafe { 950 | let node = *self 951 | .entry 952 | .from_hash(hash, move |k| is_match((*k).as_ref().key_ref()))? 953 | .0; 954 | 955 | let (key, value) = (*node.as_ptr()).entry_ref(); 956 | Some((key, value)) 957 | } 958 | } 959 | } 960 | 961 | unsafe impl<'a, K, V, S> Send for RawEntryBuilder<'a, K, V, S> 962 | where 963 | K: Send, 964 | V: Send, 965 | S: Send, 966 | { 967 | } 968 | 969 | unsafe impl<'a, K, V, S> Sync for RawEntryBuilder<'a, K, V, S> 970 | where 971 | K: Sync, 972 | V: Sync, 973 | S: Sync, 974 | { 975 | } 976 | 977 | pub struct RawEntryBuilderMut<'a, K, V, S> { 978 | hash_builder: &'a S, 979 | values: &'a mut Option>>, 980 | free: &'a mut Option>>, 981 | entry: hash_map::RawEntryBuilderMut<'a, NonNull>, (), NullHasher>, 982 | } 983 | 984 | impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> 985 | where 986 | S: BuildHasher, 987 | { 988 | #[cfg_attr(feature = "inline-more", inline)] 989 | #[allow(clippy::wrong_self_convention)] 990 | pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> 991 | where 992 | K: Borrow, 993 | Q: Hash + Eq + ?Sized, 994 | { 995 | let hash = hash_key(self.hash_builder, k); 996 | self.from_key_hashed_nocheck(hash, k) 997 | } 998 | 999 | #[cfg_attr(feature = "inline-more", inline)] 1000 | #[allow(clippy::wrong_self_convention)] 1001 | pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> 1002 | where 1003 | K: Borrow, 1004 | Q: Hash + Eq + ?Sized, 1005 | { 1006 | self.from_hash(hash, move |o| k.eq(o.borrow())) 1007 | } 1008 | 1009 | #[cfg_attr(feature = "inline-more", inline)] 1010 | #[allow(clippy::wrong_self_convention)] 1011 | pub fn from_hash( 1012 | self, 1013 | hash: u64, 1014 | mut is_match: impl FnMut(&K) -> bool, 1015 | ) -> RawEntryMut<'a, K, V, S> { 1016 | let entry = self 1017 | .entry 1018 | .from_hash(hash, move |k| is_match(unsafe { (*k).as_ref().key_ref() })); 1019 | 1020 | match entry { 1021 | hash_map::RawEntryMut::Occupied(occupied) => { 1022 | RawEntryMut::Occupied(RawOccupiedEntryMut { 1023 | free: self.free, 1024 | values: self.values, 1025 | entry: occupied, 1026 | }) 1027 | } 1028 | hash_map::RawEntryMut::Vacant(vacant) => RawEntryMut::Vacant(RawVacantEntryMut { 1029 | hash_builder: self.hash_builder, 1030 | values: self.values, 1031 | free: self.free, 1032 | entry: vacant, 1033 | }), 1034 | } 1035 | } 1036 | } 1037 | 1038 | unsafe impl<'a, K, V, S> Send for RawEntryBuilderMut<'a, K, V, S> 1039 | where 1040 | K: Send, 1041 | V: Send, 1042 | S: Send, 1043 | { 1044 | } 1045 | 1046 | unsafe impl<'a, K, V, S> Sync for RawEntryBuilderMut<'a, K, V, S> 1047 | where 1048 | K: Sync, 1049 | V: Sync, 1050 | S: Sync, 1051 | { 1052 | } 1053 | 1054 | pub enum RawEntryMut<'a, K, V, S> { 1055 | Occupied(RawOccupiedEntryMut<'a, K, V>), 1056 | Vacant(RawVacantEntryMut<'a, K, V, S>), 1057 | } 1058 | 1059 | impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { 1060 | /// Similarly to `Entry::or_insert`, if this entry is occupied, it will move the existing entry 1061 | /// to the back of the internal linked list. 1062 | #[cfg_attr(feature = "inline-more", inline)] 1063 | pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) 1064 | where 1065 | K: Hash, 1066 | S: BuildHasher, 1067 | { 1068 | match self { 1069 | RawEntryMut::Occupied(mut entry) => { 1070 | entry.to_back(); 1071 | entry.into_key_value() 1072 | } 1073 | RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val), 1074 | } 1075 | } 1076 | 1077 | /// Similarly to `Entry::or_insert_with`, if this entry is occupied, it will move the existing 1078 | /// entry to the back of the internal linked list. 1079 | #[cfg_attr(feature = "inline-more", inline)] 1080 | pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) 1081 | where 1082 | F: FnOnce() -> (K, V), 1083 | K: Hash, 1084 | S: BuildHasher, 1085 | { 1086 | match self { 1087 | RawEntryMut::Occupied(mut entry) => { 1088 | entry.to_back(); 1089 | entry.into_key_value() 1090 | } 1091 | RawEntryMut::Vacant(entry) => { 1092 | let (k, v) = default(); 1093 | entry.insert(k, v) 1094 | } 1095 | } 1096 | } 1097 | 1098 | #[cfg_attr(feature = "inline-more", inline)] 1099 | pub fn and_modify(self, f: F) -> Self 1100 | where 1101 | F: FnOnce(&mut K, &mut V), 1102 | { 1103 | match self { 1104 | RawEntryMut::Occupied(mut entry) => { 1105 | { 1106 | let (k, v) = entry.get_key_value_mut(); 1107 | f(k, v); 1108 | } 1109 | RawEntryMut::Occupied(entry) 1110 | } 1111 | RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry), 1112 | } 1113 | } 1114 | } 1115 | 1116 | pub struct RawOccupiedEntryMut<'a, K, V> { 1117 | free: &'a mut Option>>, 1118 | values: &'a mut Option>>, 1119 | entry: hash_map::RawOccupiedEntryMut<'a, NonNull>, (), NullHasher>, 1120 | } 1121 | 1122 | impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> { 1123 | #[cfg_attr(feature = "inline-more", inline)] 1124 | pub fn key(&self) -> &K { 1125 | self.get_key_value().0 1126 | } 1127 | 1128 | #[cfg_attr(feature = "inline-more", inline)] 1129 | pub fn key_mut(&mut self) -> &mut K { 1130 | self.get_key_value_mut().0 1131 | } 1132 | 1133 | #[cfg_attr(feature = "inline-more", inline)] 1134 | pub fn into_key(self) -> &'a mut K { 1135 | self.into_key_value().0 1136 | } 1137 | 1138 | #[cfg_attr(feature = "inline-more", inline)] 1139 | pub fn get(&self) -> &V { 1140 | self.get_key_value().1 1141 | } 1142 | 1143 | #[cfg_attr(feature = "inline-more", inline)] 1144 | pub fn get_mut(&mut self) -> &mut V { 1145 | self.get_key_value_mut().1 1146 | } 1147 | 1148 | #[cfg_attr(feature = "inline-more", inline)] 1149 | pub fn into_mut(self) -> &'a mut V { 1150 | self.into_key_value().1 1151 | } 1152 | 1153 | #[cfg_attr(feature = "inline-more", inline)] 1154 | pub fn get_key_value(&self) -> (&K, &V) { 1155 | unsafe { 1156 | let node = *self.entry.key(); 1157 | let (key, value) = (*node.as_ptr()).entry_ref(); 1158 | (key, value) 1159 | } 1160 | } 1161 | 1162 | #[inline] 1163 | pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { 1164 | unsafe { 1165 | let node = *self.entry.key_mut(); 1166 | let (key, value) = (*node.as_ptr()).entry_mut(); 1167 | (key, value) 1168 | } 1169 | } 1170 | 1171 | #[cfg_attr(feature = "inline-more", inline)] 1172 | pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { 1173 | unsafe { 1174 | let node = *self.entry.into_key(); 1175 | let (key, value) = (*node.as_ptr()).entry_mut(); 1176 | (key, value) 1177 | } 1178 | } 1179 | 1180 | #[cfg_attr(feature = "inline-more", inline)] 1181 | #[allow(clippy::wrong_self_convention)] 1182 | pub fn to_back(&mut self) { 1183 | unsafe { 1184 | let node = *self.entry.key_mut(); 1185 | detach_node(node); 1186 | attach_before(node, NonNull::new_unchecked(self.values.as_ptr())); 1187 | } 1188 | } 1189 | 1190 | #[cfg_attr(feature = "inline-more", inline)] 1191 | #[allow(clippy::wrong_self_convention)] 1192 | pub fn to_front(&mut self) { 1193 | unsafe { 1194 | let node = *self.entry.key_mut(); 1195 | detach_node(node); 1196 | attach_before(node, (*self.values.as_ptr()).links.value.next); 1197 | } 1198 | } 1199 | 1200 | #[cfg_attr(feature = "inline-more", inline)] 1201 | pub fn replace_value(&mut self, value: V) -> V { 1202 | unsafe { 1203 | let mut node = *self.entry.key_mut(); 1204 | mem::replace(&mut node.as_mut().entry_mut().1, value) 1205 | } 1206 | } 1207 | 1208 | #[cfg_attr(feature = "inline-more", inline)] 1209 | pub fn replace_key(&mut self, key: K) -> K { 1210 | unsafe { 1211 | let mut node = *self.entry.key_mut(); 1212 | mem::replace(&mut node.as_mut().entry_mut().0, key) 1213 | } 1214 | } 1215 | 1216 | #[cfg_attr(feature = "inline-more", inline)] 1217 | pub fn remove(self) -> V { 1218 | self.remove_entry().1 1219 | } 1220 | 1221 | #[cfg_attr(feature = "inline-more", inline)] 1222 | pub fn remove_entry(self) -> (K, V) { 1223 | let node = self.entry.remove_entry().0; 1224 | unsafe { remove_node(self.free, node) } 1225 | } 1226 | } 1227 | 1228 | pub struct RawVacantEntryMut<'a, K, V, S> { 1229 | hash_builder: &'a S, 1230 | values: &'a mut Option>>, 1231 | free: &'a mut Option>>, 1232 | entry: hash_map::RawVacantEntryMut<'a, NonNull>, (), NullHasher>, 1233 | } 1234 | 1235 | impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { 1236 | #[cfg_attr(feature = "inline-more", inline)] 1237 | pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) 1238 | where 1239 | K: Hash, 1240 | S: BuildHasher, 1241 | { 1242 | let hash = hash_key(self.hash_builder, &key); 1243 | self.insert_hashed_nocheck(hash, key, value) 1244 | } 1245 | 1246 | #[cfg_attr(feature = "inline-more", inline)] 1247 | pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) 1248 | where 1249 | K: Hash, 1250 | S: BuildHasher, 1251 | { 1252 | let hash_builder = self.hash_builder; 1253 | self.insert_with_hasher(hash, key, value, |k| hash_key(hash_builder, k)) 1254 | } 1255 | 1256 | #[cfg_attr(feature = "inline-more", inline)] 1257 | pub fn insert_with_hasher( 1258 | self, 1259 | hash: u64, 1260 | key: K, 1261 | value: V, 1262 | hasher: impl Fn(&K) -> u64, 1263 | ) -> (&'a mut K, &'a mut V) 1264 | where 1265 | S: BuildHasher, 1266 | { 1267 | unsafe { 1268 | ensure_guard_node(self.values); 1269 | let mut new_node = allocate_node(self.free); 1270 | new_node.as_mut().put_entry((key, value)); 1271 | attach_before(new_node, NonNull::new_unchecked(self.values.as_ptr())); 1272 | 1273 | let node = *self 1274 | .entry 1275 | .insert_with_hasher(hash, new_node, (), move |k| hasher((*k).as_ref().key_ref())) 1276 | .0; 1277 | 1278 | let (key, value) = (*node.as_ptr()).entry_mut(); 1279 | (key, value) 1280 | } 1281 | } 1282 | } 1283 | 1284 | impl fmt::Debug for RawEntryBuilderMut<'_, K, V, S> { 1285 | #[cfg_attr(feature = "inline-more", inline)] 1286 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1287 | f.debug_struct("RawEntryBuilder").finish() 1288 | } 1289 | } 1290 | 1291 | impl fmt::Debug for RawEntryMut<'_, K, V, S> { 1292 | #[cfg_attr(feature = "inline-more", inline)] 1293 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1294 | match *self { 1295 | RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), 1296 | RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(), 1297 | } 1298 | } 1299 | } 1300 | 1301 | impl fmt::Debug for RawOccupiedEntryMut<'_, K, V> { 1302 | #[cfg_attr(feature = "inline-more", inline)] 1303 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1304 | f.debug_struct("RawOccupiedEntryMut") 1305 | .field("key", self.key()) 1306 | .field("value", self.get()) 1307 | .finish() 1308 | } 1309 | } 1310 | 1311 | impl fmt::Debug for RawVacantEntryMut<'_, K, V, S> { 1312 | #[cfg_attr(feature = "inline-more", inline)] 1313 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1314 | f.debug_struct("RawVacantEntryMut").finish() 1315 | } 1316 | } 1317 | 1318 | impl fmt::Debug for RawEntryBuilder<'_, K, V, S> { 1319 | #[cfg_attr(feature = "inline-more", inline)] 1320 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1321 | f.debug_struct("RawEntryBuilder").finish() 1322 | } 1323 | } 1324 | 1325 | unsafe impl<'a, K, V> Send for RawOccupiedEntryMut<'a, K, V> 1326 | where 1327 | K: Send, 1328 | V: Send, 1329 | { 1330 | } 1331 | 1332 | unsafe impl<'a, K, V> Sync for RawOccupiedEntryMut<'a, K, V> 1333 | where 1334 | K: Sync, 1335 | V: Sync, 1336 | { 1337 | } 1338 | 1339 | unsafe impl<'a, K, V, S> Send for RawVacantEntryMut<'a, K, V, S> 1340 | where 1341 | K: Send, 1342 | V: Send, 1343 | S: Send, 1344 | { 1345 | } 1346 | 1347 | unsafe impl<'a, K, V, S> Sync for RawVacantEntryMut<'a, K, V, S> 1348 | where 1349 | K: Sync, 1350 | V: Sync, 1351 | S: Sync, 1352 | { 1353 | } 1354 | 1355 | pub struct Iter<'a, K, V> { 1356 | head: *const Node, 1357 | tail: *const Node, 1358 | remaining: usize, 1359 | marker: PhantomData<(&'a K, &'a V)>, 1360 | } 1361 | 1362 | pub struct IterMut<'a, K, V> { 1363 | head: Option>>, 1364 | tail: Option>>, 1365 | remaining: usize, 1366 | marker: PhantomData<(&'a K, &'a mut V)>, 1367 | } 1368 | 1369 | pub struct IntoIter { 1370 | head: Option>>, 1371 | tail: Option>>, 1372 | remaining: usize, 1373 | marker: PhantomData<(K, V)>, 1374 | } 1375 | 1376 | pub struct Drain<'a, K, V> { 1377 | free: NonNull>>>, 1378 | head: Option>>, 1379 | tail: Option>>, 1380 | remaining: usize, 1381 | // We want `Drain` to be covariant 1382 | marker: PhantomData<(K, V, &'a LinkedHashMap)>, 1383 | } 1384 | 1385 | impl IterMut<'_, K, V> { 1386 | #[cfg_attr(feature = "inline-more", inline)] 1387 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1388 | Iter { 1389 | head: self.head.as_ptr(), 1390 | tail: self.tail.as_ptr(), 1391 | remaining: self.remaining, 1392 | marker: PhantomData, 1393 | } 1394 | } 1395 | } 1396 | 1397 | impl IntoIter { 1398 | #[cfg_attr(feature = "inline-more", inline)] 1399 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1400 | Iter { 1401 | head: self.head.as_ptr(), 1402 | tail: self.tail.as_ptr(), 1403 | remaining: self.remaining, 1404 | marker: PhantomData, 1405 | } 1406 | } 1407 | } 1408 | 1409 | impl Drain<'_, K, V> { 1410 | #[cfg_attr(feature = "inline-more", inline)] 1411 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1412 | Iter { 1413 | head: self.head.as_ptr(), 1414 | tail: self.tail.as_ptr(), 1415 | remaining: self.remaining, 1416 | marker: PhantomData, 1417 | } 1418 | } 1419 | } 1420 | 1421 | unsafe impl<'a, K, V> Send for Iter<'a, K, V> 1422 | where 1423 | K: Send, 1424 | V: Send, 1425 | { 1426 | } 1427 | 1428 | unsafe impl<'a, K, V> Send for IterMut<'a, K, V> 1429 | where 1430 | K: Send, 1431 | V: Send, 1432 | { 1433 | } 1434 | 1435 | unsafe impl Send for IntoIter 1436 | where 1437 | K: Send, 1438 | V: Send, 1439 | { 1440 | } 1441 | 1442 | unsafe impl<'a, K, V> Send for Drain<'a, K, V> 1443 | where 1444 | K: Send, 1445 | V: Send, 1446 | { 1447 | } 1448 | 1449 | unsafe impl<'a, K, V> Sync for Iter<'a, K, V> 1450 | where 1451 | K: Sync, 1452 | V: Sync, 1453 | { 1454 | } 1455 | 1456 | unsafe impl<'a, K, V> Sync for IterMut<'a, K, V> 1457 | where 1458 | K: Sync, 1459 | V: Sync, 1460 | { 1461 | } 1462 | 1463 | unsafe impl Sync for IntoIter 1464 | where 1465 | K: Sync, 1466 | V: Sync, 1467 | { 1468 | } 1469 | 1470 | unsafe impl<'a, K, V> Sync for Drain<'a, K, V> 1471 | where 1472 | K: Sync, 1473 | V: Sync, 1474 | { 1475 | } 1476 | 1477 | impl<'a, K, V> Clone for Iter<'a, K, V> { 1478 | #[cfg_attr(feature = "inline-more", inline)] 1479 | fn clone(&self) -> Self { 1480 | Iter { ..*self } 1481 | } 1482 | } 1483 | 1484 | impl fmt::Debug for Iter<'_, K, V> { 1485 | #[cfg_attr(feature = "inline-more", inline)] 1486 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1487 | f.debug_list().entries(self.clone()).finish() 1488 | } 1489 | } 1490 | 1491 | impl fmt::Debug for IterMut<'_, K, V> 1492 | where 1493 | K: fmt::Debug, 1494 | V: fmt::Debug, 1495 | { 1496 | #[cfg_attr(feature = "inline-more", inline)] 1497 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1498 | f.debug_list().entries(self.iter()).finish() 1499 | } 1500 | } 1501 | 1502 | impl fmt::Debug for IntoIter 1503 | where 1504 | K: fmt::Debug, 1505 | V: fmt::Debug, 1506 | { 1507 | #[cfg_attr(feature = "inline-more", inline)] 1508 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1509 | f.debug_list().entries(self.iter()).finish() 1510 | } 1511 | } 1512 | 1513 | impl fmt::Debug for Drain<'_, K, V> 1514 | where 1515 | K: fmt::Debug, 1516 | V: fmt::Debug, 1517 | { 1518 | #[cfg_attr(feature = "inline-more", inline)] 1519 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1520 | f.debug_list().entries(self.iter()).finish() 1521 | } 1522 | } 1523 | 1524 | impl<'a, K, V> Iterator for Iter<'a, K, V> { 1525 | type Item = (&'a K, &'a V); 1526 | 1527 | #[cfg_attr(feature = "inline-more", inline)] 1528 | fn next(&mut self) -> Option<(&'a K, &'a V)> { 1529 | if self.remaining == 0 { 1530 | None 1531 | } else { 1532 | self.remaining -= 1; 1533 | unsafe { 1534 | let (key, value) = (*self.head).entry_ref(); 1535 | self.head = (*self.head).links.value.next.as_ptr(); 1536 | Some((key, value)) 1537 | } 1538 | } 1539 | } 1540 | 1541 | #[cfg_attr(feature = "inline-more", inline)] 1542 | fn size_hint(&self) -> (usize, Option) { 1543 | (self.remaining, Some(self.remaining)) 1544 | } 1545 | } 1546 | 1547 | impl<'a, K, V> Iterator for IterMut<'a, K, V> { 1548 | type Item = (&'a K, &'a mut V); 1549 | 1550 | #[cfg_attr(feature = "inline-more", inline)] 1551 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> { 1552 | if self.remaining == 0 { 1553 | None 1554 | } else { 1555 | self.remaining -= 1; 1556 | unsafe { 1557 | let head = self.head.as_ptr(); 1558 | let (key, value) = (*head).entry_mut(); 1559 | self.head = Some((*head).links.value.next); 1560 | Some((key, value)) 1561 | } 1562 | } 1563 | } 1564 | 1565 | #[cfg_attr(feature = "inline-more", inline)] 1566 | fn size_hint(&self) -> (usize, Option) { 1567 | (self.remaining, Some(self.remaining)) 1568 | } 1569 | } 1570 | 1571 | impl Iterator for IntoIter { 1572 | type Item = (K, V); 1573 | 1574 | #[cfg_attr(feature = "inline-more", inline)] 1575 | fn next(&mut self) -> Option<(K, V)> { 1576 | if self.remaining == 0 { 1577 | return None; 1578 | } 1579 | self.remaining -= 1; 1580 | unsafe { 1581 | let head = self.head.as_ptr(); 1582 | self.head = Some((*head).links.value.next); 1583 | let mut e = Box::from_raw(head); 1584 | Some(e.take_entry()) 1585 | } 1586 | } 1587 | 1588 | #[cfg_attr(feature = "inline-more", inline)] 1589 | fn size_hint(&self) -> (usize, Option) { 1590 | (self.remaining, Some(self.remaining)) 1591 | } 1592 | } 1593 | 1594 | impl<'a, K, V> Iterator for Drain<'a, K, V> { 1595 | type Item = (K, V); 1596 | 1597 | #[cfg_attr(feature = "inline-more", inline)] 1598 | fn next(&mut self) -> Option<(K, V)> { 1599 | if self.remaining == 0 { 1600 | return None; 1601 | } 1602 | self.remaining -= 1; 1603 | unsafe { 1604 | let mut head = NonNull::new_unchecked(self.head.as_ptr()); 1605 | self.head = Some(head.as_ref().links.value.next); 1606 | let entry = head.as_mut().take_entry(); 1607 | push_free(self.free.as_mut(), head); 1608 | Some(entry) 1609 | } 1610 | } 1611 | 1612 | #[cfg_attr(feature = "inline-more", inline)] 1613 | fn size_hint(&self) -> (usize, Option) { 1614 | (self.remaining, Some(self.remaining)) 1615 | } 1616 | } 1617 | 1618 | impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { 1619 | #[cfg_attr(feature = "inline-more", inline)] 1620 | fn next_back(&mut self) -> Option<(&'a K, &'a V)> { 1621 | if self.remaining == 0 { 1622 | None 1623 | } else { 1624 | self.remaining -= 1; 1625 | unsafe { 1626 | let tail = self.tail; 1627 | self.tail = (*tail).links.value.prev.as_ptr(); 1628 | let (key, value) = (*tail).entry_ref(); 1629 | Some((key, value)) 1630 | } 1631 | } 1632 | } 1633 | } 1634 | 1635 | impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { 1636 | #[cfg_attr(feature = "inline-more", inline)] 1637 | fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { 1638 | if self.remaining == 0 { 1639 | None 1640 | } else { 1641 | self.remaining -= 1; 1642 | unsafe { 1643 | let tail = self.tail.as_ptr(); 1644 | self.tail = Some((*tail).links.value.prev); 1645 | let (key, value) = (*tail).entry_mut(); 1646 | Some((key, value)) 1647 | } 1648 | } 1649 | } 1650 | } 1651 | 1652 | impl DoubleEndedIterator for IntoIter { 1653 | #[cfg_attr(feature = "inline-more", inline)] 1654 | fn next_back(&mut self) -> Option<(K, V)> { 1655 | if self.remaining == 0 { 1656 | return None; 1657 | } 1658 | self.remaining -= 1; 1659 | unsafe { 1660 | let mut e = *Box::from_raw(self.tail.as_ptr()); 1661 | self.tail = Some(e.links.value.prev); 1662 | Some(e.take_entry()) 1663 | } 1664 | } 1665 | } 1666 | 1667 | impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> { 1668 | #[cfg_attr(feature = "inline-more", inline)] 1669 | fn next_back(&mut self) -> Option<(K, V)> { 1670 | if self.remaining == 0 { 1671 | return None; 1672 | } 1673 | self.remaining -= 1; 1674 | unsafe { 1675 | let mut tail = NonNull::new_unchecked(self.tail.as_ptr()); 1676 | self.tail = Some(tail.as_ref().links.value.prev); 1677 | let entry = tail.as_mut().take_entry(); 1678 | push_free(&mut *self.free.as_ptr(), tail); 1679 | Some(entry) 1680 | } 1681 | } 1682 | } 1683 | 1684 | impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {} 1685 | 1686 | impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {} 1687 | 1688 | impl ExactSizeIterator for IntoIter {} 1689 | 1690 | impl Drop for IntoIter { 1691 | #[cfg_attr(feature = "inline-more", inline)] 1692 | fn drop(&mut self) { 1693 | for _ in 0..self.remaining { 1694 | unsafe { 1695 | let tail = self.tail.as_ptr(); 1696 | self.tail = Some((*tail).links.value.prev); 1697 | (*tail).take_entry(); 1698 | Box::from_raw(tail); 1699 | } 1700 | } 1701 | } 1702 | } 1703 | 1704 | impl<'a, K, V> Drop for Drain<'a, K, V> { 1705 | #[cfg_attr(feature = "inline-more", inline)] 1706 | fn drop(&mut self) { 1707 | for _ in 0..self.remaining { 1708 | unsafe { 1709 | let mut tail = NonNull::new_unchecked(self.tail.as_ptr()); 1710 | self.tail = Some(tail.as_ref().links.value.prev); 1711 | tail.as_mut().take_entry(); 1712 | push_free(&mut *self.free.as_ptr(), tail); 1713 | } 1714 | } 1715 | } 1716 | } 1717 | 1718 | pub struct Keys<'a, K, V> { 1719 | inner: Iter<'a, K, V>, 1720 | } 1721 | 1722 | impl fmt::Debug for Keys<'_, K, V> { 1723 | #[cfg_attr(feature = "inline-more", inline)] 1724 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1725 | f.debug_list().entries(self.clone()).finish() 1726 | } 1727 | } 1728 | 1729 | impl<'a, K, V> Clone for Keys<'a, K, V> { 1730 | #[cfg_attr(feature = "inline-more", inline)] 1731 | fn clone(&self) -> Keys<'a, K, V> { 1732 | Keys { 1733 | inner: self.inner.clone(), 1734 | } 1735 | } 1736 | } 1737 | 1738 | impl<'a, K, V> Iterator for Keys<'a, K, V> { 1739 | type Item = &'a K; 1740 | 1741 | #[cfg_attr(feature = "inline-more", inline)] 1742 | fn next(&mut self) -> Option<&'a K> { 1743 | self.inner.next().map(|e| e.0) 1744 | } 1745 | 1746 | #[cfg_attr(feature = "inline-more", inline)] 1747 | fn size_hint(&self) -> (usize, Option) { 1748 | self.inner.size_hint() 1749 | } 1750 | } 1751 | 1752 | impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { 1753 | #[cfg_attr(feature = "inline-more", inline)] 1754 | fn next_back(&mut self) -> Option<&'a K> { 1755 | self.inner.next_back().map(|e| e.0) 1756 | } 1757 | } 1758 | 1759 | impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { 1760 | #[cfg_attr(feature = "inline-more", inline)] 1761 | fn len(&self) -> usize { 1762 | self.inner.len() 1763 | } 1764 | } 1765 | 1766 | pub struct Values<'a, K, V> { 1767 | inner: Iter<'a, K, V>, 1768 | } 1769 | 1770 | impl Clone for Values<'_, K, V> { 1771 | #[cfg_attr(feature = "inline-more", inline)] 1772 | fn clone(&self) -> Self { 1773 | Values { 1774 | inner: self.inner.clone(), 1775 | } 1776 | } 1777 | } 1778 | 1779 | impl fmt::Debug for Values<'_, K, V> { 1780 | #[cfg_attr(feature = "inline-more", inline)] 1781 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1782 | f.debug_list().entries(self.clone()).finish() 1783 | } 1784 | } 1785 | 1786 | impl<'a, K, V> Iterator for Values<'a, K, V> { 1787 | type Item = &'a V; 1788 | 1789 | #[cfg_attr(feature = "inline-more", inline)] 1790 | fn next(&mut self) -> Option<&'a V> { 1791 | self.inner.next().map(|e| e.1) 1792 | } 1793 | 1794 | #[cfg_attr(feature = "inline-more", inline)] 1795 | fn size_hint(&self) -> (usize, Option) { 1796 | self.inner.size_hint() 1797 | } 1798 | } 1799 | 1800 | impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { 1801 | #[cfg_attr(feature = "inline-more", inline)] 1802 | fn next_back(&mut self) -> Option<&'a V> { 1803 | self.inner.next_back().map(|e| e.1) 1804 | } 1805 | } 1806 | 1807 | impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { 1808 | #[cfg_attr(feature = "inline-more", inline)] 1809 | fn len(&self) -> usize { 1810 | self.inner.len() 1811 | } 1812 | } 1813 | 1814 | pub struct ValuesMut<'a, K, V> { 1815 | inner: IterMut<'a, K, V>, 1816 | } 1817 | 1818 | impl fmt::Debug for ValuesMut<'_, K, V> 1819 | where 1820 | K: fmt::Debug, 1821 | V: fmt::Debug, 1822 | { 1823 | #[cfg_attr(feature = "inline-more", inline)] 1824 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1825 | f.debug_list().entries(self.inner.iter()).finish() 1826 | } 1827 | } 1828 | 1829 | impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { 1830 | type Item = &'a mut V; 1831 | 1832 | #[cfg_attr(feature = "inline-more", inline)] 1833 | fn next(&mut self) -> Option<&'a mut V> { 1834 | self.inner.next().map(|e| e.1) 1835 | } 1836 | 1837 | #[cfg_attr(feature = "inline-more", inline)] 1838 | fn size_hint(&self) -> (usize, Option) { 1839 | self.inner.size_hint() 1840 | } 1841 | } 1842 | 1843 | impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { 1844 | #[cfg_attr(feature = "inline-more", inline)] 1845 | fn next_back(&mut self) -> Option<&'a mut V> { 1846 | self.inner.next_back().map(|e| e.1) 1847 | } 1848 | } 1849 | 1850 | impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { 1851 | #[cfg_attr(feature = "inline-more", inline)] 1852 | fn len(&self) -> usize { 1853 | self.inner.len() 1854 | } 1855 | } 1856 | 1857 | impl<'a, K, V, S> IntoIterator for &'a LinkedHashMap { 1858 | type Item = (&'a K, &'a V); 1859 | type IntoIter = Iter<'a, K, V>; 1860 | 1861 | #[cfg_attr(feature = "inline-more", inline)] 1862 | fn into_iter(self) -> Iter<'a, K, V> { 1863 | self.iter() 1864 | } 1865 | } 1866 | 1867 | impl<'a, K, V, S> IntoIterator for &'a mut LinkedHashMap { 1868 | type Item = (&'a K, &'a mut V); 1869 | type IntoIter = IterMut<'a, K, V>; 1870 | 1871 | #[cfg_attr(feature = "inline-more", inline)] 1872 | fn into_iter(self) -> IterMut<'a, K, V> { 1873 | self.iter_mut() 1874 | } 1875 | } 1876 | 1877 | impl IntoIterator for LinkedHashMap { 1878 | type Item = (K, V); 1879 | type IntoIter = IntoIter; 1880 | 1881 | #[cfg_attr(feature = "inline-more", inline)] 1882 | fn into_iter(mut self) -> IntoIter { 1883 | unsafe { 1884 | let (head, tail) = if let Some(values) = self.values { 1885 | let ValueLinks { 1886 | next: head, 1887 | prev: tail, 1888 | } = values.as_ref().links.value; 1889 | 1890 | Box::from_raw(self.values.as_ptr()); 1891 | self.values = None; 1892 | 1893 | (Some(head), Some(tail)) 1894 | } else { 1895 | (None, None) 1896 | }; 1897 | let len = self.len(); 1898 | 1899 | drop_free_nodes(self.free); 1900 | self.free = None; 1901 | 1902 | self.map.clear(); 1903 | 1904 | IntoIter { 1905 | head, 1906 | tail, 1907 | remaining: len, 1908 | marker: PhantomData, 1909 | } 1910 | } 1911 | } 1912 | } 1913 | 1914 | // A ZST that asserts that the inner HashMap will not do its own key hashing 1915 | struct NullHasher; 1916 | 1917 | impl BuildHasher for NullHasher { 1918 | type Hasher = Self; 1919 | 1920 | #[cfg_attr(feature = "inline-more", inline)] 1921 | fn build_hasher(&self) -> Self { 1922 | Self 1923 | } 1924 | } 1925 | 1926 | impl Hasher for NullHasher { 1927 | #[cfg_attr(feature = "inline-more", inline)] 1928 | fn write(&mut self, _bytes: &[u8]) { 1929 | unreachable!("inner map should not be using its built-in hasher") 1930 | } 1931 | 1932 | #[cfg_attr(feature = "inline-more", inline)] 1933 | fn finish(&self) -> u64 { 1934 | unreachable!("inner map should not be using its built-in hasher") 1935 | } 1936 | } 1937 | 1938 | struct ValueLinks { 1939 | next: NonNull>, 1940 | prev: NonNull>, 1941 | } 1942 | 1943 | impl Clone for ValueLinks { 1944 | #[cfg_attr(feature = "inline-more", inline)] 1945 | fn clone(&self) -> Self { 1946 | ValueLinks { 1947 | next: self.next, 1948 | prev: self.prev, 1949 | } 1950 | } 1951 | } 1952 | 1953 | impl Copy for ValueLinks {} 1954 | 1955 | struct FreeLink { 1956 | next: Option>>, 1957 | } 1958 | 1959 | impl Clone for FreeLink { 1960 | #[cfg_attr(feature = "inline-more", inline)] 1961 | fn clone(&self) -> Self { 1962 | FreeLink { next: self.next } 1963 | } 1964 | } 1965 | 1966 | impl Copy for FreeLink {} 1967 | 1968 | union Links { 1969 | value: ValueLinks, 1970 | free: FreeLink, 1971 | } 1972 | 1973 | struct Node { 1974 | entry: MaybeUninit<(K, V)>, 1975 | links: Links, 1976 | } 1977 | 1978 | impl Node { 1979 | #[cfg_attr(feature = "inline-more", inline)] 1980 | unsafe fn put_entry(&mut self, entry: (K, V)) { 1981 | self.entry.as_mut_ptr().write(entry) 1982 | } 1983 | 1984 | #[cfg_attr(feature = "inline-more", inline)] 1985 | unsafe fn entry_ref(&self) -> &(K, V) { 1986 | &*self.entry.as_ptr() 1987 | } 1988 | 1989 | #[cfg_attr(feature = "inline-more", inline)] 1990 | unsafe fn key_ref(&self) -> &K { 1991 | &(*self.entry.as_ptr()).0 1992 | } 1993 | 1994 | #[cfg_attr(feature = "inline-more", inline)] 1995 | unsafe fn entry_mut(&mut self) -> &mut (K, V) { 1996 | &mut *self.entry.as_mut_ptr() 1997 | } 1998 | 1999 | #[cfg_attr(feature = "inline-more", inline)] 2000 | unsafe fn take_entry(&mut self) -> (K, V) { 2001 | self.entry.as_ptr().read() 2002 | } 2003 | } 2004 | 2005 | trait OptNonNullExt { 2006 | #[allow(clippy::wrong_self_convention)] 2007 | fn as_ptr(self) -> *mut T; 2008 | } 2009 | 2010 | impl OptNonNullExt for Option> { 2011 | #[cfg_attr(feature = "inline-more", inline)] 2012 | fn as_ptr(self) -> *mut T { 2013 | match self { 2014 | Some(ptr) => ptr.as_ptr(), 2015 | None => ptr::null_mut(), 2016 | } 2017 | } 2018 | } 2019 | 2020 | // Allocate a circular list guard node if not present. 2021 | #[cfg_attr(feature = "inline-more", inline)] 2022 | unsafe fn ensure_guard_node(head: &mut Option>>) { 2023 | if head.is_none() { 2024 | let mut p = NonNull::new_unchecked(Box::into_raw(Box::new(Node { 2025 | entry: MaybeUninit::uninit(), 2026 | links: Links { 2027 | value: ValueLinks { 2028 | next: NonNull::dangling(), 2029 | prev: NonNull::dangling(), 2030 | }, 2031 | }, 2032 | }))); 2033 | p.as_mut().links.value = ValueLinks { next: p, prev: p }; 2034 | *head = Some(p); 2035 | } 2036 | } 2037 | 2038 | // Attach the `to_attach` node to the existing circular list *before* `node`. 2039 | #[cfg_attr(feature = "inline-more", inline)] 2040 | unsafe fn attach_before(mut to_attach: NonNull>, mut node: NonNull>) { 2041 | to_attach.as_mut().links.value = ValueLinks { 2042 | prev: node.as_ref().links.value.prev, 2043 | next: node, 2044 | }; 2045 | node.as_mut().links.value.prev = to_attach; 2046 | (*to_attach.as_mut().links.value.prev.as_ptr()) 2047 | .links 2048 | .value 2049 | .next = to_attach; 2050 | } 2051 | 2052 | #[cfg_attr(feature = "inline-more", inline)] 2053 | unsafe fn detach_node(mut node: NonNull>) { 2054 | node.as_mut().links.value.prev.as_mut().links.value.next = node.as_ref().links.value.next; 2055 | node.as_mut().links.value.next.as_mut().links.value.prev = node.as_ref().links.value.prev; 2056 | } 2057 | 2058 | #[cfg_attr(feature = "inline-more", inline)] 2059 | unsafe fn push_free( 2060 | free_list: &mut Option>>, 2061 | mut node: NonNull>, 2062 | ) { 2063 | node.as_mut().links.free.next = *free_list; 2064 | *free_list = Some(node); 2065 | } 2066 | 2067 | #[cfg_attr(feature = "inline-more", inline)] 2068 | unsafe fn pop_free( 2069 | free_list: &mut Option>>, 2070 | ) -> Option>> { 2071 | if let Some(free) = *free_list { 2072 | *free_list = free.as_ref().links.free.next; 2073 | Some(free) 2074 | } else { 2075 | None 2076 | } 2077 | } 2078 | 2079 | #[cfg_attr(feature = "inline-more", inline)] 2080 | unsafe fn allocate_node(free_list: &mut Option>>) -> NonNull> { 2081 | if let Some(mut free) = pop_free(free_list) { 2082 | free.as_mut().links.value = ValueLinks { 2083 | next: NonNull::dangling(), 2084 | prev: NonNull::dangling(), 2085 | }; 2086 | free 2087 | } else { 2088 | NonNull::new_unchecked(Box::into_raw(Box::new(Node { 2089 | entry: MaybeUninit::uninit(), 2090 | links: Links { 2091 | value: ValueLinks { 2092 | next: NonNull::dangling(), 2093 | prev: NonNull::dangling(), 2094 | }, 2095 | }, 2096 | }))) 2097 | } 2098 | } 2099 | 2100 | // Given node is assumed to be the guard node and is *not* dropped. 2101 | #[cfg_attr(feature = "inline-more", inline)] 2102 | unsafe fn drop_value_nodes(guard: NonNull>) { 2103 | let mut cur = guard.as_ref().links.value.prev; 2104 | while cur != guard { 2105 | let prev = cur.as_ref().links.value.prev; 2106 | cur.as_mut().take_entry(); 2107 | Box::from_raw(cur.as_ptr()); 2108 | cur = prev; 2109 | } 2110 | } 2111 | 2112 | // Drops all linked free nodes starting with the given node. Free nodes are only non-circular 2113 | // singly linked, and should have uninitialized keys / values. 2114 | #[cfg_attr(feature = "inline-more", inline)] 2115 | unsafe fn drop_free_nodes(mut free: Option>>) { 2116 | while let Some(some_free) = free { 2117 | let next_free = some_free.as_ref().links.free.next; 2118 | Box::from_raw(some_free.as_ptr()); 2119 | free = next_free; 2120 | } 2121 | } 2122 | 2123 | #[cfg_attr(feature = "inline-more", inline)] 2124 | unsafe fn remove_node( 2125 | free_list: &mut Option>>, 2126 | mut node: NonNull>, 2127 | ) -> (K, V) { 2128 | detach_node(node); 2129 | push_free(free_list, node); 2130 | node.as_mut().take_entry() 2131 | } 2132 | 2133 | #[cfg_attr(feature = "inline-more", inline)] 2134 | fn hash_key(s: &S, k: &Q) -> u64 2135 | where 2136 | S: BuildHasher, 2137 | Q: Hash + ?Sized, 2138 | { 2139 | let mut hasher = s.build_hasher(); 2140 | k.hash(&mut hasher); 2141 | hasher.finish() 2142 | } 2143 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | mod size_hint { 2 | use core::cmp; 3 | 4 | /// This presumably exists to prevent denial of service attacks. 5 | /// 6 | /// Original discussion: https://github.com/serde-rs/serde/issues/1114. 7 | #[cfg_attr(feature = "inline-more", inline)] 8 | pub(super) fn cautious(hint: Option) -> usize { 9 | cmp::min(hint.unwrap_or(0), 4096) 10 | } 11 | } 12 | 13 | // LinkedHashMap impls 14 | mod map { 15 | use core::{ 16 | fmt::{self, Formatter}, 17 | hash::{BuildHasher, Hash}, 18 | marker::PhantomData, 19 | }; 20 | 21 | use serde_::{ 22 | de::{MapAccess, Visitor}, 23 | Deserialize, Deserializer, Serialize, Serializer, 24 | }; 25 | 26 | use crate::linked_hash_map::LinkedHashMap; 27 | 28 | use super::size_hint; 29 | 30 | impl Serialize for LinkedHashMap 31 | where 32 | K: Serialize + Eq + Hash, 33 | V: Serialize, 34 | H: BuildHasher, 35 | { 36 | #[cfg_attr(feature = "inline-more", inline)] 37 | fn serialize(&self, serializer: S) -> Result 38 | where 39 | S: Serializer, 40 | { 41 | serializer.collect_map(self) 42 | } 43 | } 44 | 45 | #[derive(Debug)] 46 | pub struct LinkedHashMapVisitor { 47 | marker: PhantomData>, 48 | } 49 | 50 | impl LinkedHashMapVisitor { 51 | fn new() -> Self { 52 | LinkedHashMapVisitor { 53 | marker: PhantomData, 54 | } 55 | } 56 | } 57 | 58 | impl Default for LinkedHashMapVisitor { 59 | fn default() -> Self { 60 | Self::new() 61 | } 62 | } 63 | 64 | impl<'de, K, V, S> Visitor<'de> for LinkedHashMapVisitor 65 | where 66 | K: Deserialize<'de> + Eq + Hash, 67 | V: Deserialize<'de>, 68 | S: BuildHasher + Default, 69 | { 70 | type Value = LinkedHashMap; 71 | 72 | fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { 73 | write!(formatter, "a map") 74 | } 75 | 76 | #[cfg_attr(feature = "inline-more", inline)] 77 | fn visit_map>(self, mut map: M) -> Result { 78 | let mut values = LinkedHashMap::with_capacity_and_hasher( 79 | size_hint::cautious(map.size_hint()), 80 | S::default(), 81 | ); 82 | 83 | while let Some((k, v)) = map.next_entry()? { 84 | values.insert(k, v); 85 | } 86 | 87 | Ok(values) 88 | } 89 | } 90 | 91 | impl<'de, K, V, S> Deserialize<'de> for LinkedHashMap 92 | where 93 | K: Deserialize<'de> + Eq + Hash, 94 | V: Deserialize<'de>, 95 | S: BuildHasher + Default, 96 | { 97 | fn deserialize>(deserializer: D) -> Result { 98 | deserializer.deserialize_map(LinkedHashMapVisitor::default()) 99 | } 100 | } 101 | } 102 | 103 | // LinkedHashSet impls 104 | mod set { 105 | use core::{ 106 | fmt::{self, Formatter}, 107 | hash::{BuildHasher, Hash}, 108 | marker::PhantomData, 109 | }; 110 | 111 | use serde_::{ 112 | de::{SeqAccess, Visitor}, 113 | Deserialize, Deserializer, Serialize, Serializer, 114 | }; 115 | 116 | use crate::linked_hash_set::LinkedHashSet; 117 | 118 | use super::size_hint; 119 | 120 | impl Serialize for LinkedHashSet 121 | where 122 | T: Serialize + Eq + Hash, 123 | H: BuildHasher, 124 | { 125 | #[cfg_attr(feature = "inline-more", inline)] 126 | fn serialize(&self, serializer: S) -> Result 127 | where 128 | S: Serializer, 129 | { 130 | serializer.collect_seq(self) 131 | } 132 | } 133 | 134 | #[derive(Debug)] 135 | pub struct LinkedHashSetVisitor { 136 | marker: PhantomData>, 137 | } 138 | 139 | impl LinkedHashSetVisitor { 140 | fn new() -> Self { 141 | LinkedHashSetVisitor { 142 | marker: PhantomData, 143 | } 144 | } 145 | } 146 | 147 | impl Default for LinkedHashSetVisitor { 148 | fn default() -> Self { 149 | Self::new() 150 | } 151 | } 152 | 153 | impl<'de, T, H> Visitor<'de> for LinkedHashSetVisitor 154 | where 155 | T: Deserialize<'de> + Eq + Hash, 156 | H: BuildHasher + Default, 157 | { 158 | type Value = LinkedHashSet; 159 | 160 | fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { 161 | write!(formatter, "a sequence") 162 | } 163 | 164 | #[cfg_attr(feature = "inline-more", inline)] 165 | fn visit_seq>(self, mut seq: S) -> Result { 166 | let mut values = LinkedHashSet::with_capacity_and_hasher( 167 | size_hint::cautious(seq.size_hint()), 168 | H::default(), 169 | ); 170 | 171 | while let Some(v) = seq.next_element()? { 172 | values.insert(v); 173 | } 174 | 175 | Ok(values) 176 | } 177 | } 178 | 179 | impl<'de, T, S> Deserialize<'de> for LinkedHashSet 180 | where 181 | T: Deserialize<'de> + Eq + Hash, 182 | S: BuildHasher + Default, 183 | { 184 | fn deserialize>(deserializer: D) -> Result { 185 | deserializer.deserialize_seq(LinkedHashSetVisitor::default()) 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/set.rs: -------------------------------------------------------------------------------- 1 | use crate::DefaultHashBuilder; 2 | use crate::TryReserveError; 3 | 4 | use core::{ 5 | borrow::Borrow, 6 | fmt, 7 | hash::{BuildHasher, Hash, Hasher}, 8 | iter::{Chain, FromIterator}, 9 | ops::{BitAnd, BitOr, BitXor, Sub}, 10 | }; 11 | 12 | use crate::linked_hash_map::{self, LinkedHashMap}; 13 | 14 | pub struct LinkedHashSet { 15 | map: LinkedHashMap, 16 | } 17 | 18 | #[cfg(feature = "ahash")] 19 | impl LinkedHashSet { 20 | #[cfg_attr(feature = "inline-more", inline)] 21 | pub fn new() -> LinkedHashSet { 22 | LinkedHashSet { 23 | map: LinkedHashMap::new(), 24 | } 25 | } 26 | 27 | #[cfg_attr(feature = "inline-more", inline)] 28 | pub fn with_capacity(capacity: usize) -> LinkedHashSet { 29 | LinkedHashSet { 30 | map: LinkedHashMap::with_capacity(capacity), 31 | } 32 | } 33 | } 34 | 35 | impl LinkedHashSet { 36 | #[cfg_attr(feature = "inline-more", inline)] 37 | pub fn capacity(&self) -> usize { 38 | self.map.capacity() 39 | } 40 | 41 | #[cfg_attr(feature = "inline-more", inline)] 42 | pub fn iter(&self) -> Iter<'_, T> { 43 | Iter { 44 | iter: self.map.keys(), 45 | } 46 | } 47 | 48 | #[cfg_attr(feature = "inline-more", inline)] 49 | pub fn len(&self) -> usize { 50 | self.map.len() 51 | } 52 | 53 | #[cfg_attr(feature = "inline-more", inline)] 54 | pub fn is_empty(&self) -> bool { 55 | self.map.is_empty() 56 | } 57 | 58 | #[cfg_attr(feature = "inline-more", inline)] 59 | pub fn drain(&mut self) -> Drain { 60 | Drain { 61 | iter: self.map.drain(), 62 | } 63 | } 64 | 65 | #[cfg_attr(feature = "inline-more", inline)] 66 | pub fn clear(&mut self) { 67 | self.map.clear() 68 | } 69 | } 70 | 71 | impl LinkedHashSet 72 | where 73 | T: Eq + Hash, 74 | S: BuildHasher, 75 | { 76 | #[cfg_attr(feature = "inline-more", inline)] 77 | pub fn with_hasher(hasher: S) -> LinkedHashSet { 78 | LinkedHashSet { 79 | map: LinkedHashMap::with_hasher(hasher), 80 | } 81 | } 82 | 83 | #[cfg_attr(feature = "inline-more", inline)] 84 | pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> LinkedHashSet { 85 | LinkedHashSet { 86 | map: LinkedHashMap::with_capacity_and_hasher(capacity, hasher), 87 | } 88 | } 89 | 90 | #[cfg_attr(feature = "inline-more", inline)] 91 | pub fn hasher(&self) -> &S { 92 | self.map.hasher() 93 | } 94 | 95 | #[cfg_attr(feature = "inline-more", inline)] 96 | pub fn reserve(&mut self, additional: usize) { 97 | self.map.reserve(additional) 98 | } 99 | 100 | #[cfg_attr(feature = "inline-more", inline)] 101 | pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { 102 | self.map.try_reserve(additional) 103 | } 104 | 105 | #[cfg_attr(feature = "inline-more", inline)] 106 | pub fn shrink_to_fit(&mut self) { 107 | self.map.shrink_to_fit() 108 | } 109 | 110 | #[cfg_attr(feature = "inline-more", inline)] 111 | pub fn difference<'a>(&'a self, other: &'a LinkedHashSet) -> Difference<'a, T, S> { 112 | Difference { 113 | iter: self.iter(), 114 | other, 115 | } 116 | } 117 | 118 | #[cfg_attr(feature = "inline-more", inline)] 119 | pub fn symmetric_difference<'a>( 120 | &'a self, 121 | other: &'a LinkedHashSet, 122 | ) -> SymmetricDifference<'a, T, S> { 123 | SymmetricDifference { 124 | iter: self.difference(other).chain(other.difference(self)), 125 | } 126 | } 127 | 128 | #[cfg_attr(feature = "inline-more", inline)] 129 | pub fn intersection<'a>(&'a self, other: &'a LinkedHashSet) -> Intersection<'a, T, S> { 130 | Intersection { 131 | iter: self.iter(), 132 | other, 133 | } 134 | } 135 | 136 | #[cfg_attr(feature = "inline-more", inline)] 137 | pub fn union<'a>(&'a self, other: &'a LinkedHashSet) -> Union<'a, T, S> { 138 | Union { 139 | iter: self.iter().chain(other.difference(self)), 140 | } 141 | } 142 | 143 | #[cfg_attr(feature = "inline-more", inline)] 144 | pub fn contains(&self, value: &Q) -> bool 145 | where 146 | T: Borrow, 147 | Q: Hash + Eq, 148 | { 149 | self.map.contains_key(value) 150 | } 151 | 152 | #[cfg_attr(feature = "inline-more", inline)] 153 | pub fn get(&self, value: &Q) -> Option<&T> 154 | where 155 | T: Borrow, 156 | Q: Hash + Eq, 157 | { 158 | self.map.raw_entry().from_key(value).map(|p| p.0) 159 | } 160 | 161 | #[cfg_attr(feature = "inline-more", inline)] 162 | pub fn get_or_insert(&mut self, value: T) -> &T { 163 | self.map 164 | .raw_entry_mut() 165 | .from_key(&value) 166 | .or_insert(value, ()) 167 | .0 168 | } 169 | 170 | #[cfg_attr(feature = "inline-more", inline)] 171 | pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T 172 | where 173 | T: Borrow, 174 | Q: Hash + Eq, 175 | F: FnOnce(&Q) -> T, 176 | { 177 | self.map 178 | .raw_entry_mut() 179 | .from_key(value) 180 | .or_insert_with(|| (f(value), ())) 181 | .0 182 | } 183 | 184 | #[cfg_attr(feature = "inline-more", inline)] 185 | pub fn is_disjoint(&self, other: &LinkedHashSet) -> bool { 186 | self.iter().all(|v| !other.contains(v)) 187 | } 188 | 189 | #[cfg_attr(feature = "inline-more", inline)] 190 | pub fn is_subset(&self, other: &LinkedHashSet) -> bool { 191 | self.iter().all(|v| other.contains(v)) 192 | } 193 | 194 | #[cfg_attr(feature = "inline-more", inline)] 195 | pub fn is_superset(&self, other: &LinkedHashSet) -> bool { 196 | other.is_subset(self) 197 | } 198 | 199 | /// Inserts the given value into the set. 200 | /// 201 | /// If the set did not have this value present, inserts it at the *back* of the internal linked 202 | /// list and returns true, otherwise it moves the existing value to the *back* of the internal 203 | /// linked list and returns false. 204 | #[cfg_attr(feature = "inline-more", inline)] 205 | pub fn insert(&mut self, value: T) -> bool { 206 | self.map.insert(value, ()).is_none() 207 | } 208 | 209 | /// Adds the given value to the set, replacing the existing value. 210 | /// 211 | /// If a previous value existed, returns the replaced value. In this case, the value's position 212 | /// in the internal linked list is *not* changed. 213 | #[cfg_attr(feature = "inline-more", inline)] 214 | pub fn replace(&mut self, value: T) -> Option { 215 | match self.map.entry(value) { 216 | linked_hash_map::Entry::Occupied(occupied) => Some(occupied.replace_key()), 217 | linked_hash_map::Entry::Vacant(vacant) => { 218 | vacant.insert(()); 219 | None 220 | } 221 | } 222 | } 223 | 224 | #[cfg_attr(feature = "inline-more", inline)] 225 | pub fn remove(&mut self, value: &Q) -> bool 226 | where 227 | T: Borrow, 228 | Q: Hash + Eq, 229 | { 230 | self.map.remove(value).is_some() 231 | } 232 | 233 | #[cfg_attr(feature = "inline-more", inline)] 234 | pub fn retain(&mut self, mut f: F) 235 | where 236 | F: FnMut(&T) -> bool, 237 | { 238 | self.map.retain(|k, _| f(k)); 239 | } 240 | 241 | #[cfg_attr(feature = "inline-more", inline)] 242 | pub fn take(&mut self, value: &Q) -> Option 243 | where 244 | T: Borrow, 245 | Q: Hash + Eq, 246 | { 247 | match self.map.raw_entry_mut().from_key(value) { 248 | linked_hash_map::RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry().0), 249 | linked_hash_map::RawEntryMut::Vacant(_) => None, 250 | } 251 | } 252 | 253 | #[cfg_attr(feature = "inline-more", inline)] 254 | pub fn front(&self) -> Option<&T> { 255 | self.map.front().map(|(k, _)| k) 256 | } 257 | 258 | #[cfg_attr(feature = "inline-more", inline)] 259 | pub fn pop_front(&mut self) -> Option { 260 | self.map.pop_front().map(|(k, _)| k) 261 | } 262 | 263 | #[cfg_attr(feature = "inline-more", inline)] 264 | pub fn back(&self) -> Option<&T> { 265 | self.map.back().map(|(k, _)| k) 266 | } 267 | 268 | #[cfg_attr(feature = "inline-more", inline)] 269 | pub fn pop_back(&mut self) -> Option { 270 | self.map.pop_back().map(|(k, _)| k) 271 | } 272 | 273 | #[cfg_attr(feature = "inline-more", inline)] 274 | #[allow(clippy::wrong_self_convention)] 275 | pub fn to_front(&mut self, value: &Q) -> bool 276 | where 277 | T: Borrow, 278 | Q: Hash + Eq, 279 | { 280 | match self.map.raw_entry_mut().from_key(value) { 281 | linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 282 | occupied.to_front(); 283 | true 284 | } 285 | linked_hash_map::RawEntryMut::Vacant(_) => false, 286 | } 287 | } 288 | 289 | #[cfg_attr(feature = "inline-more", inline)] 290 | #[allow(clippy::wrong_self_convention)] 291 | pub fn to_back(&mut self, value: &Q) -> bool 292 | where 293 | T: Borrow, 294 | Q: Hash + Eq, 295 | { 296 | match self.map.raw_entry_mut().from_key(value) { 297 | linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 298 | occupied.to_back(); 299 | true 300 | } 301 | linked_hash_map::RawEntryMut::Vacant(_) => false, 302 | } 303 | } 304 | } 305 | 306 | impl Clone for LinkedHashSet { 307 | #[cfg_attr(feature = "inline-more", inline)] 308 | fn clone(&self) -> Self { 309 | let map = self.map.clone(); 310 | Self { map } 311 | } 312 | } 313 | 314 | impl PartialEq for LinkedHashSet 315 | where 316 | T: Eq + Hash, 317 | S: BuildHasher, 318 | { 319 | #[cfg_attr(feature = "inline-more", inline)] 320 | fn eq(&self, other: &Self) -> bool { 321 | self.len() == other.len() && self.iter().eq(other) 322 | } 323 | } 324 | 325 | impl Hash for LinkedHashSet 326 | where 327 | T: Eq + Hash, 328 | S: BuildHasher, 329 | { 330 | #[cfg_attr(feature = "inline-more", inline)] 331 | fn hash(&self, state: &mut H) { 332 | for e in self { 333 | e.hash(state); 334 | } 335 | } 336 | } 337 | 338 | impl Eq for LinkedHashSet 339 | where 340 | T: Eq + Hash, 341 | S: BuildHasher, 342 | { 343 | } 344 | 345 | impl fmt::Debug for LinkedHashSet 346 | where 347 | T: fmt::Debug, 348 | { 349 | #[cfg_attr(feature = "inline-more", inline)] 350 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 351 | f.debug_set().entries(self.iter()).finish() 352 | } 353 | } 354 | 355 | impl FromIterator for LinkedHashSet 356 | where 357 | T: Eq + Hash, 358 | S: BuildHasher + Default, 359 | { 360 | #[cfg_attr(feature = "inline-more", inline)] 361 | fn from_iter>(iter: I) -> LinkedHashSet { 362 | let mut set = LinkedHashSet::with_hasher(Default::default()); 363 | set.extend(iter); 364 | set 365 | } 366 | } 367 | 368 | impl Extend for LinkedHashSet 369 | where 370 | T: Eq + Hash, 371 | S: BuildHasher, 372 | { 373 | #[cfg_attr(feature = "inline-more", inline)] 374 | fn extend>(&mut self, iter: I) { 375 | self.map.extend(iter.into_iter().map(|k| (k, ()))); 376 | } 377 | } 378 | 379 | impl<'a, T, S> Extend<&'a T> for LinkedHashSet 380 | where 381 | T: 'a + Eq + Hash + Copy, 382 | S: BuildHasher, 383 | { 384 | #[cfg_attr(feature = "inline-more", inline)] 385 | fn extend>(&mut self, iter: I) { 386 | self.extend(iter.into_iter().cloned()); 387 | } 388 | } 389 | 390 | impl Default for LinkedHashSet 391 | where 392 | S: Default, 393 | { 394 | #[cfg_attr(feature = "inline-more", inline)] 395 | fn default() -> LinkedHashSet { 396 | LinkedHashSet { 397 | map: LinkedHashMap::default(), 398 | } 399 | } 400 | } 401 | 402 | impl<'a, 'b, T, S> BitOr<&'b LinkedHashSet> for &'a LinkedHashSet 403 | where 404 | T: Eq + Hash + Clone, 405 | S: BuildHasher + Default, 406 | { 407 | type Output = LinkedHashSet; 408 | 409 | #[cfg_attr(feature = "inline-more", inline)] 410 | fn bitor(self, rhs: &LinkedHashSet) -> LinkedHashSet { 411 | self.union(rhs).cloned().collect() 412 | } 413 | } 414 | 415 | impl<'a, 'b, T, S> BitAnd<&'b LinkedHashSet> for &'a LinkedHashSet 416 | where 417 | T: Eq + Hash + Clone, 418 | S: BuildHasher + Default, 419 | { 420 | type Output = LinkedHashSet; 421 | 422 | #[cfg_attr(feature = "inline-more", inline)] 423 | fn bitand(self, rhs: &LinkedHashSet) -> LinkedHashSet { 424 | self.intersection(rhs).cloned().collect() 425 | } 426 | } 427 | 428 | impl<'a, 'b, T, S> BitXor<&'b LinkedHashSet> for &'a LinkedHashSet 429 | where 430 | T: Eq + Hash + Clone, 431 | S: BuildHasher + Default, 432 | { 433 | type Output = LinkedHashSet; 434 | 435 | #[cfg_attr(feature = "inline-more", inline)] 436 | fn bitxor(self, rhs: &LinkedHashSet) -> LinkedHashSet { 437 | self.symmetric_difference(rhs).cloned().collect() 438 | } 439 | } 440 | 441 | impl<'a, 'b, T, S> Sub<&'b LinkedHashSet> for &'a LinkedHashSet 442 | where 443 | T: Eq + Hash + Clone, 444 | S: BuildHasher + Default, 445 | { 446 | type Output = LinkedHashSet; 447 | 448 | #[cfg_attr(feature = "inline-more", inline)] 449 | fn sub(self, rhs: &LinkedHashSet) -> LinkedHashSet { 450 | self.difference(rhs).cloned().collect() 451 | } 452 | } 453 | 454 | pub struct Iter<'a, K> { 455 | iter: linked_hash_map::Keys<'a, K, ()>, 456 | } 457 | 458 | pub struct IntoIter { 459 | iter: linked_hash_map::IntoIter, 460 | } 461 | 462 | pub struct Drain<'a, K: 'a> { 463 | iter: linked_hash_map::Drain<'a, K, ()>, 464 | } 465 | 466 | pub struct Intersection<'a, T, S> { 467 | iter: Iter<'a, T>, 468 | other: &'a LinkedHashSet, 469 | } 470 | 471 | pub struct Difference<'a, T, S> { 472 | iter: Iter<'a, T>, 473 | other: &'a LinkedHashSet, 474 | } 475 | 476 | pub struct SymmetricDifference<'a, T, S> { 477 | iter: Chain, Difference<'a, T, S>>, 478 | } 479 | 480 | pub struct Union<'a, T, S> { 481 | iter: Chain, Difference<'a, T, S>>, 482 | } 483 | 484 | impl<'a, T, S> IntoIterator for &'a LinkedHashSet { 485 | type Item = &'a T; 486 | type IntoIter = Iter<'a, T>; 487 | 488 | #[cfg_attr(feature = "inline-more", inline)] 489 | fn into_iter(self) -> Iter<'a, T> { 490 | self.iter() 491 | } 492 | } 493 | 494 | impl IntoIterator for LinkedHashSet { 495 | type Item = T; 496 | type IntoIter = IntoIter; 497 | 498 | #[cfg_attr(feature = "inline-more", inline)] 499 | fn into_iter(self) -> IntoIter { 500 | IntoIter { 501 | iter: self.map.into_iter(), 502 | } 503 | } 504 | } 505 | 506 | impl<'a, K> Clone for Iter<'a, K> { 507 | #[cfg_attr(feature = "inline-more", inline)] 508 | fn clone(&self) -> Iter<'a, K> { 509 | Iter { 510 | iter: self.iter.clone(), 511 | } 512 | } 513 | } 514 | impl<'a, K> Iterator for Iter<'a, K> { 515 | type Item = &'a K; 516 | 517 | #[cfg_attr(feature = "inline-more", inline)] 518 | fn next(&mut self) -> Option<&'a K> { 519 | self.iter.next() 520 | } 521 | 522 | #[cfg_attr(feature = "inline-more", inline)] 523 | fn size_hint(&self) -> (usize, Option) { 524 | self.iter.size_hint() 525 | } 526 | } 527 | 528 | impl<'a, K> ExactSizeIterator for Iter<'a, K> {} 529 | 530 | impl<'a, T> DoubleEndedIterator for Iter<'a, T> { 531 | #[cfg_attr(feature = "inline-more", inline)] 532 | fn next_back(&mut self) -> Option<&'a T> { 533 | self.iter.next_back() 534 | } 535 | } 536 | 537 | impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { 538 | #[cfg_attr(feature = "inline-more", inline)] 539 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 540 | f.debug_list().entries(self.clone()).finish() 541 | } 542 | } 543 | 544 | impl Iterator for IntoIter { 545 | type Item = K; 546 | 547 | #[cfg_attr(feature = "inline-more", inline)] 548 | fn next(&mut self) -> Option { 549 | self.iter.next().map(|(k, _)| k) 550 | } 551 | 552 | #[cfg_attr(feature = "inline-more", inline)] 553 | fn size_hint(&self) -> (usize, Option) { 554 | self.iter.size_hint() 555 | } 556 | } 557 | 558 | impl ExactSizeIterator for IntoIter {} 559 | 560 | impl DoubleEndedIterator for IntoIter { 561 | #[cfg_attr(feature = "inline-more", inline)] 562 | fn next_back(&mut self) -> Option { 563 | self.iter.next_back().map(|(k, _)| k) 564 | } 565 | } 566 | 567 | impl<'a, K> Iterator for Drain<'a, K> { 568 | type Item = K; 569 | 570 | #[cfg_attr(feature = "inline-more", inline)] 571 | fn next(&mut self) -> Option { 572 | self.iter.next().map(|(k, _)| k) 573 | } 574 | 575 | #[cfg_attr(feature = "inline-more", inline)] 576 | fn size_hint(&self) -> (usize, Option) { 577 | self.iter.size_hint() 578 | } 579 | } 580 | 581 | impl<'a, K> DoubleEndedIterator for Drain<'a, K> { 582 | #[cfg_attr(feature = "inline-more", inline)] 583 | fn next_back(&mut self) -> Option { 584 | self.iter.next_back().map(|(k, _)| k) 585 | } 586 | } 587 | 588 | impl<'a, K> ExactSizeIterator for Drain<'a, K> {} 589 | 590 | impl<'a, T, S> Clone for Intersection<'a, T, S> { 591 | #[cfg_attr(feature = "inline-more", inline)] 592 | fn clone(&self) -> Intersection<'a, T, S> { 593 | Intersection { 594 | iter: self.iter.clone(), 595 | ..*self 596 | } 597 | } 598 | } 599 | 600 | impl<'a, T, S> Iterator for Intersection<'a, T, S> 601 | where 602 | T: Eq + Hash, 603 | S: BuildHasher, 604 | { 605 | type Item = &'a T; 606 | 607 | #[cfg_attr(feature = "inline-more", inline)] 608 | fn next(&mut self) -> Option<&'a T> { 609 | loop { 610 | match self.iter.next() { 611 | None => return None, 612 | Some(elt) => { 613 | if self.other.contains(elt) { 614 | return Some(elt); 615 | } 616 | } 617 | } 618 | } 619 | } 620 | 621 | #[cfg_attr(feature = "inline-more", inline)] 622 | fn size_hint(&self) -> (usize, Option) { 623 | let (_, upper) = self.iter.size_hint(); 624 | (0, upper) 625 | } 626 | } 627 | 628 | impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> 629 | where 630 | T: fmt::Debug + Eq + Hash, 631 | S: BuildHasher, 632 | { 633 | #[cfg_attr(feature = "inline-more", inline)] 634 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 635 | f.debug_list().entries(self.clone()).finish() 636 | } 637 | } 638 | 639 | impl<'a, T, S> Clone for Difference<'a, T, S> { 640 | #[cfg_attr(feature = "inline-more", inline)] 641 | fn clone(&self) -> Difference<'a, T, S> { 642 | Difference { 643 | iter: self.iter.clone(), 644 | ..*self 645 | } 646 | } 647 | } 648 | 649 | impl<'a, T, S> Iterator for Difference<'a, T, S> 650 | where 651 | T: Eq + Hash, 652 | S: BuildHasher, 653 | { 654 | type Item = &'a T; 655 | 656 | #[cfg_attr(feature = "inline-more", inline)] 657 | fn next(&mut self) -> Option<&'a T> { 658 | loop { 659 | match self.iter.next() { 660 | None => return None, 661 | Some(elt) => { 662 | if !self.other.contains(elt) { 663 | return Some(elt); 664 | } 665 | } 666 | } 667 | } 668 | } 669 | 670 | #[cfg_attr(feature = "inline-more", inline)] 671 | fn size_hint(&self) -> (usize, Option) { 672 | let (_, upper) = self.iter.size_hint(); 673 | (0, upper) 674 | } 675 | } 676 | 677 | impl<'a, T, S> fmt::Debug for Difference<'a, T, S> 678 | where 679 | T: fmt::Debug + Eq + Hash, 680 | S: BuildHasher, 681 | { 682 | #[cfg_attr(feature = "inline-more", inline)] 683 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 684 | f.debug_list().entries(self.clone()).finish() 685 | } 686 | } 687 | 688 | impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { 689 | #[cfg_attr(feature = "inline-more", inline)] 690 | fn clone(&self) -> SymmetricDifference<'a, T, S> { 691 | SymmetricDifference { 692 | iter: self.iter.clone(), 693 | } 694 | } 695 | } 696 | 697 | impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> 698 | where 699 | T: Eq + Hash, 700 | S: BuildHasher, 701 | { 702 | type Item = &'a T; 703 | 704 | #[cfg_attr(feature = "inline-more", inline)] 705 | fn next(&mut self) -> Option<&'a T> { 706 | self.iter.next() 707 | } 708 | 709 | #[cfg_attr(feature = "inline-more", inline)] 710 | fn size_hint(&self) -> (usize, Option) { 711 | self.iter.size_hint() 712 | } 713 | } 714 | 715 | impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> 716 | where 717 | T: fmt::Debug + Eq + Hash, 718 | S: BuildHasher, 719 | { 720 | #[cfg_attr(feature = "inline-more", inline)] 721 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 722 | f.debug_list().entries(self.clone()).finish() 723 | } 724 | } 725 | 726 | impl<'a, T, S> Clone for Union<'a, T, S> { 727 | #[cfg_attr(feature = "inline-more", inline)] 728 | fn clone(&self) -> Union<'a, T, S> { 729 | Union { 730 | iter: self.iter.clone(), 731 | } 732 | } 733 | } 734 | 735 | impl<'a, T, S> fmt::Debug for Union<'a, T, S> 736 | where 737 | T: fmt::Debug + Eq + Hash, 738 | S: BuildHasher, 739 | { 740 | #[cfg_attr(feature = "inline-more", inline)] 741 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 742 | f.debug_list().entries(self.clone()).finish() 743 | } 744 | } 745 | 746 | impl<'a, T, S> Iterator for Union<'a, T, S> 747 | where 748 | T: Eq + Hash, 749 | S: BuildHasher, 750 | { 751 | type Item = &'a T; 752 | 753 | #[cfg_attr(feature = "inline-more", inline)] 754 | fn next(&mut self) -> Option<&'a T> { 755 | self.iter.next() 756 | } 757 | 758 | #[cfg_attr(feature = "inline-more", inline)] 759 | fn size_hint(&self) -> (usize, Option) { 760 | self.iter.size_hint() 761 | } 762 | } 763 | -------------------------------------------------------------------------------- /tests/linked_hash_map.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "default")] 2 | 3 | use ritelinked::{linked_hash_map, LinkedHashMap}; 4 | 5 | #[allow(dead_code)] 6 | fn assert_covariance() { 7 | fn set<'new>(v: LinkedHashMap<&'static str, ()>) -> LinkedHashMap<&'new str, ()> { 8 | v 9 | } 10 | 11 | fn iter<'a, 'new>( 12 | v: linked_hash_map::Iter<'a, &'static str, &'static str>, 13 | ) -> linked_hash_map::Iter<'a, &'new str, &'new str> { 14 | v 15 | } 16 | 17 | fn iter_mut<'a, 'new>( 18 | v: linked_hash_map::Iter<'a, &'static str, ()>, 19 | ) -> linked_hash_map::Iter<'a, &'new str, ()> { 20 | v 21 | } 22 | 23 | fn into_iter<'new>( 24 | v: linked_hash_map::IntoIter<&'static str, &'static str>, 25 | ) -> linked_hash_map::IntoIter<&'new str, &'new str> { 26 | v 27 | } 28 | 29 | fn drain<'new>( 30 | d: linked_hash_map::Drain<'static, &'static str, &'static str>, 31 | ) -> linked_hash_map::Drain<'new, &'new str, &'new str> { 32 | d 33 | } 34 | 35 | fn raw_entry_builder<'a, 'new>( 36 | v: linked_hash_map::RawEntryBuilder<'a, &'static str, &'static str, ()>, 37 | ) -> linked_hash_map::RawEntryBuilder<'a, &'new str, &'new str, ()> { 38 | v 39 | } 40 | } 41 | 42 | #[test] 43 | fn test_index() { 44 | let mut map = LinkedHashMap::new(); 45 | map.insert(1, 10); 46 | map.insert(2, 20); 47 | assert_eq!(10, map[&1]); 48 | map[&2] = 22; 49 | assert_eq!(22, map[&2]); 50 | } 51 | 52 | #[test] 53 | fn test_insert_and_get() { 54 | let mut map = LinkedHashMap::new(); 55 | map.insert(1, 10); 56 | map.insert(2, 20); 57 | assert_eq!(map.get(&1), Some(&10)); 58 | assert_eq!(map.get(&2), Some(&20)); 59 | assert_eq!(map.len(), 2); 60 | } 61 | 62 | #[test] 63 | fn test_get_refresh() { 64 | let mut map = LinkedHashMap::new(); 65 | 66 | map.insert(1, "a"); 67 | map.insert(2, "b"); 68 | map.insert(3, "d"); 69 | 70 | assert_eq!(map.get_refresh(&2), Some(&mut "b")); 71 | assert_eq!((&2, &"b"), map.iter().rev().next().unwrap()); 72 | } 73 | 74 | #[test] 75 | fn test_insert_update() { 76 | let mut map = LinkedHashMap::new(); 77 | map.insert("1".to_string(), vec![10, 10]); 78 | map.insert("1".to_string(), vec![10, 19]); 79 | assert_eq!(map.get(&"1".to_string()), Some(&vec![10, 19])); 80 | assert_eq!(map.len(), 1); 81 | } 82 | 83 | #[test] 84 | fn test_entry_insert_vacant() { 85 | let mut map = LinkedHashMap::new(); 86 | match map.entry("1".to_string()) { 87 | linked_hash_map::Entry::Vacant(e) => { 88 | assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]); 89 | } 90 | _ => panic!("fail"), 91 | } 92 | assert!(map.contains_key("1")); 93 | assert_eq!(map["1"], vec![10, 10]); 94 | 95 | match map.entry("1".to_string()) { 96 | linked_hash_map::Entry::Occupied(mut e) => { 97 | assert_eq!(*e.get(), vec![10, 10]); 98 | assert_eq!(e.insert(vec![10, 16]), vec![10, 10]); 99 | } 100 | _ => panic!("fail"), 101 | } 102 | 103 | assert!(map.contains_key("1")); 104 | assert_eq!(map["1"], vec![10, 16]); 105 | 106 | match map.entry("1".to_string()) { 107 | linked_hash_map::Entry::Occupied(e) => { 108 | assert_eq!(e.remove(), vec![10, 16]); 109 | } 110 | _ => panic!("fail"), 111 | } 112 | } 113 | 114 | #[test] 115 | fn test_remove() { 116 | let mut map = LinkedHashMap::new(); 117 | map.insert(1, 10); 118 | map.insert(2, 20); 119 | map.insert(3, 30); 120 | map.insert(4, 40); 121 | map.insert(5, 50); 122 | map.remove(&3); 123 | map.remove(&4); 124 | assert!(map.get(&3).is_none()); 125 | assert!(map.get(&4).is_none()); 126 | map.insert(6, 60); 127 | map.insert(7, 70); 128 | map.insert(8, 80); 129 | assert_eq!(map.get(&6), Some(&60)); 130 | assert_eq!(map.get(&7), Some(&70)); 131 | assert_eq!(map.get(&8), Some(&80)); 132 | } 133 | 134 | #[test] 135 | fn test_pop() { 136 | let mut map = LinkedHashMap::new(); 137 | map.insert(1, 10); 138 | map.insert(2, 20); 139 | map.insert(3, 30); 140 | map.insert(4, 40); 141 | map.insert(5, 50); 142 | assert_eq!(map.pop_front(), Some((1, 10))); 143 | assert!(map.get(&1).is_none()); 144 | assert_eq!(map.pop_back(), Some((5, 50))); 145 | assert!(map.get(&5).is_none()); 146 | map.insert(6, 60); 147 | map.insert(7, 70); 148 | map.insert(8, 80); 149 | assert_eq!(map.pop_front(), Some((2, 20))); 150 | assert!(map.get(&2).is_none()); 151 | assert_eq!(map.pop_back(), Some((8, 80))); 152 | assert!(map.get(&8).is_none()); 153 | map.insert(3, 30); 154 | assert_eq!(map.pop_front(), Some((4, 40))); 155 | assert!(map.get(&4).is_none()); 156 | assert_eq!(map.pop_back(), Some((3, 30))); 157 | assert!(map.get(&3).is_none()); 158 | } 159 | 160 | #[test] 161 | fn test_move() { 162 | let to_back = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) { 163 | linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_back(), 164 | linked_hash_map::Entry::Vacant(_) => panic!(), 165 | }; 166 | 167 | let to_front = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) { 168 | linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_front(), 169 | linked_hash_map::Entry::Vacant(_) => panic!(), 170 | }; 171 | 172 | let mut map = LinkedHashMap::new(); 173 | map.insert(1, 10); 174 | map.insert(2, 20); 175 | map.insert(3, 30); 176 | map.insert(4, 40); 177 | map.insert(5, 50); 178 | 179 | to_back(&mut map, 1); 180 | assert_eq!(map.keys().copied().collect::>(), vec![2, 3, 4, 5, 1]); 181 | 182 | to_front(&mut map, 4); 183 | assert_eq!(map.keys().copied().collect::>(), vec![4, 2, 3, 5, 1]); 184 | 185 | to_back(&mut map, 3); 186 | assert_eq!(map.keys().copied().collect::>(), vec![4, 2, 5, 1, 3]); 187 | 188 | to_front(&mut map, 2); 189 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 190 | 191 | to_back(&mut map, 3); 192 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 193 | 194 | to_front(&mut map, 2); 195 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 196 | } 197 | 198 | #[test] 199 | fn test_clear() { 200 | let mut map = LinkedHashMap::new(); 201 | map.insert(1, 10); 202 | map.insert(2, 20); 203 | map.clear(); 204 | assert!(map.get(&1).is_none()); 205 | assert!(map.get(&2).is_none()); 206 | assert!(map.is_empty()); 207 | } 208 | 209 | #[test] 210 | fn test_iter() { 211 | let mut map = LinkedHashMap::new(); 212 | 213 | // empty iter 214 | assert_eq!(None, map.iter().next()); 215 | 216 | map.insert("a", 10); 217 | map.insert("b", 20); 218 | map.insert("c", 30); 219 | 220 | // regular iter 221 | let mut iter = map.iter(); 222 | assert_eq!((&"a", &10), iter.next().unwrap()); 223 | assert_eq!((&"b", &20), iter.next().unwrap()); 224 | assert_eq!((&"c", &30), iter.next().unwrap()); 225 | assert_eq!(None, iter.next()); 226 | assert_eq!(None, iter.next()); 227 | 228 | let mut iter = map.iter(); 229 | assert_eq!((&"a", &10), iter.next().unwrap()); 230 | let mut iclone = iter.clone(); 231 | assert_eq!((&"b", &20), iter.next().unwrap()); 232 | assert_eq!((&"b", &20), iclone.next().unwrap()); 233 | assert_eq!((&"c", &30), iter.next().unwrap()); 234 | assert_eq!((&"c", &30), iclone.next().unwrap()); 235 | 236 | // reversed iter 237 | let mut rev_iter = map.iter().rev(); 238 | assert_eq!((&"c", &30), rev_iter.next().unwrap()); 239 | assert_eq!((&"b", &20), rev_iter.next().unwrap()); 240 | assert_eq!((&"a", &10), rev_iter.next().unwrap()); 241 | assert_eq!(None, rev_iter.next()); 242 | assert_eq!(None, rev_iter.next()); 243 | 244 | // mixed 245 | let mut mixed_iter = map.iter(); 246 | assert_eq!((&"a", &10), mixed_iter.next().unwrap()); 247 | assert_eq!((&"c", &30), mixed_iter.next_back().unwrap()); 248 | assert_eq!((&"b", &20), mixed_iter.next().unwrap()); 249 | assert_eq!(None, mixed_iter.next()); 250 | assert_eq!(None, mixed_iter.next_back()); 251 | } 252 | 253 | #[test] 254 | fn test_borrow() { 255 | #[derive(PartialEq, Eq, Hash)] 256 | struct Foo(Bar); 257 | #[derive(PartialEq, Eq, Hash)] 258 | struct Bar(i32); 259 | 260 | impl ::std::borrow::Borrow for Foo { 261 | fn borrow(&self) -> &Bar { 262 | &self.0 263 | } 264 | } 265 | 266 | let mut map = LinkedHashMap::new(); 267 | map.insert(Foo(Bar(1)), "a"); 268 | map.insert(Foo(Bar(2)), "b"); 269 | 270 | assert!(map.contains_key(&Bar(1))); 271 | assert!(map.contains_key(&Bar(2))); 272 | assert!(map.contains_key(&Foo(Bar(1)))); 273 | assert!(map.contains_key(&Foo(Bar(2)))); 274 | 275 | assert_eq!(map.get(&Bar(1)), Some(&"a")); 276 | assert_eq!(map.get(&Bar(2)), Some(&"b")); 277 | assert_eq!(map.get(&Foo(Bar(1))), Some(&"a")); 278 | assert_eq!(map.get(&Foo(Bar(2))), Some(&"b")); 279 | 280 | assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a")); 281 | assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b")); 282 | assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a")); 283 | assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b")); 284 | 285 | assert_eq!(map[&Bar(1)], "a"); 286 | assert_eq!(map[&Bar(2)], "b"); 287 | assert_eq!(map[&Foo(Bar(1))], "a"); 288 | assert_eq!(map[&Foo(Bar(2))], "b"); 289 | 290 | assert_eq!(map.remove(&Bar(1)), Some("a")); 291 | assert_eq!(map.remove(&Bar(2)), Some("b")); 292 | assert_eq!(map.remove(&Foo(Bar(1))), None); 293 | assert_eq!(map.remove(&Foo(Bar(2))), None); 294 | } 295 | 296 | #[test] 297 | fn test_iter_mut() { 298 | let mut map = LinkedHashMap::new(); 299 | map.insert("a", 10); 300 | map.insert("c", 30); 301 | map.insert("b", 20); 302 | 303 | { 304 | let mut iter = map.iter_mut(); 305 | let entry = iter.next().unwrap(); 306 | assert_eq!("a", *entry.0); 307 | *entry.1 = 17; 308 | 309 | assert_eq!(format!("{:?}", iter), "[(\"c\", 30), (\"b\", 20)]"); 310 | 311 | // reverse iterator 312 | let mut iter = iter.rev(); 313 | let entry = iter.next().unwrap(); 314 | assert_eq!("b", *entry.0); 315 | *entry.1 = 23; 316 | 317 | let entry = iter.next().unwrap(); 318 | assert_eq!("c", *entry.0); 319 | assert_eq!(None, iter.next()); 320 | assert_eq!(None, iter.next()); 321 | } 322 | 323 | assert_eq!(17, map[&"a"]); 324 | assert_eq!(23, map[&"b"]); 325 | } 326 | 327 | #[test] 328 | fn test_consuming_iter() { 329 | let map = { 330 | let mut map = LinkedHashMap::new(); 331 | map.insert("a", 10); 332 | map.insert("c", 30); 333 | map.insert("b", 20); 334 | map 335 | }; 336 | 337 | let mut iter = map.into_iter(); 338 | assert_eq!(Some(("a", 10)), iter.next()); 339 | assert_eq!(Some(("b", 20)), iter.next_back()); 340 | assert_eq!(iter.len(), 1); 341 | assert_eq!(format!("{:?}", iter), "[(\"c\", 30)]"); 342 | assert_eq!(Some(("c", 30)), iter.next()); 343 | assert_eq!(None, iter.next()); 344 | } 345 | 346 | #[test] 347 | fn test_consuming_iter_empty() { 348 | let map = LinkedHashMap::<&str, i32>::new(); 349 | let mut iter = map.into_iter(); 350 | assert_eq!(None, iter.next()); 351 | } 352 | 353 | #[test] 354 | fn test_consuming_iter_with_free_list() { 355 | let mut map = LinkedHashMap::new(); 356 | map.insert("a", 10); 357 | map.insert("c", 30); 358 | map.insert("b", 20); 359 | map.remove("a"); 360 | map.remove("b"); 361 | 362 | let mut iter = map.into_iter(); 363 | assert_eq!(Some(("c", 30)), iter.next()); 364 | assert_eq!(None, iter.next()); 365 | } 366 | 367 | #[test] 368 | fn test_into_iter_drop() { 369 | struct Counter<'a>(&'a mut usize); 370 | 371 | impl<'a> Drop for Counter<'a> { 372 | fn drop(&mut self) { 373 | *self.0 += 1; 374 | } 375 | } 376 | 377 | let mut a = 0; 378 | let mut b = 0; 379 | let mut c = 0; 380 | 381 | { 382 | let mut map = LinkedHashMap::new(); 383 | map.insert("a", Counter(&mut a)); 384 | map.insert("b", Counter(&mut b)); 385 | map.insert("c", Counter(&mut c)); 386 | 387 | let mut iter = map.into_iter(); 388 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 389 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 390 | } 391 | 392 | assert_eq!(a, 1); 393 | assert_eq!(b, 1); 394 | assert_eq!(c, 1); 395 | } 396 | 397 | #[test] 398 | fn test_drain() { 399 | use std::{cell::Cell, rc::Rc}; 400 | 401 | struct Counter(Rc>); 402 | 403 | impl<'a> Drop for Counter { 404 | fn drop(&mut self) { 405 | self.0.set(self.0.get() + 1); 406 | } 407 | } 408 | 409 | let mut map = LinkedHashMap::new(); 410 | 411 | let a = Rc::new(Cell::new(0)); 412 | let b = Rc::new(Cell::new(0)); 413 | let c = Rc::new(Cell::new(0)); 414 | 415 | map.insert("a", Counter(a.clone())); 416 | map.insert("b", Counter(b.clone())); 417 | map.insert("c", Counter(c.clone())); 418 | 419 | let mut iter = map.drain(); 420 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 421 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 422 | assert_eq!(iter.next_back().map(|p| p.0), Some("b")); 423 | assert!(iter.next().is_none()); 424 | assert!(iter.next_back().is_none()); 425 | 426 | drop(iter); 427 | assert_eq!(map.len(), 0); 428 | 429 | assert_eq!(a.get(), 1); 430 | assert_eq!(b.get(), 1); 431 | assert_eq!(c.get(), 1); 432 | 433 | map.insert("a", Counter(a.clone())); 434 | map.insert("b", Counter(b.clone())); 435 | map.insert("c", Counter(c.clone())); 436 | 437 | let mut iter = map.drain(); 438 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 439 | assert_eq!(iter.next().map(|p| p.0), Some("b")); 440 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 441 | assert!(iter.next().is_none()); 442 | assert!(iter.next_back().is_none()); 443 | 444 | drop(iter); 445 | assert_eq!(map.len(), 0); 446 | 447 | assert_eq!(a.get(), 2); 448 | assert_eq!(b.get(), 2); 449 | assert_eq!(c.get(), 2); 450 | 451 | map.insert("a", Counter(a.clone())); 452 | map.insert("b", Counter(b.clone())); 453 | map.insert("c", Counter(c.clone())); 454 | 455 | map.drain(); 456 | assert_eq!(map.len(), 0); 457 | 458 | assert_eq!(a.get(), 3); 459 | assert_eq!(b.get(), 3); 460 | assert_eq!(c.get(), 3); 461 | } 462 | 463 | #[test] 464 | fn test_send_sync() { 465 | fn is_send_sync() {} 466 | 467 | is_send_sync::>(); 468 | is_send_sync::>(); 469 | is_send_sync::>(); 470 | is_send_sync::>(); 471 | is_send_sync::>(); 472 | is_send_sync::>(); 473 | is_send_sync::>(); 474 | is_send_sync::>(); 475 | is_send_sync::>(); 476 | is_send_sync::>(); 477 | } 478 | 479 | #[test] 480 | fn test_retain() { 481 | use std::{cell::Cell, rc::Rc}; 482 | 483 | let xs = [1, 2, 3, 4, 5, 6]; 484 | let mut map: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 485 | map.retain(|_, v| *v % 2 == 0); 486 | assert_eq!(map.len(), 3); 487 | assert!(map.contains_key("2")); 488 | assert!(map.contains_key("4")); 489 | assert!(map.contains_key("6")); 490 | 491 | struct Counter(Rc>); 492 | 493 | impl<'a> Drop for Counter { 494 | fn drop(&mut self) { 495 | self.0.set(self.0.get() + 1); 496 | } 497 | } 498 | 499 | let c = Rc::new(Cell::new(0)); 500 | 501 | let mut map = LinkedHashMap::new(); 502 | map.insert(1, Counter(Rc::clone(&c))); 503 | map.insert(2, Counter(Rc::clone(&c))); 504 | map.insert(3, Counter(Rc::clone(&c))); 505 | map.insert(4, Counter(Rc::clone(&c))); 506 | 507 | map.retain(|k, _| *k % 2 == 0); 508 | 509 | assert!(c.get() == 2); 510 | drop(map); 511 | assert!(c.get() == 4); 512 | } 513 | 514 | #[test] 515 | fn test_order_equality() { 516 | let xs = [1, 2, 3, 4, 5, 6]; 517 | let mut map1: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 518 | let mut map2: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 519 | 520 | assert_eq!(map1, map2); 521 | 522 | map1.to_front("4"); 523 | assert_ne!(map1, map2); 524 | 525 | map2.to_front("4"); 526 | assert_eq!(map1, map2); 527 | } 528 | 529 | #[test] 530 | fn test_replace() { 531 | let mut map = LinkedHashMap::new(); 532 | 533 | map.insert(1, 1); 534 | map.insert(2, 2); 535 | map.insert(3, 3); 536 | map.insert(4, 4); 537 | 538 | assert!(map 539 | .iter() 540 | .map(|(k, v)| (*k, *v)) 541 | .eq([(1, 1), (2, 2), (3, 3), (4, 4)].iter().copied())); 542 | 543 | map.insert(3, 5); 544 | 545 | assert!(map 546 | .iter() 547 | .map(|(k, v)| (*k, *v)) 548 | .eq([(1, 1), (2, 2), (4, 4), (3, 5)].iter().copied())); 549 | 550 | map.replace(2, 6); 551 | 552 | assert!(map 553 | .iter() 554 | .map(|(k, v)| (*k, *v)) 555 | .eq([(1, 1), (2, 6), (4, 4), (3, 5)].iter().copied())); 556 | } 557 | -------------------------------------------------------------------------------- /tests/linked_hash_set.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "default")] 2 | 3 | use hashbrown::hash_map::DefaultHashBuilder; 4 | use ritelinked::linked_hash_set::{self, LinkedHashSet}; 5 | 6 | #[allow(dead_code)] 7 | fn assert_covariance() { 8 | fn set<'new>(v: LinkedHashSet<&'static str>) -> LinkedHashSet<&'new str> { 9 | v 10 | } 11 | 12 | fn iter<'a, 'new>( 13 | v: linked_hash_set::Iter<'a, &'static str>, 14 | ) -> linked_hash_set::Iter<'a, &'new str> { 15 | v 16 | } 17 | 18 | fn into_iter<'new>( 19 | v: linked_hash_set::IntoIter<&'static str>, 20 | ) -> linked_hash_set::IntoIter<&'new str> { 21 | v 22 | } 23 | 24 | fn difference<'a, 'new>( 25 | v: linked_hash_set::Difference<'a, &'static str, DefaultHashBuilder>, 26 | ) -> linked_hash_set::Difference<'a, &'new str, DefaultHashBuilder> { 27 | v 28 | } 29 | 30 | fn symmetric_difference<'a, 'new>( 31 | v: linked_hash_set::SymmetricDifference<'a, &'static str, DefaultHashBuilder>, 32 | ) -> linked_hash_set::SymmetricDifference<'a, &'new str, DefaultHashBuilder> { 33 | v 34 | } 35 | 36 | fn intersection<'a, 'new>( 37 | v: linked_hash_set::Intersection<'a, &'static str, DefaultHashBuilder>, 38 | ) -> linked_hash_set::Intersection<'a, &'new str, DefaultHashBuilder> { 39 | v 40 | } 41 | 42 | fn union<'a, 'new>( 43 | v: linked_hash_set::Union<'a, &'static str, DefaultHashBuilder>, 44 | ) -> linked_hash_set::Union<'a, &'new str, DefaultHashBuilder> { 45 | v 46 | } 47 | 48 | fn drain<'new>( 49 | d: linked_hash_set::Drain<'static, &'static str>, 50 | ) -> linked_hash_set::Drain<'new, &'new str> { 51 | d 52 | } 53 | } 54 | 55 | #[test] 56 | fn test_zero_capacities() { 57 | type HS = LinkedHashSet; 58 | 59 | let s = HS::new(); 60 | assert_eq!(s.capacity(), 0); 61 | 62 | let s = HS::default(); 63 | assert_eq!(s.capacity(), 0); 64 | 65 | let s = HS::with_hasher(DefaultHashBuilder::default()); 66 | assert_eq!(s.capacity(), 0); 67 | 68 | let s = HS::with_capacity(0); 69 | assert_eq!(s.capacity(), 0); 70 | 71 | let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default()); 72 | assert_eq!(s.capacity(), 0); 73 | 74 | let mut s = HS::new(); 75 | s.insert(1); 76 | s.insert(2); 77 | s.remove(&1); 78 | s.remove(&2); 79 | s.shrink_to_fit(); 80 | assert_eq!(s.capacity(), 0); 81 | 82 | let mut s = HS::new(); 83 | s.reserve(0); 84 | assert_eq!(s.capacity(), 0); 85 | } 86 | 87 | #[test] 88 | fn test_disjoint() { 89 | let mut xs = LinkedHashSet::new(); 90 | let mut ys = LinkedHashSet::new(); 91 | assert!(xs.is_disjoint(&ys)); 92 | assert!(ys.is_disjoint(&xs)); 93 | assert!(xs.insert(5)); 94 | assert!(ys.insert(11)); 95 | assert!(xs.is_disjoint(&ys)); 96 | assert!(ys.is_disjoint(&xs)); 97 | assert!(xs.insert(7)); 98 | assert!(xs.insert(19)); 99 | assert!(xs.insert(4)); 100 | assert!(ys.insert(2)); 101 | assert!(ys.insert(-11)); 102 | assert!(xs.is_disjoint(&ys)); 103 | assert!(ys.is_disjoint(&xs)); 104 | assert!(ys.insert(7)); 105 | assert!(!xs.is_disjoint(&ys)); 106 | assert!(!ys.is_disjoint(&xs)); 107 | } 108 | 109 | #[test] 110 | fn test_subset_and_superset() { 111 | let mut a = LinkedHashSet::new(); 112 | assert!(a.insert(0)); 113 | assert!(a.insert(5)); 114 | assert!(a.insert(11)); 115 | assert!(a.insert(7)); 116 | 117 | let mut b = LinkedHashSet::new(); 118 | assert!(b.insert(0)); 119 | assert!(b.insert(7)); 120 | assert!(b.insert(19)); 121 | assert!(b.insert(250)); 122 | assert!(b.insert(11)); 123 | assert!(b.insert(200)); 124 | 125 | assert!(!a.is_subset(&b)); 126 | assert!(!a.is_superset(&b)); 127 | assert!(!b.is_subset(&a)); 128 | assert!(!b.is_superset(&a)); 129 | 130 | assert!(b.insert(5)); 131 | 132 | assert!(a.is_subset(&b)); 133 | assert!(!a.is_superset(&b)); 134 | assert!(!b.is_subset(&a)); 135 | assert!(b.is_superset(&a)); 136 | } 137 | 138 | #[test] 139 | fn test_iterate() { 140 | let mut a = LinkedHashSet::new(); 141 | for i in 0..32 { 142 | assert!(a.insert(i)); 143 | } 144 | let mut observed: u32 = 0; 145 | for k in &a { 146 | observed |= 1 << *k; 147 | } 148 | assert_eq!(observed, 0xFFFF_FFFF); 149 | } 150 | 151 | #[test] 152 | fn test_intersection() { 153 | let mut a = LinkedHashSet::new(); 154 | let mut b = LinkedHashSet::new(); 155 | 156 | assert!(a.insert(11)); 157 | assert!(a.insert(1)); 158 | assert!(a.insert(3)); 159 | assert!(a.insert(77)); 160 | assert!(a.insert(103)); 161 | assert!(a.insert(5)); 162 | assert!(a.insert(-5)); 163 | 164 | assert!(b.insert(2)); 165 | assert!(b.insert(11)); 166 | assert!(b.insert(77)); 167 | assert!(b.insert(-9)); 168 | assert!(b.insert(-42)); 169 | assert!(b.insert(5)); 170 | assert!(b.insert(3)); 171 | 172 | let mut i = 0; 173 | let expected = [3, 5, 11, 77]; 174 | for x in a.intersection(&b) { 175 | assert!(expected.contains(x)); 176 | i += 1 177 | } 178 | assert_eq!(i, expected.len()); 179 | } 180 | 181 | #[test] 182 | fn test_difference() { 183 | let mut a = LinkedHashSet::new(); 184 | let mut b = LinkedHashSet::new(); 185 | 186 | assert!(a.insert(1)); 187 | assert!(a.insert(3)); 188 | assert!(a.insert(5)); 189 | assert!(a.insert(9)); 190 | assert!(a.insert(11)); 191 | 192 | assert!(b.insert(3)); 193 | assert!(b.insert(9)); 194 | 195 | let mut i = 0; 196 | let expected = [1, 5, 11]; 197 | for x in a.difference(&b) { 198 | assert!(expected.contains(x)); 199 | i += 1 200 | } 201 | assert_eq!(i, expected.len()); 202 | } 203 | 204 | #[test] 205 | fn test_symmetric_difference() { 206 | let mut a = LinkedHashSet::new(); 207 | let mut b = LinkedHashSet::new(); 208 | 209 | assert!(a.insert(1)); 210 | assert!(a.insert(3)); 211 | assert!(a.insert(5)); 212 | assert!(a.insert(9)); 213 | assert!(a.insert(11)); 214 | 215 | assert!(b.insert(-2)); 216 | assert!(b.insert(3)); 217 | assert!(b.insert(9)); 218 | assert!(b.insert(14)); 219 | assert!(b.insert(22)); 220 | 221 | let mut i = 0; 222 | let expected = [-2, 1, 5, 11, 14, 22]; 223 | for x in a.symmetric_difference(&b) { 224 | assert!(expected.contains(x)); 225 | i += 1 226 | } 227 | assert_eq!(i, expected.len()); 228 | } 229 | 230 | #[test] 231 | fn test_union() { 232 | let mut a = LinkedHashSet::new(); 233 | let mut b = LinkedHashSet::new(); 234 | 235 | assert!(a.insert(1)); 236 | assert!(a.insert(3)); 237 | assert!(a.insert(5)); 238 | assert!(a.insert(9)); 239 | assert!(a.insert(11)); 240 | assert!(a.insert(16)); 241 | assert!(a.insert(19)); 242 | assert!(a.insert(24)); 243 | 244 | assert!(b.insert(-2)); 245 | assert!(b.insert(1)); 246 | assert!(b.insert(5)); 247 | assert!(b.insert(9)); 248 | assert!(b.insert(13)); 249 | assert!(b.insert(19)); 250 | 251 | let mut i = 0; 252 | let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; 253 | for x in a.union(&b) { 254 | assert!(expected.contains(x)); 255 | i += 1 256 | } 257 | assert_eq!(i, expected.len()); 258 | } 259 | 260 | #[test] 261 | fn test_from_iter() { 262 | let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 263 | 264 | let set: LinkedHashSet<_> = xs.iter().cloned().collect(); 265 | 266 | for x in &xs { 267 | assert!(set.contains(x)); 268 | } 269 | } 270 | 271 | #[test] 272 | fn test_move_iter() { 273 | let hs = { 274 | let mut hs = LinkedHashSet::new(); 275 | 276 | hs.insert('a'); 277 | hs.insert('b'); 278 | 279 | hs 280 | }; 281 | 282 | let v = hs.into_iter().collect::>(); 283 | assert!(v == ['a', 'b'] || v == ['b', 'a']); 284 | } 285 | 286 | #[test] 287 | fn test_eq() { 288 | let mut s1 = LinkedHashSet::new(); 289 | 290 | s1.insert(1); 291 | s1.insert(2); 292 | s1.insert(3); 293 | 294 | let mut s2 = LinkedHashSet::new(); 295 | 296 | s2.insert(1); 297 | s2.insert(2); 298 | 299 | assert!(s1 != s2); 300 | 301 | s2.insert(3); 302 | 303 | assert_eq!(s1, s2); 304 | } 305 | 306 | #[test] 307 | fn test_show() { 308 | let mut set = LinkedHashSet::new(); 309 | let empty = LinkedHashSet::::new(); 310 | 311 | set.insert(1); 312 | set.insert(2); 313 | 314 | let set_str = format!("{:?}", set); 315 | 316 | assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); 317 | assert_eq!(format!("{:?}", empty), "{}"); 318 | } 319 | 320 | #[test] 321 | fn test_trivial_drain() { 322 | let mut s = LinkedHashSet::::new(); 323 | for _ in s.drain() {} 324 | assert!(s.is_empty()); 325 | drop(s); 326 | 327 | let mut s = LinkedHashSet::::new(); 328 | drop(s.drain()); 329 | assert!(s.is_empty()); 330 | } 331 | 332 | #[test] 333 | fn test_drain() { 334 | let mut s: LinkedHashSet<_> = (1..100).collect(); 335 | 336 | for _ in 0..20 { 337 | assert_eq!(s.len(), 99); 338 | 339 | { 340 | let mut last_i = 0; 341 | let mut d = s.drain(); 342 | for (i, x) in d.by_ref().take(50).enumerate() { 343 | last_i = i; 344 | assert!(x != 0); 345 | } 346 | assert_eq!(last_i, 49); 347 | } 348 | 349 | for _ in &s { 350 | panic!("s should be empty!"); 351 | } 352 | 353 | s.extend(1..100); 354 | } 355 | } 356 | 357 | #[test] 358 | fn test_replace() { 359 | use core::hash; 360 | 361 | #[derive(Debug)] 362 | struct Foo(&'static str, i32); 363 | 364 | impl PartialEq for Foo { 365 | fn eq(&self, other: &Self) -> bool { 366 | self.0 == other.0 367 | } 368 | } 369 | 370 | impl Eq for Foo {} 371 | 372 | impl hash::Hash for Foo { 373 | fn hash(&self, h: &mut H) { 374 | self.0.hash(h); 375 | } 376 | } 377 | 378 | let mut s = LinkedHashSet::new(); 379 | assert_eq!(s.replace(Foo("a", 1)), None); 380 | assert_eq!(s.len(), 1); 381 | assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); 382 | assert_eq!(s.len(), 1); 383 | 384 | let mut it = s.iter(); 385 | assert_eq!(it.next(), Some(&Foo("a", 2))); 386 | assert_eq!(it.next(), None); 387 | } 388 | 389 | #[test] 390 | fn test_extend_ref() { 391 | let mut a = LinkedHashSet::new(); 392 | a.insert(1); 393 | 394 | a.extend(&[2, 3, 4]); 395 | 396 | assert_eq!(a.len(), 4); 397 | assert!(a.contains(&1)); 398 | assert!(a.contains(&2)); 399 | assert!(a.contains(&3)); 400 | assert!(a.contains(&4)); 401 | 402 | let mut b = LinkedHashSet::new(); 403 | b.insert(5); 404 | b.insert(6); 405 | 406 | a.extend(&b); 407 | 408 | assert_eq!(a.len(), 6); 409 | assert!(a.contains(&1)); 410 | assert!(a.contains(&2)); 411 | assert!(a.contains(&3)); 412 | assert!(a.contains(&4)); 413 | assert!(a.contains(&5)); 414 | assert!(a.contains(&6)); 415 | } 416 | 417 | #[test] 418 | fn test_retain() { 419 | let xs = [1, 2, 3, 4, 5, 6]; 420 | let mut set: LinkedHashSet = xs.iter().cloned().collect(); 421 | set.retain(|&k| k % 2 == 0); 422 | assert_eq!(set.len(), 3); 423 | assert!(set.contains(&2)); 424 | assert!(set.contains(&4)); 425 | assert!(set.contains(&6)); 426 | } 427 | 428 | #[test] 429 | fn insert_order() { 430 | let mut set = LinkedHashSet::new(); 431 | set.insert(1); 432 | set.insert(2); 433 | set.insert(3); 434 | set.insert(4); 435 | assert_eq!( 436 | set.clone().into_iter().collect::>(), 437 | vec![1, 2, 3, 4] 438 | ); 439 | assert_eq!(set.into_iter().collect::>(), vec![1, 2, 3, 4]); 440 | } 441 | 442 | #[test] 443 | fn front_back() { 444 | let mut set = LinkedHashSet::new(); 445 | set.insert(1); 446 | set.insert(2); 447 | set.insert(3); 448 | set.insert(4); 449 | assert_eq!(set.front(), Some(&1)); 450 | assert_eq!(set.back(), Some(&4)); 451 | assert_eq!(set.pop_back(), Some(4)); 452 | assert_eq!(set.back(), Some(&3)); 453 | assert_eq!(set.pop_front(), Some(1)); 454 | assert_eq!(set.front(), Some(&2)); 455 | } 456 | 457 | #[test] 458 | fn double_ended_iter() { 459 | let mut set = LinkedHashSet::new(); 460 | set.insert(1); 461 | set.insert(2); 462 | set.insert(3); 463 | set.insert(4); 464 | 465 | let mut iter = set.iter(); 466 | assert_eq!(iter.next(), Some(&1)); 467 | assert_eq!(iter.next(), Some(&2)); 468 | assert_eq!(iter.next_back(), Some(&4)); 469 | assert_eq!(iter.next_back(), Some(&3)); 470 | assert_eq!(iter.next_back(), None); 471 | assert_eq!(iter.next(), None); 472 | assert_eq!(iter.next_back(), None); 473 | drop(iter); 474 | 475 | let mut iter = set.drain(); 476 | assert_eq!(iter.next(), Some(1)); 477 | assert_eq!(iter.next(), Some(2)); 478 | assert_eq!(iter.next_back(), Some(4)); 479 | assert_eq!(iter.next_back(), Some(3)); 480 | assert_eq!(iter.next_back(), None); 481 | assert_eq!(iter.next(), None); 482 | assert_eq!(iter.next_back(), None); 483 | drop(iter); 484 | 485 | set.insert(1); 486 | set.insert(2); 487 | set.insert(3); 488 | set.insert(4); 489 | 490 | let mut iter = set.into_iter(); 491 | assert_eq!(iter.next(), Some(1)); 492 | assert_eq!(iter.next(), Some(2)); 493 | assert_eq!(iter.next_back(), Some(4)); 494 | assert_eq!(iter.next_back(), Some(3)); 495 | assert_eq!(iter.next_back(), None); 496 | assert_eq!(iter.next(), None); 497 | assert_eq!(iter.next_back(), None); 498 | } 499 | 500 | #[test] 501 | fn to_back_front_order() { 502 | let mut set = LinkedHashSet::new(); 503 | set.insert(1); 504 | set.insert(2); 505 | set.insert(3); 506 | set.insert(4); 507 | 508 | assert_eq!(set.back().copied(), Some(4)); 509 | assert_eq!(set.front().copied(), Some(1)); 510 | set.to_back(&2); 511 | assert_eq!(set.back().copied(), Some(2)); 512 | set.to_front(&3); 513 | assert_eq!(set.front().copied(), Some(3)); 514 | } 515 | 516 | #[test] 517 | fn test_order_equality() { 518 | let xs = [1, 2, 3, 4, 5, 6]; 519 | let mut set1: LinkedHashSet = xs.iter().copied().collect(); 520 | let mut set2: LinkedHashSet = xs.iter().copied().collect(); 521 | 522 | assert_eq!(set1, set2); 523 | 524 | set1.to_front(&4); 525 | assert_ne!(set1, set2); 526 | 527 | set2.to_front(&4); 528 | assert_eq!(set1, set2); 529 | } 530 | 531 | #[test] 532 | fn test_retain_order() { 533 | let xs = [1, 2, 3, 4, 5, 6]; 534 | let mut set: LinkedHashSet = xs.iter().cloned().collect(); 535 | let mut vec = Vec::new(); 536 | set.retain(|&k| { 537 | if k % 2 == 0 { 538 | true 539 | } else { 540 | vec.push(k); 541 | false 542 | } 543 | }); 544 | assert_eq!(vec![1, 3, 5], vec); 545 | } 546 | -------------------------------------------------------------------------------- /tests/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde")] 2 | 3 | use core::hash::BuildHasherDefault; 4 | use fnv::FnvHasher; 5 | 6 | use ritelinked::{LinkedHashMap, LinkedHashSet}; 7 | use serde_test::{assert_tokens, Token}; 8 | 9 | type FnvHashMap = LinkedHashMap>; 10 | type FnvHashSet = LinkedHashSet>; 11 | 12 | #[test] 13 | fn map_serde_tokens_empty() { 14 | let map = FnvHashMap::::default(); 15 | 16 | assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); 17 | } 18 | 19 | #[test] 20 | fn map_serde_tokens() { 21 | let mut map = FnvHashMap::default(); 22 | map.insert('a', 10); 23 | map.insert('b', 20); 24 | map.insert('c', 30); 25 | 26 | assert_tokens( 27 | &map, 28 | &[ 29 | Token::Map { len: Some(3) }, 30 | Token::Char('a'), 31 | Token::I32(10), 32 | Token::Char('b'), 33 | Token::I32(20), 34 | Token::Char('c'), 35 | Token::I32(30), 36 | Token::MapEnd, 37 | ], 38 | ); 39 | } 40 | 41 | #[test] 42 | fn set_serde_tokens_empty() { 43 | let set = FnvHashSet::::default(); 44 | 45 | assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]); 46 | } 47 | 48 | #[test] 49 | fn set_serde_tokens() { 50 | let mut set = FnvHashSet::default(); 51 | set.insert(10); 52 | set.insert(20); 53 | set.insert(30); 54 | 55 | assert_tokens( 56 | &set, 57 | &[ 58 | Token::Seq { len: Some(3) }, 59 | Token::I32(10), 60 | Token::I32(20), 61 | Token::I32(30), 62 | Token::SeqEnd, 63 | ], 64 | ); 65 | } 66 | --------------------------------------------------------------------------------