├── .gitignore ├── src ├── tests │ ├── heapsize.rs │ ├── serde.rs │ └── mod.rs ├── heapsize.rs ├── serde.rs └── lib.rs ├── Cargo.toml ├── README.md ├── LICENSE-MIT ├── .github └── workflows │ └── rust.yml └── LICENSE-APACHE /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /src/tests/heapsize.rs: -------------------------------------------------------------------------------- 1 | #![cfg(all(feature = "heapsize_impl", not(miri)))] 2 | 3 | extern crate heapsize; 4 | extern crate linked_hash_map; 5 | 6 | use heapsize::HeapSizeOf; 7 | use linked_hash_map::LinkedHashMap; 8 | 9 | #[test] 10 | fn empty() { 11 | assert_eq!( 12 | LinkedHashMap::::new().heap_size_of_children(), 13 | 0 14 | ); 15 | } 16 | 17 | #[test] 18 | fn nonempty() { 19 | let mut map = LinkedHashMap::new(); 20 | map.insert("hello".to_string(), "world".to_string()); 21 | map.insert("hola".to_string(), "mundo".to_string()); 22 | map.insert("bonjour".to_string(), "monde".to_string()); 23 | map.remove("hello"); 24 | 25 | assert!(map.heap_size_of_children() != 0); 26 | } 27 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "linked-hash-map" 4 | version = "0.5.6" 5 | license = "MIT/Apache-2.0" 6 | description = "A HashMap wrapper that holds key-value pairs in insertion order" 7 | authors = [ 8 | "Stepan Koltsov ", 9 | "Andrew Paseltiner ", 10 | ] 11 | 12 | repository = "https://github.com/contain-rs/linked-hash-map" 13 | homepage = "https://github.com/contain-rs/linked-hash-map" 14 | documentation = "https://docs.rs/linked-hash-map" 15 | keywords = ["data-structures"] 16 | readme = "README.md" 17 | exclude = [".github", "src/tests"] 18 | 19 | [features] 20 | nightly = [] 21 | serde_impl = ["serde"] 22 | heapsize_impl = ["heapsize"] 23 | 24 | [dependencies] 25 | serde = { version = "1.0", optional = true } 26 | heapsize = { version = "0.4", optional = true } 27 | 28 | [dev-dependencies] 29 | serde_test = { version = "1.0" } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Rust CI](https://github.com/contain-rs/linked-hash-map/workflows/Rust/badge.svg?branch=master) [![crates.io](https://img.shields.io/crates/v/linked-hash-map.svg)](https://crates.io/crates/linked-hash-map) [![](https://docs.rs/linked-hash-map/badge.svg)](https://docs.rs/linked-hash-map) 2 | 3 | 4 | **WARNING: THIS PROJECT IS IN MAINTENANCE MODE, DUE TO INSUFFICIENT MAINTAINER RESOURCES** 5 | 6 | It works fine, but will generally no longer be improved. 7 | 8 | We are currently only accepting changes which: 9 | 10 | * fix correctness issues 11 | * keep this compiling with the latest versions of Rust or its dependencies. 12 | * have minimal review requirements, such as documentation changes (so not totally new APIs). 13 | 14 | ------ 15 | 16 | 17 | A HashMap wrapper that holds key-value pairs in insertion order. 18 | 19 | Documentation is available at https://docs.rs/linked-hash-map. 20 | -------------------------------------------------------------------------------- /src/tests/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde_impl")] 2 | 3 | extern crate linked_hash_map; 4 | use linked_hash_map::LinkedHashMap; 5 | 6 | extern crate serde_test; 7 | use serde_test::{assert_tokens, Token}; 8 | 9 | #[test] 10 | fn test_ser_de_empty() { 11 | let map = LinkedHashMap::::new(); 12 | 13 | assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); 14 | } 15 | 16 | #[test] 17 | fn test_ser_de() { 18 | let mut map = LinkedHashMap::new(); 19 | map.insert('b', 20); 20 | map.insert('a', 10); 21 | map.insert('c', 30); 22 | 23 | assert_tokens( 24 | &map, 25 | &[ 26 | Token::Map { len: Some(3) }, 27 | Token::Char('b'), 28 | Token::I32(20), 29 | Token::Char('a'), 30 | Token::I32(10), 31 | Token::Char('c'), 32 | Token::I32(30), 33 | Token::MapEnd, 34 | ], 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /src/heapsize.rs: -------------------------------------------------------------------------------- 1 | extern crate heapsize; 2 | 3 | use self::heapsize::{heap_size_of, HeapSizeOf}; 4 | use std::hash::{BuildHasher, Hash}; 5 | 6 | use {KeyRef, LinkedHashMap, Node}; 7 | 8 | impl HeapSizeOf for KeyRef { 9 | fn heap_size_of_children(&self) -> usize { 10 | 0 11 | } 12 | } 13 | 14 | impl HeapSizeOf for Node 15 | where 16 | K: HeapSizeOf, 17 | V: HeapSizeOf, 18 | { 19 | fn heap_size_of_children(&self) -> usize { 20 | self.key.heap_size_of_children() + self.value.heap_size_of_children() 21 | } 22 | } 23 | 24 | impl HeapSizeOf for LinkedHashMap 25 | where 26 | K: HeapSizeOf + Hash + Eq, 27 | V: HeapSizeOf, 28 | S: BuildHasher, 29 | { 30 | fn heap_size_of_children(&self) -> usize { 31 | unsafe { 32 | let mut size = self.map.heap_size_of_children(); 33 | for &value in self.map.values() { 34 | size += (*value).heap_size_of_children(); 35 | size += heap_size_of(value as *const _ as *const _); 36 | } 37 | 38 | if !self.head.is_null() { 39 | size += heap_size_of(self.head as *const _ as *const _); 40 | } 41 | 42 | let mut free = self.free; 43 | while !free.is_null() { 44 | size += heap_size_of(free as *const _ as *const _); 45 | free = (*free).next 46 | } 47 | 48 | size 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Build 18 | run: cargo build --verbose 19 | - name: Run tests 20 | run: cargo test --verbose 21 | - name: Run tests (no features) 22 | run: cargo test --no-default-features --verbose 23 | - name: Run tests (all features) 24 | run: cargo test --verbose --features=serde_impl,heapsize_impl 25 | 26 | miri: 27 | name: "Miri" 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v2 31 | - name: Install Miri 32 | run: | 33 | rustup toolchain install nightly --component miri 34 | rustup override set nightly 35 | cargo miri setup 36 | - name: Test with Miri 37 | run: MIRIFLAGS=-Zmiri-strict-provenance cargo miri test 38 | - name: Test with Miri (all features) 39 | run: MIRIFLAGS=-Zmiri-strict-provenance cargo miri test --all-features 40 | - name: Test with Miri (no features) 41 | run: MIRIFLAGS=-Zmiri-strict-provenance cargo miri test --no-default-features 42 | 43 | fmt: 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v2 47 | - uses: actions-rs/toolchain@v1 48 | with: 49 | toolchain: stable 50 | profile: minimal 51 | components: rustfmt 52 | override: true 53 | - uses: actions-rs/cargo@v1 54 | with: 55 | command: fmt 56 | args: --all -- --check 57 | 58 | 59 | clippy: 60 | runs-on: ubuntu-latest 61 | steps: 62 | - uses: actions/checkout@v2 63 | - uses: actions-rs/toolchain@v1 64 | with: 65 | toolchain: stable 66 | profile: minimal 67 | components: clippy 68 | override: true 69 | - uses: actions-rs/clippy-check@v1 70 | env: 71 | PWD: ${{ env.GITHUB_WORKSPACE }} 72 | with: 73 | token: ${{ secrets.GITHUB_TOKEN }} 74 | args: --workspace --tests --examples 75 | 76 | 77 | docs: 78 | runs-on: ubuntu-latest 79 | env: 80 | RUSTDOCFLAGS: -Dwarnings 81 | steps: 82 | - uses: actions/checkout@v2 83 | - uses: actions-rs/toolchain@v1 84 | with: 85 | toolchain: stable 86 | profile: minimal 87 | components: rust-docs 88 | override: true 89 | - uses: swatinem/rust-cache@v1 90 | - uses: actions-rs/cargo@v1 91 | with: 92 | command: doc 93 | args: --workspace --no-deps 94 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | //! An optional implementation of serialization/deserialization. 2 | 3 | extern crate serde; 4 | 5 | use std::fmt::{Formatter, Result as FmtResult}; 6 | use std::hash::{BuildHasher, Hash}; 7 | use std::marker::PhantomData; 8 | 9 | use super::LinkedHashMap; 10 | 11 | use self::serde::de::{Error, MapAccess, Visitor}; 12 | use self::serde::ser::SerializeMap; 13 | use self::serde::{Deserialize, Deserializer, Serialize, Serializer}; 14 | 15 | impl Serialize for LinkedHashMap 16 | where 17 | K: Serialize + Eq + Hash, 18 | V: Serialize, 19 | S: BuildHasher, 20 | { 21 | #[inline] 22 | fn serialize(&self, serializer: T) -> Result 23 | where 24 | T: Serializer, 25 | { 26 | let mut map_serializer = serializer.serialize_map(Some(self.len()))?; 27 | for (k, v) in self { 28 | map_serializer.serialize_key(k)?; 29 | map_serializer.serialize_value(v)?; 30 | } 31 | map_serializer.end() 32 | } 33 | } 34 | 35 | #[derive(Debug)] 36 | /// `serde::de::Visitor` for a linked hash map. 37 | pub struct LinkedHashMapVisitor { 38 | marker: PhantomData>, 39 | } 40 | 41 | impl LinkedHashMapVisitor { 42 | /// Creates a new visitor for a linked hash map. 43 | pub fn new() -> Self { 44 | LinkedHashMapVisitor { 45 | marker: PhantomData, 46 | } 47 | } 48 | } 49 | 50 | impl Default for LinkedHashMapVisitor { 51 | fn default() -> Self { 52 | LinkedHashMapVisitor::new() 53 | } 54 | } 55 | 56 | impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor 57 | where 58 | K: Deserialize<'de> + Eq + Hash, 59 | V: Deserialize<'de>, 60 | { 61 | type Value = LinkedHashMap; 62 | 63 | fn expecting(&self, formatter: &mut Formatter) -> FmtResult { 64 | write!(formatter, "a map") 65 | } 66 | 67 | #[inline] 68 | fn visit_unit(self) -> Result 69 | where 70 | E: Error, 71 | { 72 | Ok(LinkedHashMap::new()) 73 | } 74 | 75 | #[inline] 76 | fn visit_map(self, mut map: M) -> Result 77 | where 78 | M: MapAccess<'de>, 79 | { 80 | let mut values = LinkedHashMap::with_capacity(map.size_hint().unwrap_or(0)); 81 | 82 | while let Some((key, value)) = map.next_entry()? { 83 | values.insert(key, value); 84 | } 85 | 86 | Ok(values) 87 | } 88 | } 89 | 90 | impl<'de, K, V> Deserialize<'de> for LinkedHashMap 91 | where 92 | K: Deserialize<'de> + Eq + Hash, 93 | V: Deserialize<'de>, 94 | { 95 | fn deserialize(deserializer: D) -> Result, D::Error> 96 | where 97 | D: Deserializer<'de>, 98 | { 99 | deserializer.deserialize_map(LinkedHashMapVisitor::new()) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::needless_collect)] 2 | #![allow(clippy::iter_cloned_collect)] 3 | 4 | use crate::{Entry, LinkedHashMap}; 5 | 6 | fn assert_opt_eq(opt: Option<&V>, v: V) { 7 | assert!(opt.is_some()); 8 | assert!(opt.unwrap() == &v); 9 | } 10 | 11 | #[test] 12 | fn test_insert_and_get() { 13 | let mut map = LinkedHashMap::new(); 14 | map.insert(1, 10); 15 | map.insert(2, 20); 16 | assert_opt_eq(map.get(&1), 10); 17 | assert_opt_eq(map.get(&2), 20); 18 | assert_eq!(map.len(), 2); 19 | } 20 | 21 | #[test] 22 | fn test_index() { 23 | let mut map = LinkedHashMap::new(); 24 | map.insert(1, 10); 25 | map.insert(2, 20); 26 | assert_eq!(10, map[&1]); 27 | map[&2] = 22; 28 | assert_eq!(22, map[&2]); 29 | } 30 | 31 | #[test] 32 | fn test_insert_update() { 33 | let mut map = LinkedHashMap::new(); 34 | map.insert("1".to_string(), vec![10, 10]); 35 | map.insert("1".to_string(), vec![10, 19]); 36 | assert_opt_eq(map.get(&"1".to_string()), vec![10, 19]); 37 | assert_eq!(map.len(), 1); 38 | } 39 | 40 | #[test] 41 | fn test_entry_insert_vacant() { 42 | let mut map = LinkedHashMap::new(); 43 | match map.entry("1".to_string()) { 44 | Entry::Vacant(e) => { 45 | assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]); 46 | } 47 | _ => panic!("fail"), 48 | } 49 | assert!(map.contains_key("1")); 50 | assert_eq!(map["1"], vec![10, 10]); 51 | 52 | match map.entry("1".to_string()) { 53 | Entry::Occupied(mut e) => { 54 | assert_eq!(*e.get(), vec![10, 10]); 55 | assert_eq!(e.insert(vec![10, 16]), vec![10, 10]); 56 | } 57 | _ => panic!("fail"), 58 | } 59 | 60 | assert!(map.contains_key("1")); 61 | assert_eq!(map["1"], vec![10, 16]); 62 | 63 | match map.entry("1".to_string()) { 64 | Entry::Occupied(e) => { 65 | assert_eq!(e.remove(), vec![10, 16]); 66 | } 67 | _ => panic!("fail"), 68 | } 69 | } 70 | 71 | #[test] 72 | fn test_entry_or_default() { 73 | let mut map = LinkedHashMap::>::new(); 74 | map.entry("hello".to_string()).or_default().push(4); 75 | map.entry("hello".to_string()).or_default().push(5); 76 | map.entry("hello".to_string()).or_default().push(8); 77 | 78 | map.entry("bye".to_string()).or_default().push(9); 79 | 80 | map.entry("there".to_string()).or_default(); 81 | 82 | assert_eq!(map["hello"], &[4, 5, 8]); 83 | assert_eq!(map["bye"], &[9]); 84 | assert_eq!(map["there"], &[]); 85 | } 86 | 87 | #[test] 88 | fn test_entry_and_modify() { 89 | let mut map = LinkedHashMap::>::new(); 90 | map.entry("hello".to_string()) 91 | .and_modify(|v| v.push(3)) 92 | .or_default(); 93 | map.entry("hello".to_string()) 94 | .and_modify(|v| v.push(4)) 95 | .or_default(); 96 | map.entry("hello".to_string()) 97 | .and_modify(|v| v.push(5)) 98 | .or_default(); 99 | 100 | map.entry("bye".to_string()).or_default(); 101 | 102 | map.entry("bye".to_string()) 103 | .and_modify(|v| v.push(3)) 104 | .and_modify(|v| v.push(4)) 105 | .and_modify(|v| v.push(5)); 106 | 107 | map.entry("there".to_string()).and_modify(|v| v.push(3)); 108 | 109 | assert_eq!(map["hello"], &[4, 5]); 110 | assert_eq!(map["bye"], &[3, 4, 5]); 111 | assert_eq!(map.get("there"), None); 112 | } 113 | 114 | #[test] 115 | fn test_entries_replacing() { 116 | let mut map = LinkedHashMap::new(); 117 | map.insert("a", 10); 118 | 119 | { 120 | let mut iter = map.entries(); 121 | let mut entry = iter.next().unwrap(); 122 | assert_eq!(entry.insert(20), 10); 123 | assert!(iter.next().is_none()); 124 | } 125 | 126 | assert_eq!(map["a"], 20); 127 | } 128 | 129 | #[test] 130 | fn test_entries_remove() { 131 | let mut map = LinkedHashMap::new(); 132 | map.insert("a", 10); 133 | map.insert("b", 20); 134 | map.insert("c", 30); 135 | map.insert("d", 40); 136 | 137 | // remove middle 138 | { 139 | let mut iter = map.entries(); 140 | iter.next().unwrap(); 141 | let b = iter.next().unwrap(); 142 | assert_eq!(*b.key(), "b"); 143 | assert_eq!(b.remove(), 20); 144 | assert_eq!(*iter.next().unwrap().key(), "c"); 145 | } 146 | 147 | assert_eq!(map.len(), 3); 148 | assert_eq!(map["a"], 10); 149 | assert_eq!(map["c"], 30); 150 | assert_eq!(map["d"], 40); 151 | 152 | // remove first 153 | { 154 | let mut iter = map.entries(); 155 | let a = iter.next().unwrap(); 156 | assert_eq!(*a.key(), "a"); 157 | assert_eq!(a.remove(), 10); 158 | } 159 | 160 | assert_eq!(map.len(), 2); 161 | assert_eq!(map["c"], 30); 162 | assert_eq!(map["d"], 40); 163 | 164 | // remove last 165 | { 166 | let mut iter = map.entries(); 167 | iter.next().unwrap(); 168 | let d = iter.next().unwrap(); 169 | assert_eq!(*d.key(), "d"); 170 | assert_eq!(d.remove(), 40); 171 | assert!(iter.next().is_none()); 172 | } 173 | 174 | assert_eq!(map.len(), 1); 175 | assert_eq!(map["c"], 30); 176 | 177 | // remove only 178 | { 179 | let mut iter = map.entries(); 180 | let c = iter.next().unwrap(); 181 | assert_eq!(*c.key(), "c"); 182 | assert_eq!(c.remove(), 30); 183 | } 184 | 185 | assert!(map.is_empty()); 186 | } 187 | #[test] 188 | fn entries_insert() { 189 | let mut map = LinkedHashMap::new(); 190 | map.insert(0, 0); 191 | map.insert(1, 1); 192 | 193 | let mut iter = map.entries(); 194 | 195 | iter.next().unwrap().insert(0); 196 | iter.next().unwrap(); // 1 197 | assert!(iter.next().is_none()); 198 | } 199 | 200 | #[test] 201 | fn test_debug() { 202 | let mut map = LinkedHashMap::new(); 203 | assert_eq!(format!("{:?}", map), "{}"); 204 | map.insert(1, 10); 205 | map.insert(2, 20); 206 | map.insert(3, 30); 207 | assert_eq!(format!("{:?}", map), "{1: 10, 2: 20, 3: 30}"); 208 | map.insert(2, 22); 209 | assert_eq!(format!("{:?}", map), "{1: 10, 3: 30, 2: 22}"); 210 | map.get(&3); 211 | assert_eq!(format!("{:?}", map), "{1: 10, 3: 30, 2: 22}"); 212 | map.get_refresh(&3); 213 | assert_eq!(format!("{:?}", map), "{1: 10, 2: 22, 3: 30}"); 214 | map.clear(); 215 | assert_eq!(format!("{:?}", map), "{}"); 216 | } 217 | 218 | #[test] 219 | fn test_remove() { 220 | let mut map = LinkedHashMap::new(); 221 | map.insert(1, 10); 222 | map.insert(2, 20); 223 | map.insert(3, 30); 224 | map.insert(4, 40); 225 | map.insert(5, 50); 226 | map.remove(&3); 227 | map.remove(&4); 228 | assert!(map.get(&3).is_none()); 229 | assert!(map.get(&4).is_none()); 230 | map.insert(6, 60); 231 | map.insert(7, 70); 232 | map.insert(8, 80); 233 | assert_opt_eq(map.get(&6), 60); 234 | assert_opt_eq(map.get(&7), 70); 235 | assert_opt_eq(map.get(&8), 80); 236 | } 237 | 238 | #[test] 239 | fn test_pop() { 240 | let mut map = LinkedHashMap::new(); 241 | map.insert(1, 10); 242 | map.insert(2, 20); 243 | map.insert(3, 30); 244 | map.insert(4, 40); 245 | map.insert(5, 50); 246 | assert_eq!(map.pop_front(), Some((1, 10))); 247 | assert!(map.get(&1).is_none()); 248 | assert_eq!(map.pop_back(), Some((5, 50))); 249 | assert!(map.get(&5).is_none()); 250 | map.insert(6, 60); 251 | map.insert(7, 70); 252 | map.insert(8, 80); 253 | assert_eq!(map.pop_front(), Some((2, 20))); 254 | assert!(map.get(&2).is_none()); 255 | assert_eq!(map.pop_back(), Some((8, 80))); 256 | assert!(map.get(&8).is_none()); 257 | map.insert(3, 30); 258 | assert_eq!(map.pop_front(), Some((4, 40))); 259 | assert!(map.get(&4).is_none()); 260 | assert_eq!(map.pop_back(), Some((3, 30))); 261 | assert!(map.get(&3).is_none()); 262 | } 263 | 264 | #[test] 265 | fn test_clear() { 266 | let mut map = LinkedHashMap::new(); 267 | map.insert(1, 10); 268 | map.insert(2, 20); 269 | map.clear(); 270 | assert!(map.get(&1).is_none()); 271 | assert!(map.get(&2).is_none()); 272 | assert_eq!(format!("{:?}", map), "{}"); 273 | } 274 | 275 | #[test] 276 | fn test_iter() { 277 | let mut map = LinkedHashMap::new(); 278 | 279 | // empty iter 280 | assert_eq!(None, map.iter().next()); 281 | 282 | map.insert("a", 10); 283 | map.insert("b", 20); 284 | map.insert("c", 30); 285 | 286 | // regular iter 287 | let mut iter = map.iter(); 288 | assert_eq!((&"a", &10), iter.next().unwrap()); 289 | assert_eq!((&"b", &20), iter.next().unwrap()); 290 | assert_eq!((&"c", &30), iter.next().unwrap()); 291 | assert_eq!(None, iter.next()); 292 | assert_eq!(None, iter.next()); 293 | 294 | // reversed iter 295 | let mut rev_iter = map.iter().rev(); 296 | assert_eq!((&"c", &30), rev_iter.next().unwrap()); 297 | assert_eq!((&"b", &20), rev_iter.next().unwrap()); 298 | assert_eq!((&"a", &10), rev_iter.next().unwrap()); 299 | assert_eq!(None, rev_iter.next()); 300 | assert_eq!(None, rev_iter.next()); 301 | 302 | // mixed 303 | let mut mixed_iter = map.iter(); 304 | assert_eq!((&"a", &10), mixed_iter.next().unwrap()); 305 | assert_eq!((&"c", &30), mixed_iter.next_back().unwrap()); 306 | assert_eq!((&"b", &20), mixed_iter.next().unwrap()); 307 | assert_eq!(None, mixed_iter.next()); 308 | assert_eq!(None, mixed_iter.next_back()); 309 | } 310 | 311 | #[test] 312 | fn test_iter_mut() { 313 | let mut map = LinkedHashMap::new(); 314 | map.insert("a", 10); 315 | map.insert("c", 30); 316 | map.insert("b", 20); 317 | 318 | { 319 | let mut iter = map.iter_mut(); 320 | let entry = iter.next().unwrap(); 321 | assert_eq!(&"a", entry.0); 322 | *entry.1 = 17; 323 | 324 | // reverse iterator 325 | let mut iter = iter.rev(); 326 | let entry = iter.next().unwrap(); 327 | assert_eq!(&"b", entry.0); 328 | *entry.1 = 23; 329 | 330 | let entry = iter.next().unwrap(); 331 | assert_eq!(&"c", entry.0); 332 | assert_eq!(None, iter.next()); 333 | assert_eq!(None, iter.next()); 334 | } 335 | 336 | assert_eq!(17, map[&"a"]); 337 | assert_eq!(23, map[&"b"]); 338 | } 339 | 340 | #[test] 341 | fn test_consuming_iter() { 342 | let map = { 343 | let mut map = LinkedHashMap::new(); 344 | map.insert("a", 10); 345 | map.insert("c", 30); 346 | map.insert("b", 20); 347 | map 348 | }; 349 | 350 | let mut iter = map.into_iter(); 351 | assert_eq!(Some(("a", 10)), iter.next()); 352 | 353 | let clone = iter.clone(); 354 | for iter in &mut [iter, clone] { 355 | assert_eq!(Some(("b", 20)), iter.next_back()); 356 | assert_eq!(1, iter.len()); 357 | assert_eq!(Some(("c", 30)), iter.next()); 358 | assert_eq!(None, iter.next()); 359 | } 360 | } 361 | 362 | #[test] 363 | fn test_consuming_iter_empty() { 364 | let map = LinkedHashMap::<&str, i32>::new(); 365 | let mut iter = map.into_iter(); 366 | assert_eq!(None, iter.next()); 367 | let mut clone = iter.clone(); 368 | assert_eq!(None, clone.next()); 369 | } 370 | 371 | #[test] 372 | fn test_consuming_iter_with_free_list() { 373 | let mut map = LinkedHashMap::new(); 374 | map.insert("a", 10); 375 | map.insert("c", 30); 376 | map.insert("b", 20); 377 | map.remove("a"); 378 | map.remove("b"); 379 | 380 | let mut iter = map.into_iter(); 381 | assert_eq!(Some(("c", 30)), iter.next()); 382 | assert_eq!(None, iter.next()); 383 | } 384 | 385 | #[test] 386 | fn test_into_iter_drop() { 387 | struct Counter<'a>(&'a mut usize); 388 | 389 | impl<'a> Drop for Counter<'a> { 390 | fn drop(&mut self) { 391 | *self.0 += 1; 392 | } 393 | } 394 | 395 | let mut a = 0; 396 | let mut b = 0; 397 | let mut c = 0; 398 | 399 | { 400 | let mut map = LinkedHashMap::new(); 401 | map.insert("a", Counter(&mut a)); 402 | map.insert("b", Counter(&mut b)); 403 | map.insert("c", Counter(&mut c)); 404 | 405 | let mut iter = map.into_iter(); 406 | iter.next(); 407 | iter.next_back(); 408 | } 409 | 410 | assert_eq!(a, 1); 411 | assert_eq!(b, 1); 412 | assert_eq!(c, 1); 413 | } 414 | 415 | #[test] 416 | fn test_drain() { 417 | let data = [("a", 1), ("b", 2), ("c", 3), ("d", 4)]; 418 | 419 | let mut map = data.iter().copied().collect::>(); 420 | assert_eq!(map.len(), 4); 421 | let mut iter = map.drain(); 422 | assert_eq!(iter.size_hint(), (4, Some(4))); 423 | assert_eq!(iter.next(), Some(("a", 1))); 424 | assert_eq!(iter.size_hint(), (3, Some(3))); 425 | assert_eq!(iter.next(), Some(("b", 2))); 426 | assert_eq!(iter.size_hint(), (2, Some(2))); 427 | assert_eq!(iter.next(), Some(("c", 3))); 428 | assert_eq!(iter.size_hint(), (1, Some(1))); 429 | assert_eq!(iter.next(), Some(("d", 4))); 430 | assert_eq!(iter.size_hint(), (0, Some(0))); 431 | assert_eq!(iter.next(), None); 432 | assert_eq!(iter.size_hint(), (0, Some(0))); 433 | assert_eq!(iter.next(), None); 434 | assert_eq!(iter.size_hint(), (0, Some(0))); 435 | assert_eq!(iter.next_back(), None); 436 | assert_eq!(iter.size_hint(), (0, Some(0))); 437 | drop(iter); 438 | assert_eq!(map.len(), 0); 439 | 440 | map.extend(data.iter().copied()); 441 | assert_eq!(map.len(), 4); 442 | let mut iter = map.drain(); 443 | assert_eq!(iter.size_hint(), (4, Some(4))); 444 | assert_eq!(iter.next_back(), Some(("d", 4))); 445 | assert_eq!(iter.size_hint(), (3, Some(3))); 446 | assert_eq!(iter.next_back(), Some(("c", 3))); 447 | assert_eq!(iter.size_hint(), (2, Some(2))); 448 | assert_eq!(iter.next_back(), Some(("b", 2))); 449 | assert_eq!(iter.size_hint(), (1, Some(1))); 450 | assert_eq!(iter.next_back(), Some(("a", 1))); 451 | assert_eq!(iter.size_hint(), (0, Some(0))); 452 | assert_eq!(iter.next_back(), None); 453 | assert_eq!(iter.next_back(), None); 454 | assert_eq!(iter.next(), None); 455 | drop(iter); 456 | assert_eq!(map.len(), 0); 457 | 458 | map.extend(data.iter().rev().copied()); 459 | assert!(map.insert("e", 5).is_none()); 460 | assert!(map.insert("f", 6).is_none()); 461 | assert_eq!(map.len(), 6); 462 | assert_eq!(map.remove("b"), Some(2)); 463 | assert!(map.get("b").is_none()); 464 | assert_eq!(map.len(), 5); 465 | let mut iter = map.drain(); 466 | assert_eq!(iter.size_hint(), (5, Some(5))); 467 | assert_eq!(iter.next(), Some(("d", 4))); 468 | assert_eq!(iter.next(), Some(("c", 3))); 469 | assert_eq!(iter.next_back(), Some(("f", 6))); 470 | assert_eq!(iter.next(), Some(("a", 1))); 471 | assert_eq!(iter.next(), Some(("e", 5))); 472 | assert_eq!(iter.next(), None); 473 | assert_eq!(iter.next(), None); 474 | drop(iter); 475 | assert_eq!(map.len(), 0); 476 | 477 | map.insert("g", 2); 478 | assert_eq!(map.get("g"), Some(&2)); 479 | assert_eq!(map.len(), 1); 480 | } 481 | 482 | #[test] 483 | fn test_drain_corners() { 484 | { 485 | let mut map = LinkedHashMap::::new(); 486 | assert_eq!(map.len(), 0); 487 | assert_eq!(map.drain().collect::>(), vec![]); 488 | assert_eq!(map.len(), 0); 489 | assert!(map.is_empty()); 490 | assert!(map.iter().collect::>().is_empty()); 491 | } 492 | { 493 | let mut map = LinkedHashMap::::new(); 494 | assert_eq!(map.drain().rev().size_hint(), (0, Some(0))); 495 | assert!(map.into_iter().collect::>().is_empty()); 496 | } 497 | { 498 | let mut map = LinkedHashMap::::new(); 499 | assert_eq!(map.drain().size_hint(), (0, Some(0))); 500 | assert_eq!(map.len(), 0); 501 | assert!(map.is_empty()); 502 | assert!(map.iter_mut().collect::>().is_empty()); 503 | } 504 | { 505 | let mut map = LinkedHashMap::new(); 506 | map.insert("a", 1); 507 | assert_eq!(map.len(), 1); 508 | assert_eq!(map.drain().collect::>(), vec![("a", 1)]); 509 | assert_eq!(map.len(), 0); 510 | assert!(map.get("a").is_none()); 511 | } 512 | { 513 | let mut map = LinkedHashMap::new(); 514 | map.insert("b", 2); 515 | assert_eq!(map.len(), 1); 516 | assert_eq!(map.drain().rev().collect::>(), vec![("b", 2)]); 517 | assert!(map.into_iter().rev().collect::>().is_empty()); 518 | } 519 | { 520 | let mut map = LinkedHashMap::new(); 521 | map.insert("c", 3); 522 | map.insert("d", 4); 523 | assert_eq!(map.len(), 2); 524 | assert_eq!(map.drain().collect::>(), vec![("c", 3), ("d", 4)]); 525 | } 526 | { 527 | let mut map = LinkedHashMap::new(); 528 | map.insert("e", 5); 529 | map.insert("f", 6); 530 | assert_eq!(map.len(), 2); 531 | assert_eq!( 532 | map.drain().rev().collect::>(), 533 | vec![("f", 6), ("e", 5)] 534 | ); 535 | } 536 | { 537 | let mut map = LinkedHashMap::new(); 538 | map.insert("e", 5); 539 | assert_eq!(map.remove("e"), Some(5)); 540 | assert_eq!(map.len(), 0); 541 | let iter = map.drain(); 542 | assert_eq!(iter.size_hint(), (0, Some(0))); 543 | assert_eq!(iter.collect::>(), vec![]); 544 | assert_eq!(map.len(), 0); 545 | assert!(map.is_empty()); 546 | assert!(map.iter_mut().rev().collect::>().is_empty()); 547 | } 548 | { 549 | let mut map = LinkedHashMap::new(); 550 | map.insert("e", 5); 551 | assert_eq!(map.remove("e"), Some(5)); 552 | assert_eq!(map.len(), 0); 553 | let iter = map.drain().rev(); 554 | assert_eq!(iter.size_hint(), (0, Some(0))); 555 | assert_eq!(iter.collect::>(), vec![]); 556 | assert_eq!(map.len(), 0); 557 | assert!(map.is_empty()); 558 | assert!(map.iter_mut().rev().collect::>().is_empty()); 559 | } 560 | { 561 | let mut map = LinkedHashMap::new(); 562 | map.insert("e", 5); 563 | assert_eq!(map.remove("e"), Some(5)); 564 | assert_eq!(map.len(), 0); 565 | assert_eq!(map.drain().collect::>(), vec![]); 566 | assert_eq!(map.len(), 0); 567 | assert!(map.into_iter().rev().collect::>().is_empty()); 568 | } 569 | { 570 | let mut map = LinkedHashMap::new(); 571 | map.insert("e", 5); 572 | assert_eq!(map.remove("e"), Some(5)); 573 | assert_eq!(map.len(), 0); 574 | assert_eq!(map.drain().rev().collect::>(), vec![]); 575 | assert_eq!(map.len(), 0); 576 | assert!(map.into_iter().collect::>().is_empty()); 577 | } 578 | } 579 | 580 | #[test] 581 | fn test_drain_forget() { 582 | let data = [("a", 1), ("b", 2), ("c", 3), ("d", 4)]; 583 | 584 | let mut map = data.iter().copied().collect::>(); 585 | assert_eq!(map.len(), 4); 586 | let iter = map.drain(); 587 | std::mem::forget(iter); 588 | assert_eq!(map.len(), 0); 589 | assert!(map.get("a").is_none()); 590 | assert!(map.get("b").is_none()); 591 | assert!(map.iter().collect::>().is_empty()); 592 | assert!(map.iter().rev().collect::>().is_empty()); 593 | 594 | map.extend(data.iter().copied()); 595 | let mut iter = map.drain(); 596 | assert_eq!(iter.next(), Some(("a", 1))); 597 | std::mem::forget(iter); 598 | assert_eq!(map.len(), 0); 599 | assert!(map.get("a").is_none()); 600 | assert!(map.get("b").is_none()); 601 | assert!(map.iter_mut().collect::>().is_empty()); 602 | assert!(map.iter_mut().rev().collect::>().is_empty()); 603 | 604 | map.extend(data.iter().rev().copied()); 605 | let mut iter = map.drain(); 606 | assert_eq!(iter.next_back(), Some(("a", 1))); 607 | std::mem::forget(iter); 608 | assert_eq!(map.len(), 0); 609 | assert!(map.get("a").is_none()); 610 | assert!(map.get("b").is_none()); 611 | assert!(map.iter_mut().collect::>().is_empty()); 612 | assert!(map.iter_mut().rev().collect::>().is_empty()); 613 | 614 | map.extend(data.iter().rev().copied()); 615 | let mut iter = map.drain(); 616 | assert_eq!( 617 | iter.by_ref().collect::>(), 618 | data.iter().rev().copied().collect::>() 619 | ); 620 | std::mem::forget(iter); 621 | assert_eq!(map.len(), 0); 622 | assert!(map.get("a").is_none()); 623 | assert!(map.get("b").is_none()); 624 | assert!(map.iter_mut().collect::>().is_empty()); 625 | assert!(map.iter_mut().rev().collect::>().is_empty()); 626 | 627 | map.extend(data.iter().rev().copied()); 628 | let mut iter = map.drain(); 629 | assert_eq!( 630 | iter.by_ref().rev().collect::>(), 631 | data.iter().copied().collect::>() 632 | ); 633 | std::mem::forget(iter); 634 | assert_eq!(map.len(), 0); 635 | assert!(map.get("a").is_none()); 636 | assert!(map.get("b").is_none()); 637 | assert!(map.iter_mut().collect::>().is_empty()); 638 | assert!(map.iter_mut().rev().collect::>().is_empty()); 639 | } 640 | 641 | #[test] 642 | fn test_drain_drop() { 643 | struct Counter<'a>(&'a mut usize); 644 | 645 | impl<'a> Drop for Counter<'a> { 646 | fn drop(&mut self) { 647 | *self.0 += 1; 648 | } 649 | } 650 | 651 | let mut a = 0; 652 | let mut b = 0; 653 | let mut c = 0; 654 | 655 | { 656 | let mut map = LinkedHashMap::new(); 657 | map.insert("a", Counter(&mut a)); 658 | map.insert("b", Counter(&mut b)); 659 | map.insert("c", Counter(&mut c)); 660 | 661 | let mut iter = map.drain(); 662 | assert_eq!(iter.next().unwrap().0, "a"); 663 | assert_eq!(iter.next_back().unwrap().0, "c"); 664 | } 665 | 666 | assert_eq!(a, 1); 667 | assert_eq!(b, 1); 668 | assert_eq!(c, 1); 669 | 670 | { 671 | let mut map = LinkedHashMap::new(); 672 | map.insert("a", Counter(&mut a)); 673 | map.insert("b", Counter(&mut b)); 674 | map.insert("c", Counter(&mut c)); 675 | 676 | let _iter = map.drain(); 677 | } 678 | 679 | assert_eq!(a, 2); 680 | assert_eq!(b, 2); 681 | assert_eq!(c, 2); 682 | 683 | { 684 | let mut map = LinkedHashMap::new(); 685 | map.insert("a", Counter(&mut a)); 686 | map.insert("b", Counter(&mut b)); 687 | map.insert("c", Counter(&mut c)); 688 | 689 | let iter = map.drain(); 690 | std::mem::forget(iter); 691 | assert_eq!(map.len(), 0); 692 | 693 | assert!(map.is_empty()); 694 | let mut normal_iter = map.iter(); 695 | assert!(normal_iter.next().is_none()); 696 | assert!(normal_iter.next_back().is_none()); 697 | } 698 | 699 | assert_eq!(a, 2); 700 | assert_eq!(b, 2); 701 | assert_eq!(c, 2); 702 | 703 | { 704 | let mut map = LinkedHashMap::new(); 705 | map.insert("a", Counter(&mut a)); 706 | map.insert("b", Counter(&mut b)); 707 | map.insert("c", Counter(&mut c)); 708 | 709 | let iter = map.drain(); 710 | std::mem::forget(iter); 711 | 712 | assert_eq!(map.len(), 0); 713 | let mut normal_iter = map.iter(); 714 | assert!(normal_iter.next().is_none()); 715 | assert!(normal_iter.next_back().is_none()); 716 | } 717 | 718 | assert_eq!(a, 2); 719 | assert_eq!(b, 2); 720 | assert_eq!(c, 2); 721 | 722 | { 723 | let mut map = LinkedHashMap::new(); 724 | map.insert("a", Counter(&mut a)); 725 | map.insert("b", Counter(&mut b)); 726 | map.insert("c", Counter(&mut c)); 727 | 728 | let iter = map.drain(); 729 | for _ in iter {} 730 | } 731 | 732 | assert_eq!(a, 3); 733 | assert_eq!(b, 3); 734 | assert_eq!(c, 3); 735 | 736 | { 737 | let mut map = LinkedHashMap::new(); 738 | map.insert("a", Counter(&mut a)); 739 | map.insert("b", Counter(&mut b)); 740 | map.insert("c", Counter(&mut c)); 741 | 742 | let iter = map.drain(); 743 | for _ in iter.rev() {} 744 | } 745 | 746 | assert_eq!(a, 4); 747 | assert_eq!(b, 4); 748 | assert_eq!(c, 4); 749 | 750 | { 751 | let mut map = LinkedHashMap::new(); 752 | map.insert("a", Counter(&mut a)); 753 | map.insert("b", Counter(&mut b)); 754 | map.insert("c", Counter(&mut c)); 755 | 756 | let mut iter = map.drain(); 757 | assert!(iter.next().is_some()); 758 | std::mem::forget(iter); 759 | } 760 | 761 | assert_eq!(a, 5); 762 | assert_eq!(b, 4); 763 | assert_eq!(c, 4); 764 | 765 | { 766 | let mut map = LinkedHashMap::new(); 767 | map.insert("a", Counter(&mut a)); 768 | map.insert("b", Counter(&mut b)); 769 | map.insert("c", Counter(&mut c)); 770 | 771 | let mut iter = map.drain(); 772 | assert!(iter.next_back().is_some()); 773 | std::mem::forget(iter); 774 | } 775 | 776 | assert_eq!(a, 5); 777 | assert_eq!(b, 4); 778 | assert_eq!(c, 5); 779 | } 780 | 781 | #[test] 782 | fn test_borrow() { 783 | #[derive(PartialEq, Eq, Hash)] 784 | struct Foo(Bar); 785 | #[derive(PartialEq, Eq, Hash)] 786 | struct Bar(i32); 787 | 788 | impl ::std::borrow::Borrow for Foo { 789 | fn borrow(&self) -> &Bar { 790 | &self.0 791 | } 792 | } 793 | 794 | let mut map = LinkedHashMap::new(); 795 | map.insert(Foo(Bar(1)), "a"); 796 | map.insert(Foo(Bar(2)), "b"); 797 | 798 | assert!(map.contains_key(&Bar(1))); 799 | assert!(map.contains_key(&Bar(2))); 800 | assert!(map.contains_key(&Foo(Bar(1)))); 801 | assert!(map.contains_key(&Foo(Bar(2)))); 802 | 803 | assert_eq!(map.get(&Bar(1)), Some(&"a")); 804 | assert_eq!(map.get(&Bar(2)), Some(&"b")); 805 | assert_eq!(map.get(&Foo(Bar(1))), Some(&"a")); 806 | assert_eq!(map.get(&Foo(Bar(2))), Some(&"b")); 807 | 808 | assert_eq!(map.get_refresh(&Bar(1)), Some(&mut "a")); 809 | assert_eq!(map.get_refresh(&Bar(2)), Some(&mut "b")); 810 | assert_eq!(map.get_refresh(&Foo(Bar(1))), Some(&mut "a")); 811 | assert_eq!(map.get_refresh(&Foo(Bar(2))), Some(&mut "b")); 812 | 813 | assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a")); 814 | assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b")); 815 | assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a")); 816 | assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b")); 817 | 818 | assert_eq!(map[&Bar(1)], "a"); 819 | assert_eq!(map[&Bar(2)], "b"); 820 | assert_eq!(map[&Foo(Bar(1))], "a"); 821 | assert_eq!(map[&Foo(Bar(2))], "b"); 822 | 823 | assert_eq!(map.remove(&Bar(1)), Some("a")); 824 | assert_eq!(map.remove(&Bar(2)), Some("b")); 825 | assert_eq!(map.remove(&Foo(Bar(1))), None); 826 | assert_eq!(map.remove(&Foo(Bar(2))), None); 827 | } 828 | 829 | #[test] 830 | fn test_send_sync() { 831 | fn is_send_sync() {} 832 | 833 | is_send_sync::>(); 834 | is_send_sync::>(); 835 | is_send_sync::>(); 836 | is_send_sync::>(); 837 | is_send_sync::>(); 838 | is_send_sync::>(); 839 | is_send_sync::>(); 840 | } 841 | 842 | #[cfg(all(feature = "nightly", test, not(miri)))] 843 | mod bench { 844 | extern crate test; 845 | 846 | use super::LinkedHashMap; 847 | 848 | #[bench] 849 | fn not_recycled_cycling(b: &mut test::Bencher) { 850 | let mut hash_map = LinkedHashMap::with_capacity(1000); 851 | for i in 0usize..1000 { 852 | hash_map.insert(i, i); 853 | } 854 | b.iter(|| { 855 | for i in 0usize..1000 { 856 | hash_map.remove(&i); 857 | } 858 | hash_map.clear_free_list(); 859 | for i in 0usize..1000 { 860 | hash_map.insert(i, i); 861 | } 862 | }) 863 | } 864 | 865 | #[bench] 866 | fn recycled_cycling(b: &mut test::Bencher) { 867 | let mut hash_map = LinkedHashMap::with_capacity(1000); 868 | for i in 0usize..1000 { 869 | hash_map.insert(i, i); 870 | } 871 | b.iter(|| { 872 | for i in 0usize..1000 { 873 | hash_map.remove(&i); 874 | } 875 | for i in 0usize..1000 { 876 | hash_map.insert(i, i); 877 | } 878 | }) 879 | } 880 | } 881 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! A `HashMap` wrapper that holds key-value pairs in insertion order. 12 | //! 13 | //! # Examples 14 | //! 15 | //! ``` 16 | //! use linked_hash_map::LinkedHashMap; 17 | //! 18 | //! let mut map = LinkedHashMap::new(); 19 | //! map.insert(2, 20); 20 | //! map.insert(1, 10); 21 | //! map.insert(3, 30); 22 | //! assert_eq!(map[&1], 10); 23 | //! assert_eq!(map[&2], 20); 24 | //! assert_eq!(map[&3], 30); 25 | //! 26 | //! let items: Vec<(i32, i32)> = map.iter().map(|t| (*t.0, *t.1)).collect(); 27 | //! assert_eq!(items, [(2, 20), (1, 10), (3, 30)]); 28 | //! ``` 29 | 30 | #![forbid(missing_docs)] 31 | #![cfg_attr(all(feature = "nightly", test), feature(test))] 32 | 33 | // Optional Serde support 34 | #[cfg(feature = "serde_impl")] 35 | pub mod serde; 36 | // Optional Heapsize support 37 | #[cfg(feature = "heapsize_impl")] 38 | mod heapsize; 39 | #[cfg(test)] 40 | mod tests; 41 | 42 | use std::borrow::Borrow; 43 | use std::cmp::Ordering; 44 | use std::collections::hash_map::{self, HashMap}; 45 | use std::fmt; 46 | use std::hash::{BuildHasher, Hash, Hasher}; 47 | use std::iter; 48 | use std::marker; 49 | use std::mem; 50 | use std::ops::{Index, IndexMut}; 51 | use std::ptr::{self, addr_of_mut}; 52 | 53 | struct KeyRef { 54 | k: *const K, 55 | } 56 | 57 | struct Node { 58 | next: *mut Node, 59 | prev: *mut Node, 60 | key: K, 61 | value: V, 62 | } 63 | 64 | /// A linked hash map. 65 | pub struct LinkedHashMap { 66 | map: HashMap, *mut Node, S>, 67 | head: *mut Node, 68 | free: *mut Node, 69 | } 70 | 71 | impl Hash for KeyRef { 72 | fn hash(&self, state: &mut H) { 73 | unsafe { (*self.k).hash(state) } 74 | } 75 | } 76 | 77 | impl PartialEq for KeyRef { 78 | fn eq(&self, other: &Self) -> bool { 79 | unsafe { (*self.k).eq(&*other.k) } 80 | } 81 | } 82 | 83 | impl Eq for KeyRef {} 84 | 85 | // This type exists only to support borrowing `KeyRef`s, which cannot be borrowed to `Q` directly 86 | // due to conflicting implementations of `Borrow`. The layout of `&Qey` must be identical to 87 | // `&Q` in order to support transmuting in the `Qey::from_ref` method. 88 | #[derive(Hash, PartialEq, Eq)] 89 | #[repr(transparent)] 90 | struct Qey(Q); 91 | 92 | impl Qey { 93 | fn from_ref(q: &Q) -> &Self { 94 | unsafe { mem::transmute(q) } 95 | } 96 | } 97 | 98 | impl Borrow> for KeyRef 99 | where 100 | K: Borrow, 101 | { 102 | fn borrow(&self) -> &Qey { 103 | Qey::from_ref(unsafe { (*self.k).borrow() }) 104 | } 105 | } 106 | 107 | impl Node { 108 | fn new(k: K, v: V) -> Self { 109 | Node { 110 | key: k, 111 | value: v, 112 | next: ptr::null_mut(), 113 | prev: ptr::null_mut(), 114 | } 115 | } 116 | } 117 | 118 | // drop empty node without dropping its key and value 119 | unsafe fn drop_empty_node(the_box: *mut Node) { 120 | // Safety: 121 | // In this crate all `Node` is allocated via `Box` or `alloc`, and `Box` uses the 122 | // Global allocator for its allocation, 123 | // (https://doc.rust-lang.org/std/boxed/index.html#memory-layout) so we can safely 124 | // deallocate the pointer to `Node` by calling `dealloc` method 125 | let layout = std::alloc::Layout::new::>(); 126 | std::alloc::dealloc(the_box as *mut u8, layout); 127 | } 128 | 129 | impl LinkedHashMap { 130 | /// Creates a linked hash map. 131 | pub fn new() -> Self { 132 | Self::with_map(HashMap::new()) 133 | } 134 | 135 | /// Creates an empty linked hash map with the given initial capacity. 136 | pub fn with_capacity(capacity: usize) -> Self { 137 | Self::with_map(HashMap::with_capacity(capacity)) 138 | } 139 | } 140 | 141 | impl LinkedHashMap { 142 | #[inline] 143 | fn detach(&mut self, node: *mut Node) { 144 | unsafe { 145 | (*(*node).prev).next = (*node).next; 146 | (*(*node).next).prev = (*node).prev; 147 | } 148 | } 149 | 150 | #[inline] 151 | fn attach(&mut self, node: *mut Node) { 152 | unsafe { 153 | (*node).next = (*self.head).next; 154 | (*node).prev = self.head; 155 | (*self.head).next = node; 156 | (*(*node).next).prev = node; 157 | } 158 | } 159 | 160 | // Caller must check `!self.head.is_null()` 161 | unsafe fn drop_entries(&mut self) { 162 | let mut cur = (*self.head).next; 163 | while cur != self.head { 164 | let next = (*cur).next; 165 | Box::from_raw(cur); 166 | cur = next; 167 | } 168 | } 169 | 170 | fn clear_free_list(&mut self) { 171 | unsafe { 172 | let mut free = self.free; 173 | while !free.is_null() { 174 | let next_free = (*free).next; 175 | drop_empty_node(free); 176 | free = next_free; 177 | } 178 | self.free = ptr::null_mut(); 179 | } 180 | } 181 | 182 | fn ensure_guard_node(&mut self) { 183 | if self.head.is_null() { 184 | // allocate the guard node if not present 185 | unsafe { 186 | let node_layout = std::alloc::Layout::new::>(); 187 | self.head = std::alloc::alloc(node_layout) as *mut Node; 188 | (*self.head).next = self.head; 189 | (*self.head).prev = self.head; 190 | } 191 | } 192 | } 193 | } 194 | 195 | impl LinkedHashMap { 196 | fn with_map(map: HashMap, *mut Node, S>) -> Self { 197 | LinkedHashMap { 198 | map, 199 | head: ptr::null_mut(), 200 | free: ptr::null_mut(), 201 | } 202 | } 203 | 204 | /// Creates an empty linked hash map with the given initial hash builder. 205 | pub fn with_hasher(hash_builder: S) -> Self { 206 | Self::with_map(HashMap::with_hasher(hash_builder)) 207 | } 208 | 209 | /// Creates an empty linked hash map with the given initial capacity and hash builder. 210 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { 211 | Self::with_map(HashMap::with_capacity_and_hasher(capacity, hash_builder)) 212 | } 213 | 214 | /// Reserves capacity for at least `additional` more elements to be inserted into the map. The 215 | /// map may reserve more space to avoid frequent allocations. 216 | /// 217 | /// # Panics 218 | /// 219 | /// Panics if the new allocation size overflows `usize.` 220 | pub fn reserve(&mut self, additional: usize) { 221 | self.map.reserve(additional); 222 | } 223 | 224 | /// Shrinks the capacity of the map as much as possible. It will drop down as much as possible 225 | /// while maintaining the internal rules and possibly leaving some space in accordance with the 226 | /// resize policy. 227 | pub fn shrink_to_fit(&mut self) { 228 | self.map.shrink_to_fit(); 229 | self.clear_free_list(); 230 | } 231 | 232 | /// Gets the given key's corresponding entry in the map for in-place manipulation. 233 | /// 234 | /// # Examples 235 | /// 236 | /// ``` 237 | /// use linked_hash_map::LinkedHashMap; 238 | /// 239 | /// let mut letters = LinkedHashMap::new(); 240 | /// 241 | /// for ch in "a short treatise on fungi".chars() { 242 | /// let counter = letters.entry(ch).or_insert(0); 243 | /// *counter += 1; 244 | /// } 245 | /// 246 | /// assert_eq!(letters[&'s'], 2); 247 | /// assert_eq!(letters[&'t'], 3); 248 | /// assert_eq!(letters[&'u'], 1); 249 | /// assert_eq!(letters.get(&'y'), None); 250 | /// ``` 251 | pub fn entry(&mut self, k: K) -> Entry { 252 | let self_ptr: *mut Self = self; 253 | 254 | if let Some(entry) = self.map.get_mut(&KeyRef { k: &k }) { 255 | return Entry::Occupied(OccupiedEntry { 256 | entry: *entry, 257 | map: self_ptr, 258 | marker: marker::PhantomData, 259 | }); 260 | } 261 | 262 | Entry::Vacant(VacantEntry { key: k, map: self }) 263 | } 264 | 265 | /// Returns an iterator visiting all entries in insertion order. 266 | /// Iterator element type is `OccupiedEntry`. Allows for removal 267 | /// as well as replacing the entry. 268 | /// 269 | /// # Examples 270 | /// ``` 271 | /// use linked_hash_map::LinkedHashMap; 272 | /// 273 | /// let mut map = LinkedHashMap::new(); 274 | /// map.insert("a", 10); 275 | /// map.insert("c", 30); 276 | /// map.insert("b", 20); 277 | /// 278 | /// { 279 | /// let mut iter = map.entries(); 280 | /// let mut entry = iter.next().unwrap(); 281 | /// assert_eq!(&"a", entry.key()); 282 | /// *entry.get_mut() = 17; 283 | /// } 284 | /// 285 | /// assert_eq!(&17, map.get(&"a").unwrap()); 286 | /// ``` 287 | pub fn entries(&mut self) -> Entries { 288 | let head = if !self.head.is_null() { 289 | unsafe { (*self.head).prev } 290 | } else { 291 | ptr::null_mut() 292 | }; 293 | Entries { 294 | map: self, 295 | head, 296 | remaining: self.len(), 297 | marker: marker::PhantomData, 298 | } 299 | } 300 | 301 | /// Inserts a key-value pair into the map. If the key already existed, the old value is 302 | /// returned. 303 | /// 304 | /// # Examples 305 | /// 306 | /// ``` 307 | /// use linked_hash_map::LinkedHashMap; 308 | /// let mut map = LinkedHashMap::new(); 309 | /// 310 | /// map.insert(1, "a"); 311 | /// map.insert(2, "b"); 312 | /// assert_eq!(map[&1], "a"); 313 | /// assert_eq!(map[&2], "b"); 314 | /// ``` 315 | pub fn insert(&mut self, k: K, v: V) -> Option { 316 | self.ensure_guard_node(); 317 | 318 | let (node, old_val) = match self.map.get(&KeyRef { k: &k }) { 319 | Some(node) => { 320 | let old_val = unsafe { ptr::replace(&mut (**node).value, v) }; 321 | (*node, Some(old_val)) 322 | } 323 | None => { 324 | let node = if self.free.is_null() { 325 | Box::into_raw(Box::new(Node::new(k, v))) 326 | } else { 327 | // use a recycled box 328 | unsafe { 329 | let free = self.free; 330 | self.free = (*free).next; 331 | ptr::write(free, Node::new(k, v)); 332 | free 333 | } 334 | }; 335 | (node, None) 336 | } 337 | }; 338 | match old_val { 339 | Some(_) => { 340 | // Existing node, just update LRU position 341 | self.detach(node); 342 | self.attach(node); 343 | } 344 | None => { 345 | let keyref = unsafe { &(*node).key }; 346 | self.map.insert(KeyRef { k: keyref }, node); 347 | self.attach(node); 348 | } 349 | } 350 | old_val 351 | } 352 | 353 | /// Checks if the map contains the given key. 354 | pub fn contains_key(&self, k: &Q) -> bool 355 | where 356 | K: Borrow, 357 | Q: Eq + Hash, 358 | { 359 | self.map.contains_key(Qey::from_ref(k)) 360 | } 361 | 362 | /// Returns the value corresponding to the key in the map. 363 | /// 364 | /// # Examples 365 | /// 366 | /// ``` 367 | /// use linked_hash_map::LinkedHashMap; 368 | /// let mut map = LinkedHashMap::new(); 369 | /// 370 | /// map.insert(1, "a"); 371 | /// map.insert(2, "b"); 372 | /// map.insert(2, "c"); 373 | /// map.insert(3, "d"); 374 | /// 375 | /// assert_eq!(map.get(&1), Some(&"a")); 376 | /// assert_eq!(map.get(&2), Some(&"c")); 377 | /// ``` 378 | pub fn get(&self, k: &Q) -> Option<&V> 379 | where 380 | K: Borrow, 381 | Q: Eq + Hash, 382 | { 383 | self.map 384 | .get(Qey::from_ref(k)) 385 | .map(|e| unsafe { &(**e).value }) 386 | } 387 | 388 | /// Returns the mutable reference corresponding to the key in the map. 389 | /// 390 | /// # Examples 391 | /// 392 | /// ``` 393 | /// use linked_hash_map::LinkedHashMap; 394 | /// let mut map = LinkedHashMap::new(); 395 | /// 396 | /// map.insert(1, "a"); 397 | /// map.insert(2, "b"); 398 | /// 399 | /// *map.get_mut(&1).unwrap() = "c"; 400 | /// assert_eq!(map.get(&1), Some(&"c")); 401 | /// ``` 402 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 403 | where 404 | K: Borrow, 405 | Q: Eq + Hash, 406 | { 407 | self.map 408 | .get(Qey::from_ref(k)) 409 | .map(|e| unsafe { &mut (**e).value }) 410 | } 411 | 412 | /// Returns the value corresponding to the key in the map. 413 | /// 414 | /// If value is found, it is moved to the end of the list. 415 | /// This operation can be used in implemenation of LRU cache. 416 | /// 417 | /// # Examples 418 | /// 419 | /// ``` 420 | /// use linked_hash_map::LinkedHashMap; 421 | /// let mut map = LinkedHashMap::new(); 422 | /// 423 | /// map.insert(1, "a"); 424 | /// map.insert(2, "b"); 425 | /// map.insert(3, "d"); 426 | /// 427 | /// assert_eq!(map.get_refresh(&2), Some(&mut "b")); 428 | /// 429 | /// assert_eq!((&2, &"b"), map.iter().rev().next().unwrap()); 430 | /// ``` 431 | pub fn get_refresh(&mut self, k: &Q) -> Option<&mut V> 432 | where 433 | K: Borrow, 434 | Q: Eq + Hash, 435 | { 436 | let (value, node_ptr_opt) = match self.map.get(Qey::from_ref(k)) { 437 | None => (None, None), 438 | Some(node) => (Some(unsafe { &mut (**node).value }), Some(*node)), 439 | }; 440 | if let Some(node_ptr) = node_ptr_opt { 441 | self.detach(node_ptr); 442 | self.attach(node_ptr); 443 | } 444 | value 445 | } 446 | 447 | /// Removes and returns the value corresponding to the key from the map. 448 | /// 449 | /// # Examples 450 | /// 451 | /// ``` 452 | /// use linked_hash_map::LinkedHashMap; 453 | /// let mut map = LinkedHashMap::new(); 454 | /// 455 | /// map.insert(2, "a"); 456 | /// 457 | /// assert_eq!(map.remove(&1), None); 458 | /// assert_eq!(map.remove(&2), Some("a")); 459 | /// assert_eq!(map.remove(&2), None); 460 | /// assert_eq!(map.len(), 0); 461 | /// ``` 462 | pub fn remove(&mut self, k: &Q) -> Option 463 | where 464 | K: Borrow, 465 | Q: Eq + Hash, 466 | { 467 | let removed = self.map.remove(Qey::from_ref(k)); 468 | removed.map(|node| { 469 | self.detach(node); 470 | unsafe { 471 | // add to free list 472 | (*node).next = self.free; 473 | self.free = node; 474 | // drop the key and return the value 475 | drop(ptr::read(&(*node).key)); 476 | ptr::read(&(*node).value) 477 | } 478 | }) 479 | } 480 | 481 | /// Returns the maximum number of key-value pairs the map can hold without reallocating. 482 | /// 483 | /// # Examples 484 | /// 485 | /// ``` 486 | /// use linked_hash_map::LinkedHashMap; 487 | /// let mut map: LinkedHashMap = LinkedHashMap::new(); 488 | /// let capacity = map.capacity(); 489 | /// ``` 490 | pub fn capacity(&self) -> usize { 491 | self.map.capacity() 492 | } 493 | 494 | /// Removes the first entry. 495 | /// 496 | /// Can be used in implementation of LRU cache. 497 | /// 498 | /// # Examples 499 | /// 500 | /// ``` 501 | /// use linked_hash_map::LinkedHashMap; 502 | /// let mut map = LinkedHashMap::new(); 503 | /// map.insert(1, 10); 504 | /// map.insert(2, 20); 505 | /// map.pop_front(); 506 | /// assert_eq!(map.get(&1), None); 507 | /// assert_eq!(map.get(&2), Some(&20)); 508 | /// ``` 509 | #[inline] 510 | pub fn pop_front(&mut self) -> Option<(K, V)> { 511 | if self.is_empty() { 512 | return None; 513 | } 514 | let lru = unsafe { (*self.head).prev }; 515 | self.detach(lru); 516 | self.map 517 | .remove(&KeyRef { 518 | k: unsafe { &(*lru).key }, 519 | }) 520 | .map(|e| { 521 | let e = *unsafe { Box::from_raw(e) }; 522 | (e.key, e.value) 523 | }) 524 | } 525 | 526 | /// Gets the first entry. 527 | /// 528 | /// # Examples 529 | /// 530 | /// ``` 531 | /// use linked_hash_map::LinkedHashMap; 532 | /// let mut map = LinkedHashMap::new(); 533 | /// map.insert(1, 10); 534 | /// map.insert(2, 20); 535 | /// assert_eq!(map.front(), Some((&1, &10))); 536 | /// ``` 537 | #[inline] 538 | pub fn front(&self) -> Option<(&K, &V)> { 539 | if self.is_empty() { 540 | return None; 541 | } 542 | let lru = unsafe { (*self.head).prev }; 543 | self.map 544 | .get(&KeyRef { 545 | k: unsafe { &(*lru).key }, 546 | }) 547 | .map(|e| unsafe { (&(**e).key, &(**e).value) }) 548 | } 549 | 550 | /// Removes the last entry. 551 | /// 552 | /// # Examples 553 | /// 554 | /// ``` 555 | /// use linked_hash_map::LinkedHashMap; 556 | /// let mut map = LinkedHashMap::new(); 557 | /// map.insert(1, 10); 558 | /// map.insert(2, 20); 559 | /// map.pop_back(); 560 | /// assert_eq!(map.get(&1), Some(&10)); 561 | /// assert_eq!(map.get(&2), None); 562 | /// ``` 563 | #[inline] 564 | pub fn pop_back(&mut self) -> Option<(K, V)> { 565 | if self.is_empty() { 566 | return None; 567 | } 568 | let mru = unsafe { (*self.head).next }; 569 | self.detach(mru); 570 | self.map 571 | .remove(&KeyRef { 572 | k: unsafe { &(*mru).key }, 573 | }) 574 | .map(|e| { 575 | let e = *unsafe { Box::from_raw(e) }; 576 | (e.key, e.value) 577 | }) 578 | } 579 | 580 | /// Gets the last entry. 581 | /// 582 | /// # Examples 583 | /// 584 | /// ``` 585 | /// use linked_hash_map::LinkedHashMap; 586 | /// let mut map = LinkedHashMap::new(); 587 | /// map.insert(1, 10); 588 | /// map.insert(2, 20); 589 | /// assert_eq!(map.back(), Some((&2, &20))); 590 | /// ``` 591 | #[inline] 592 | pub fn back(&self) -> Option<(&K, &V)> { 593 | if self.is_empty() { 594 | return None; 595 | } 596 | let mru = unsafe { (*self.head).next }; 597 | self.map 598 | .get(&KeyRef { 599 | k: unsafe { &(*mru).key }, 600 | }) 601 | .map(|e| unsafe { (&(**e).key, &(**e).value) }) 602 | } 603 | 604 | /// Returns the number of key-value pairs in the map. 605 | pub fn len(&self) -> usize { 606 | self.map.len() 607 | } 608 | 609 | /// Returns whether the map is currently empty. 610 | pub fn is_empty(&self) -> bool { 611 | self.len() == 0 612 | } 613 | 614 | /// Returns a reference to the map's hasher. 615 | pub fn hasher(&self) -> &S { 616 | self.map.hasher() 617 | } 618 | 619 | /// Clears the map of all key-value pairs. 620 | pub fn clear(&mut self) { 621 | self.map.clear(); 622 | // update the guard node if present 623 | if !self.head.is_null() { 624 | unsafe { 625 | self.drop_entries(); 626 | (*self.head).prev = self.head; 627 | (*self.head).next = self.head; 628 | } 629 | } 630 | } 631 | 632 | /// Returns a double-ended iterator visiting all key-value pairs in order of insertion. 633 | /// Iterator element type is `(&'a K, &'a V)` 634 | /// 635 | /// # Examples 636 | /// ``` 637 | /// use linked_hash_map::LinkedHashMap; 638 | /// 639 | /// let mut map = LinkedHashMap::new(); 640 | /// map.insert("a", 10); 641 | /// map.insert("c", 30); 642 | /// map.insert("b", 20); 643 | /// 644 | /// let mut iter = map.iter(); 645 | /// assert_eq!((&"a", &10), iter.next().unwrap()); 646 | /// assert_eq!((&"c", &30), iter.next().unwrap()); 647 | /// assert_eq!((&"b", &20), iter.next().unwrap()); 648 | /// assert_eq!(None, iter.next()); 649 | /// ``` 650 | pub fn iter(&self) -> Iter { 651 | let head = if self.head.is_null() { 652 | ptr::null_mut() 653 | } else { 654 | unsafe { (*self.head).prev } 655 | }; 656 | Iter { 657 | head, 658 | tail: self.head, 659 | remaining: self.len(), 660 | marker: marker::PhantomData, 661 | } 662 | } 663 | 664 | /// Returns a double-ended iterator visiting all key-value pairs in order of insertion. 665 | /// Iterator element type is `(&'a K, &'a mut V)` 666 | /// # Examples 667 | /// ``` 668 | /// use linked_hash_map::LinkedHashMap; 669 | /// 670 | /// let mut map = LinkedHashMap::new(); 671 | /// map.insert("a", 10); 672 | /// map.insert("c", 30); 673 | /// map.insert("b", 20); 674 | /// 675 | /// { 676 | /// let mut iter = map.iter_mut(); 677 | /// let mut entry = iter.next().unwrap(); 678 | /// assert_eq!(&"a", entry.0); 679 | /// *entry.1 = 17; 680 | /// } 681 | /// 682 | /// assert_eq!(&17, map.get(&"a").unwrap()); 683 | /// ``` 684 | pub fn iter_mut(&mut self) -> IterMut { 685 | let head = if self.head.is_null() { 686 | ptr::null_mut() 687 | } else { 688 | unsafe { (*self.head).prev } 689 | }; 690 | IterMut { 691 | head, 692 | tail: self.head, 693 | remaining: self.len(), 694 | marker: marker::PhantomData, 695 | } 696 | } 697 | 698 | /// Clears the map, returning all key-value pairs as an iterator. Keeps the 699 | /// allocated memory for reuse. 700 | /// 701 | /// If the returned iterator is dropped before being fully consumed, it 702 | /// drops the remaining key-value pairs. The returned iterator keeps a 703 | /// mutable borrow on the vector to optimize its implementation. 704 | /// 705 | /// Current performance implications (why to use this over into_iter()): 706 | /// 707 | /// * Clears the inner HashMap instead of dropping it 708 | /// * Puts all drained nodes in the free-list instead of deallocating them 709 | /// * Avoids deallocating the sentinel node 710 | pub fn drain(&mut self) -> Drain { 711 | let len = self.len(); 712 | // Map should be empty now, regardless of current state 713 | self.map.clear(); 714 | let (head, tail) = if len != 0 { 715 | // This is basically the same as IntoIter's impl, but we don't 716 | // deallocate/drop anything. Instead we make the sentinel head node 717 | // point at itself (same state you get from removing the last element from a map), 718 | // and then append the entire list to the free list. At this point all the entries 719 | // have essentially been fed into mem::forget. The Drain iterator will then iterate 720 | // over those nodes in the freelist (using `len` to know where to stop) and `read` 721 | // the values out of the nodes, "unforgetting" them. 722 | // 723 | // This design results in no observable consequences for mem::forgetting the 724 | // drain iterator, because the drain iterator has no responsibility to "fix up" 725 | // things during iteration/destruction. That said, you will effectively mem::forget 726 | // any elements that weren't yielded yet. 727 | unsafe { 728 | debug_assert!(!self.head.is_null()); 729 | debug_assert!(!(*self.head).prev.is_null()); 730 | debug_assert!((*self.head).prev != self.head); 731 | let head = (*self.head).prev; 732 | let tail = (*self.head).next; 733 | (*self.head).prev = self.head; 734 | (*self.head).next = self.head; 735 | (*head).next = self.free; 736 | (*tail).prev = ptr::null_mut(); 737 | self.free = tail; 738 | (head, tail) 739 | } 740 | } else { 741 | (ptr::null_mut(), ptr::null_mut()) 742 | }; 743 | 744 | Drain { 745 | head, 746 | tail, 747 | remaining: len, 748 | marker: marker::PhantomData, 749 | } 750 | } 751 | 752 | /// Returns a double-ended iterator visiting all key in order of insertion. 753 | /// 754 | /// # Examples 755 | /// ``` 756 | /// use linked_hash_map::LinkedHashMap; 757 | /// 758 | /// let mut map = LinkedHashMap::new(); 759 | /// map.insert('a', 10); 760 | /// map.insert('c', 30); 761 | /// map.insert('b', 20); 762 | /// 763 | /// let mut keys = map.keys(); 764 | /// assert_eq!(&'a', keys.next().unwrap()); 765 | /// assert_eq!(&'c', keys.next().unwrap()); 766 | /// assert_eq!(&'b', keys.next().unwrap()); 767 | /// assert_eq!(None, keys.next()); 768 | /// ``` 769 | pub fn keys(&self) -> Keys { 770 | Keys { inner: self.iter() } 771 | } 772 | 773 | /// Returns a double-ended iterator visiting all values in order of insertion. 774 | /// 775 | /// # Examples 776 | /// ``` 777 | /// use linked_hash_map::LinkedHashMap; 778 | /// 779 | /// let mut map = LinkedHashMap::new(); 780 | /// map.insert('a', 10); 781 | /// map.insert('c', 30); 782 | /// map.insert('b', 20); 783 | /// 784 | /// let mut values = map.values(); 785 | /// assert_eq!(&10, values.next().unwrap()); 786 | /// assert_eq!(&30, values.next().unwrap()); 787 | /// assert_eq!(&20, values.next().unwrap()); 788 | /// assert_eq!(None, values.next()); 789 | /// ``` 790 | pub fn values(&self) -> Values { 791 | Values { inner: self.iter() } 792 | } 793 | } 794 | 795 | impl<'a, K, V, S, Q: ?Sized> Index<&'a Q> for LinkedHashMap 796 | where 797 | K: Hash + Eq + Borrow, 798 | S: BuildHasher, 799 | Q: Eq + Hash, 800 | { 801 | type Output = V; 802 | 803 | fn index(&self, index: &'a Q) -> &V { 804 | self.get(index).expect("no entry found for key") 805 | } 806 | } 807 | 808 | impl<'a, K, V, S, Q: ?Sized> IndexMut<&'a Q> for LinkedHashMap 809 | where 810 | K: Hash + Eq + Borrow, 811 | S: BuildHasher, 812 | Q: Eq + Hash, 813 | { 814 | fn index_mut(&mut self, index: &'a Q) -> &mut V { 815 | self.get_mut(index).expect("no entry found for key") 816 | } 817 | } 818 | 819 | impl Clone for LinkedHashMap { 820 | fn clone(&self) -> Self { 821 | let mut map = Self::with_hasher(self.map.hasher().clone()); 822 | map.extend(self.iter().map(|(k, v)| (k.clone(), v.clone()))); 823 | map 824 | } 825 | } 826 | 827 | impl Default for LinkedHashMap { 828 | fn default() -> Self { 829 | Self::with_hasher(S::default()) 830 | } 831 | } 832 | 833 | impl Extend<(K, V)> for LinkedHashMap { 834 | fn extend>(&mut self, iter: I) { 835 | for (k, v) in iter { 836 | self.insert(k, v); 837 | } 838 | } 839 | } 840 | 841 | impl<'a, K, V, S> Extend<(&'a K, &'a V)> for LinkedHashMap 842 | where 843 | K: 'a + Hash + Eq + Copy, 844 | V: 'a + Copy, 845 | S: BuildHasher, 846 | { 847 | fn extend>(&mut self, iter: I) { 848 | for (&k, &v) in iter { 849 | self.insert(k, v); 850 | } 851 | } 852 | } 853 | 854 | impl iter::FromIterator<(K, V)> 855 | for LinkedHashMap 856 | { 857 | fn from_iter>(iter: I) -> Self { 858 | let iter = iter.into_iter(); 859 | let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default()); 860 | map.extend(iter); 861 | map 862 | } 863 | } 864 | 865 | impl fmt::Debug 866 | for LinkedHashMap 867 | { 868 | /// Returns a string that lists the key-value pairs in insertion order. 869 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 870 | f.debug_map().entries(self).finish() 871 | } 872 | } 873 | 874 | impl PartialEq for LinkedHashMap { 875 | fn eq(&self, other: &Self) -> bool { 876 | self.len() == other.len() && self.iter().eq(other) 877 | } 878 | } 879 | 880 | impl Eq for LinkedHashMap {} 881 | 882 | impl PartialOrd 883 | for LinkedHashMap 884 | { 885 | fn partial_cmp(&self, other: &Self) -> Option { 886 | self.iter().partial_cmp(other) 887 | } 888 | 889 | fn lt(&self, other: &Self) -> bool { 890 | self.iter().lt(other) 891 | } 892 | 893 | fn le(&self, other: &Self) -> bool { 894 | self.iter().le(other) 895 | } 896 | 897 | fn ge(&self, other: &Self) -> bool { 898 | self.iter().ge(other) 899 | } 900 | 901 | fn gt(&self, other: &Self) -> bool { 902 | self.iter().gt(other) 903 | } 904 | } 905 | 906 | impl Ord for LinkedHashMap { 907 | fn cmp(&self, other: &Self) -> Ordering { 908 | self.iter().cmp(other) 909 | } 910 | } 911 | 912 | impl Hash for LinkedHashMap { 913 | fn hash(&self, h: &mut H) { 914 | for e in self.iter() { 915 | e.hash(h); 916 | } 917 | } 918 | } 919 | 920 | unsafe impl Send for LinkedHashMap {} 921 | 922 | unsafe impl Sync for LinkedHashMap {} 923 | 924 | impl Drop for LinkedHashMap { 925 | fn drop(&mut self) { 926 | if !self.head.is_null() { 927 | unsafe { 928 | self.drop_entries(); 929 | drop_empty_node(self.head); 930 | } 931 | } 932 | self.clear_free_list(); 933 | } 934 | } 935 | 936 | /// An insertion-order iterator over a `LinkedHashMap`'s entries, with immutable references to the 937 | /// values. 938 | pub struct Iter<'a, K: 'a, V: 'a> { 939 | head: *const Node, 940 | tail: *const Node, 941 | remaining: usize, 942 | marker: marker::PhantomData<(&'a K, &'a V)>, 943 | } 944 | 945 | /// An insertion-order iterator over a `LinkedHashMap`'s entries, with mutable references to the 946 | /// values. 947 | pub struct IterMut<'a, K: 'a, V: 'a> { 948 | head: *mut Node, 949 | tail: *mut Node, 950 | remaining: usize, 951 | marker: marker::PhantomData<(&'a K, &'a mut V)>, 952 | } 953 | 954 | /// A consuming insertion-order iterator over a `LinkedHashMap`'s entries. 955 | pub struct IntoIter { 956 | head: *mut Node, 957 | tail: *mut Node, 958 | remaining: usize, 959 | marker: marker::PhantomData<(K, V)>, 960 | } 961 | 962 | /// A draining insertion-order iterator over a `LinkedHashMap`'s entries. 963 | pub struct Drain<'a, K, V> { 964 | head: *mut Node, 965 | tail: *mut Node, 966 | remaining: usize, 967 | marker: marker::PhantomData<&'a mut (K, V)>, 968 | } 969 | 970 | /// An insertion-order iterator over a `LinkedHashMap`'s entries represented as 971 | /// an `OccupiedEntry`. 972 | pub struct Entries<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> { 973 | map: *mut LinkedHashMap, 974 | head: *mut Node, 975 | remaining: usize, 976 | marker: marker::PhantomData<(&'a K, &'a mut V, &'a S)>, 977 | } 978 | 979 | unsafe impl<'a, K, V> Send for Iter<'a, K, V> 980 | where 981 | K: Send, 982 | V: Send, 983 | { 984 | } 985 | 986 | unsafe impl<'a, K, V> Send for IterMut<'a, K, V> 987 | where 988 | K: Send, 989 | V: Send, 990 | { 991 | } 992 | 993 | unsafe impl<'a, K, V> Send for Drain<'a, K, V> 994 | where 995 | K: Send, 996 | V: Send, 997 | { 998 | } 999 | 1000 | unsafe impl Send for IntoIter 1001 | where 1002 | K: Send, 1003 | V: Send, 1004 | { 1005 | } 1006 | 1007 | unsafe impl<'a, K, V, S> Send for Entries<'a, K, V, S> 1008 | where 1009 | K: Send, 1010 | V: Send, 1011 | S: Send, 1012 | { 1013 | } 1014 | 1015 | unsafe impl<'a, K, V> Sync for Iter<'a, K, V> 1016 | where 1017 | K: Sync, 1018 | V: Sync, 1019 | { 1020 | } 1021 | 1022 | unsafe impl<'a, K, V> Sync for IterMut<'a, K, V> 1023 | where 1024 | K: Sync, 1025 | V: Sync, 1026 | { 1027 | } 1028 | 1029 | unsafe impl<'a, K, V> Sync for Drain<'a, K, V> 1030 | where 1031 | K: Sync, 1032 | V: Sync, 1033 | { 1034 | } 1035 | unsafe impl Sync for IntoIter 1036 | where 1037 | K: Sync, 1038 | V: Sync, 1039 | { 1040 | } 1041 | 1042 | unsafe impl<'a, K, V, S> Sync for Entries<'a, K, V, S> 1043 | where 1044 | K: Sync, 1045 | V: Sync, 1046 | S: Sync, 1047 | { 1048 | } 1049 | 1050 | impl<'a, K, V> Clone for Iter<'a, K, V> { 1051 | fn clone(&self) -> Self { 1052 | Iter { ..*self } 1053 | } 1054 | } 1055 | 1056 | impl Clone for IntoIter 1057 | where 1058 | K: Clone, 1059 | V: Clone, 1060 | { 1061 | fn clone(&self) -> Self { 1062 | if self.remaining == 0 { 1063 | return IntoIter { ..*self }; 1064 | } 1065 | 1066 | fn clone_node(e: *mut Node) -> *mut Node 1067 | where 1068 | K: Clone, 1069 | V: Clone, 1070 | { 1071 | Box::into_raw(Box::new(Node::new(unsafe { (*e).key.clone() }, unsafe { 1072 | (*e).value.clone() 1073 | }))) 1074 | } 1075 | 1076 | let mut cur = self.head; 1077 | let head = clone_node(cur); 1078 | let mut tail = head; 1079 | for _ in 1..self.remaining { 1080 | unsafe { 1081 | (*tail).prev = clone_node((*cur).prev); 1082 | (*(*tail).prev).next = tail; 1083 | tail = (*tail).prev; 1084 | cur = (*cur).prev; 1085 | } 1086 | } 1087 | 1088 | IntoIter { 1089 | head, 1090 | tail, 1091 | remaining: self.remaining, 1092 | marker: marker::PhantomData, 1093 | } 1094 | } 1095 | } 1096 | 1097 | impl<'a, K, V> Iterator for Iter<'a, K, V> { 1098 | type Item = (&'a K, &'a V); 1099 | 1100 | fn next(&mut self) -> Option<(&'a K, &'a V)> { 1101 | if self.head == self.tail { 1102 | None 1103 | } else { 1104 | self.remaining -= 1; 1105 | unsafe { 1106 | let r = Some((&(*self.head).key, &(*self.head).value)); 1107 | self.head = (*self.head).prev; 1108 | r 1109 | } 1110 | } 1111 | } 1112 | 1113 | fn size_hint(&self) -> (usize, Option) { 1114 | (self.remaining, Some(self.remaining)) 1115 | } 1116 | } 1117 | 1118 | impl<'a, K, V> Iterator for IterMut<'a, K, V> { 1119 | type Item = (&'a K, &'a mut V); 1120 | 1121 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> { 1122 | if self.head == self.tail { 1123 | None 1124 | } else { 1125 | self.remaining -= 1; 1126 | unsafe { 1127 | let r = Some((&(*self.head).key, &mut (*self.head).value)); 1128 | self.head = (*self.head).prev; 1129 | r 1130 | } 1131 | } 1132 | } 1133 | 1134 | fn size_hint(&self) -> (usize, Option) { 1135 | (self.remaining, Some(self.remaining)) 1136 | } 1137 | } 1138 | 1139 | impl Iterator for IntoIter { 1140 | type Item = (K, V); 1141 | 1142 | fn next(&mut self) -> Option<(K, V)> { 1143 | if self.remaining == 0 { 1144 | return None; 1145 | } 1146 | self.remaining -= 1; 1147 | unsafe { 1148 | let prev = (*self.head).prev; 1149 | let e = *Box::from_raw(self.head); 1150 | self.head = prev; 1151 | Some((e.key, e.value)) 1152 | } 1153 | } 1154 | 1155 | fn size_hint(&self) -> (usize, Option) { 1156 | (self.remaining, Some(self.remaining)) 1157 | } 1158 | } 1159 | 1160 | impl<'a, K, V> Iterator for Drain<'a, K, V> { 1161 | type Item = (K, V); 1162 | 1163 | fn next(&mut self) -> Option<(K, V)> { 1164 | if self.remaining == 0 { 1165 | return None; 1166 | } 1167 | self.remaining -= 1; 1168 | unsafe { 1169 | let prev = (*self.head).prev; 1170 | // Read the values out, the node is in the free-list already so these will 1171 | // be treated as uninit memory. 1172 | let k = addr_of_mut!((*self.head).key).read(); 1173 | let v = addr_of_mut!((*self.head).value).read(); 1174 | self.head = prev; 1175 | Some((k, v)) 1176 | } 1177 | } 1178 | 1179 | fn size_hint(&self) -> (usize, Option) { 1180 | (self.remaining, Some(self.remaining)) 1181 | } 1182 | } 1183 | 1184 | impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> { 1185 | fn next_back(&mut self) -> Option<(K, V)> { 1186 | if self.remaining == 0 { 1187 | return None; 1188 | } 1189 | self.remaining -= 1; 1190 | unsafe { 1191 | let next = (*self.tail).next; 1192 | // Read the values out, the node is in the free-list already so these will 1193 | // be treated as uninit memory. 1194 | let k = addr_of_mut!((*self.tail).key).read(); 1195 | let v = addr_of_mut!((*self.tail).value).read(); 1196 | self.tail = next; 1197 | Some((k, v)) 1198 | } 1199 | } 1200 | } 1201 | 1202 | impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { 1203 | fn len(&self) -> usize { 1204 | self.remaining 1205 | } 1206 | } 1207 | 1208 | impl<'a, K, V, S: BuildHasher> Iterator for Entries<'a, K, V, S> { 1209 | type Item = OccupiedEntry<'a, K, V, S>; 1210 | 1211 | fn next(&mut self) -> Option> { 1212 | if self.remaining == 0 { 1213 | None 1214 | } else { 1215 | self.remaining -= 1; 1216 | unsafe { 1217 | let r = Some(OccupiedEntry { 1218 | map: self.map, 1219 | entry: self.head, 1220 | marker: marker::PhantomData, 1221 | }); 1222 | 1223 | self.head = (*self.head).prev; 1224 | r 1225 | } 1226 | } 1227 | } 1228 | 1229 | fn size_hint(&self) -> (usize, Option) { 1230 | (self.remaining, Some(self.remaining)) 1231 | } 1232 | } 1233 | 1234 | impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { 1235 | fn next_back(&mut self) -> Option<(&'a K, &'a V)> { 1236 | if self.head == self.tail { 1237 | None 1238 | } else { 1239 | self.remaining -= 1; 1240 | unsafe { 1241 | self.tail = (*self.tail).next; 1242 | Some((&(*self.tail).key, &(*self.tail).value)) 1243 | } 1244 | } 1245 | } 1246 | } 1247 | 1248 | impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { 1249 | fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { 1250 | if self.head == self.tail { 1251 | None 1252 | } else { 1253 | self.remaining -= 1; 1254 | unsafe { 1255 | self.tail = (*self.tail).next; 1256 | Some((&(*self.tail).key, &mut (*self.tail).value)) 1257 | } 1258 | } 1259 | } 1260 | } 1261 | 1262 | impl DoubleEndedIterator for IntoIter { 1263 | fn next_back(&mut self) -> Option<(K, V)> { 1264 | if self.remaining == 0 { 1265 | return None; 1266 | } 1267 | self.remaining -= 1; 1268 | unsafe { 1269 | let next = (*self.tail).next; 1270 | let e = *Box::from_raw(self.tail); 1271 | self.tail = next; 1272 | Some((e.key, e.value)) 1273 | } 1274 | } 1275 | } 1276 | 1277 | impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { 1278 | fn len(&self) -> usize { 1279 | self.remaining 1280 | } 1281 | } 1282 | 1283 | impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { 1284 | fn len(&self) -> usize { 1285 | self.remaining 1286 | } 1287 | } 1288 | 1289 | impl ExactSizeIterator for IntoIter { 1290 | fn len(&self) -> usize { 1291 | self.remaining 1292 | } 1293 | } 1294 | 1295 | impl Drop for IntoIter { 1296 | fn drop(&mut self) { 1297 | for _ in 0..self.remaining { 1298 | unsafe { 1299 | let next = (*self.tail).next; 1300 | Box::from_raw(self.tail); 1301 | self.tail = next; 1302 | } 1303 | } 1304 | } 1305 | } 1306 | 1307 | impl<'a, K, V> Drop for Drain<'a, K, V> { 1308 | fn drop(&mut self) { 1309 | for _ in self {} 1310 | } 1311 | } 1312 | 1313 | /// An insertion-order iterator over a `LinkedHashMap`'s keys. 1314 | pub struct Keys<'a, K: 'a, V: 'a> { 1315 | inner: Iter<'a, K, V>, 1316 | } 1317 | 1318 | impl<'a, K, V> Clone for Keys<'a, K, V> { 1319 | fn clone(&self) -> Self { 1320 | Keys { 1321 | inner: self.inner.clone(), 1322 | } 1323 | } 1324 | } 1325 | 1326 | impl<'a, K, V> Iterator for Keys<'a, K, V> { 1327 | type Item = &'a K; 1328 | 1329 | #[inline] 1330 | fn next(&mut self) -> Option<&'a K> { 1331 | self.inner.next().map(|e| e.0) 1332 | } 1333 | #[inline] 1334 | fn size_hint(&self) -> (usize, Option) { 1335 | self.inner.size_hint() 1336 | } 1337 | } 1338 | 1339 | impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { 1340 | #[inline] 1341 | fn next_back(&mut self) -> Option<&'a K> { 1342 | self.inner.next_back().map(|e| e.0) 1343 | } 1344 | } 1345 | 1346 | impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { 1347 | fn len(&self) -> usize { 1348 | self.inner.len() 1349 | } 1350 | } 1351 | 1352 | /// An insertion-order iterator over a `LinkedHashMap`'s values. 1353 | pub struct Values<'a, K: 'a, V: 'a> { 1354 | inner: Iter<'a, K, V>, 1355 | } 1356 | 1357 | impl<'a, K, V> Clone for Values<'a, K, V> { 1358 | fn clone(&self) -> Self { 1359 | Values { 1360 | inner: self.inner.clone(), 1361 | } 1362 | } 1363 | } 1364 | 1365 | impl<'a, K, V> Iterator for Values<'a, K, V> { 1366 | type Item = &'a V; 1367 | 1368 | #[inline] 1369 | fn next(&mut self) -> Option<&'a V> { 1370 | self.inner.next().map(|e| e.1) 1371 | } 1372 | #[inline] 1373 | fn size_hint(&self) -> (usize, Option) { 1374 | self.inner.size_hint() 1375 | } 1376 | } 1377 | 1378 | impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { 1379 | #[inline] 1380 | fn next_back(&mut self) -> Option<&'a V> { 1381 | self.inner.next_back().map(|e| e.1) 1382 | } 1383 | } 1384 | 1385 | impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { 1386 | fn len(&self) -> usize { 1387 | self.inner.len() 1388 | } 1389 | } 1390 | 1391 | impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a LinkedHashMap { 1392 | type Item = (&'a K, &'a V); 1393 | type IntoIter = Iter<'a, K, V>; 1394 | fn into_iter(self) -> Iter<'a, K, V> { 1395 | self.iter() 1396 | } 1397 | } 1398 | 1399 | impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a mut LinkedHashMap { 1400 | type Item = (&'a K, &'a mut V); 1401 | type IntoIter = IterMut<'a, K, V>; 1402 | fn into_iter(self) -> IterMut<'a, K, V> { 1403 | self.iter_mut() 1404 | } 1405 | } 1406 | 1407 | impl IntoIterator for LinkedHashMap { 1408 | type Item = (K, V); 1409 | type IntoIter = IntoIter; 1410 | fn into_iter(mut self) -> IntoIter { 1411 | let (head, tail) = if !self.head.is_null() { 1412 | unsafe { ((*self.head).prev, (*self.head).next) } 1413 | } else { 1414 | (ptr::null_mut(), ptr::null_mut()) 1415 | }; 1416 | let len = self.len(); 1417 | 1418 | if !self.head.is_null() { 1419 | unsafe { drop_empty_node(self.head) } 1420 | } 1421 | self.clear_free_list(); 1422 | // drop the HashMap but not the LinkedHashMap 1423 | unsafe { 1424 | ptr::drop_in_place(&mut self.map); 1425 | } 1426 | mem::forget(self); 1427 | 1428 | IntoIter { 1429 | head, 1430 | tail, 1431 | remaining: len, 1432 | marker: marker::PhantomData, 1433 | } 1434 | } 1435 | } 1436 | 1437 | /// A view into a single location in a map, which may be vacant or occupied. 1438 | pub enum Entry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> { 1439 | /// An occupied Entry. 1440 | Occupied(OccupiedEntry<'a, K, V, S>), 1441 | /// A vacant Entry. 1442 | Vacant(VacantEntry<'a, K, V, S>), 1443 | } 1444 | 1445 | /// A view into a single occupied location in a `LinkedHashMap`. 1446 | pub struct OccupiedEntry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> { 1447 | entry: *mut Node, 1448 | map: *mut LinkedHashMap, 1449 | marker: marker::PhantomData<&'a K>, 1450 | } 1451 | 1452 | /// A view into a single empty location in a `LinkedHashMap`. 1453 | pub struct VacantEntry<'a, K: 'a, V: 'a, S: 'a = hash_map::RandomState> { 1454 | key: K, 1455 | map: &'a mut LinkedHashMap, 1456 | } 1457 | 1458 | impl<'a, K: Hash + Eq, V, S: BuildHasher> Entry<'a, K, V, S> { 1459 | /// Returns the entry key 1460 | /// 1461 | /// # Examples 1462 | /// 1463 | /// ``` 1464 | /// use linked_hash_map::LinkedHashMap; 1465 | /// 1466 | /// let mut map = LinkedHashMap::::new(); 1467 | /// 1468 | /// assert_eq!("hello", map.entry("hello".to_string()).key()); 1469 | /// ``` 1470 | pub fn key(&self) -> &K { 1471 | match *self { 1472 | Entry::Occupied(ref e) => e.key(), 1473 | Entry::Vacant(ref e) => e.key(), 1474 | } 1475 | } 1476 | 1477 | /// Ensures a value is in the entry by inserting the default if empty, and returns 1478 | /// a mutable reference to the value in the entry. 1479 | pub fn or_insert(self, default: V) -> &'a mut V { 1480 | match self { 1481 | Entry::Occupied(entry) => entry.into_mut(), 1482 | Entry::Vacant(entry) => entry.insert(default), 1483 | } 1484 | } 1485 | 1486 | /// Ensures a value is in the entry by inserting the result of the default function if empty, 1487 | /// and returns a mutable reference to the value in the entry. 1488 | pub fn or_insert_with V>(self, default: F) -> &'a mut V { 1489 | match self { 1490 | Entry::Occupied(entry) => entry.into_mut(), 1491 | Entry::Vacant(entry) => entry.insert(default()), 1492 | } 1493 | } 1494 | 1495 | /// Provides in-place mutable access to an occupied entry before any 1496 | /// potential inserts into the map. 1497 | pub fn and_modify(self, f: F) -> Self 1498 | where 1499 | F: FnOnce(&mut V), 1500 | { 1501 | match self { 1502 | Entry::Occupied(mut entry) => { 1503 | f(entry.get_mut()); 1504 | Entry::Occupied(entry) 1505 | } 1506 | Entry::Vacant(entry) => Entry::Vacant(entry), 1507 | } 1508 | } 1509 | 1510 | /// Ensures a value is in the entry by inserting the default value if empty, 1511 | /// and returns a mutable reference to the value in the entry. 1512 | pub fn or_default(self) -> &'a mut V 1513 | where 1514 | V: Default, 1515 | { 1516 | match self { 1517 | Entry::Occupied(entry) => entry.into_mut(), 1518 | Entry::Vacant(entry) => entry.insert(V::default()), 1519 | } 1520 | } 1521 | } 1522 | 1523 | impl<'a, K: Hash + Eq, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> { 1524 | /// Gets a reference to the entry key 1525 | /// 1526 | /// # Examples 1527 | /// 1528 | /// ``` 1529 | /// use linked_hash_map::LinkedHashMap; 1530 | /// 1531 | /// let mut map = LinkedHashMap::new(); 1532 | /// 1533 | /// map.insert("foo".to_string(), 1); 1534 | /// assert_eq!("foo", map.entry("foo".to_string()).key()); 1535 | /// ``` 1536 | pub fn key(&self) -> &K { 1537 | unsafe { &(*self.entry).key } 1538 | } 1539 | 1540 | /// Gets a reference to the value in the entry. 1541 | pub fn get(&self) -> &V { 1542 | unsafe { &(*self.entry).value } 1543 | } 1544 | 1545 | /// Gets a mutable reference to the value in the entry. 1546 | pub fn get_mut(&mut self) -> &mut V { 1547 | unsafe { &mut (*self.entry).value } 1548 | } 1549 | 1550 | /// Converts the OccupiedEntry into a mutable reference to the value in the entry 1551 | /// with a lifetime bound to the map itself 1552 | pub fn into_mut(self) -> &'a mut V { 1553 | unsafe { &mut (*self.entry).value } 1554 | } 1555 | 1556 | /// Sets the value of the entry, and returns the entry's old value 1557 | pub fn insert(&mut self, value: V) -> V { 1558 | unsafe { 1559 | (*self.map).ensure_guard_node(); 1560 | 1561 | let old_val = mem::replace(&mut (*self.entry).value, value); 1562 | let node_ptr: *mut Node = self.entry; 1563 | 1564 | // Existing node, just update LRU position 1565 | (*self.map).detach(node_ptr); 1566 | (*self.map).attach(node_ptr); 1567 | 1568 | old_val 1569 | } 1570 | } 1571 | 1572 | /// Takes the value out of the entry, and returns it 1573 | pub fn remove(self) -> V { 1574 | unsafe { (*self.map).remove(&(*self.entry).key) }.unwrap() 1575 | } 1576 | } 1577 | 1578 | impl<'a, K: 'a + Hash + Eq, V: 'a, S: BuildHasher> VacantEntry<'a, K, V, S> { 1579 | /// Gets a reference to the entry key 1580 | /// 1581 | /// # Examples 1582 | /// 1583 | /// ``` 1584 | /// use linked_hash_map::LinkedHashMap; 1585 | /// 1586 | /// let mut map = LinkedHashMap::::new(); 1587 | /// 1588 | /// assert_eq!("foo", map.entry("foo".to_string()).key()); 1589 | /// ``` 1590 | pub fn key(&self) -> &K { 1591 | &self.key 1592 | } 1593 | 1594 | /// Sets the value of the entry with the VacantEntry's key, 1595 | /// and returns a mutable reference to it 1596 | pub fn insert(self, value: V) -> &'a mut V { 1597 | self.map.ensure_guard_node(); 1598 | 1599 | let node = if self.map.free.is_null() { 1600 | Box::into_raw(Box::new(Node::new(self.key, value))) 1601 | } else { 1602 | // use a recycled box 1603 | unsafe { 1604 | let free = self.map.free; 1605 | self.map.free = (*free).next; 1606 | ptr::write(free, Node::new(self.key, value)); 1607 | free 1608 | } 1609 | }; 1610 | 1611 | let keyref = unsafe { &(*node).key }; 1612 | 1613 | self.map.attach(node); 1614 | 1615 | let ret = self.map.map.entry(KeyRef { k: keyref }).or_insert(node); 1616 | unsafe { &mut (**ret).value } 1617 | } 1618 | } 1619 | --------------------------------------------------------------------------------