indexmap_amortized/lib.rs
1// We *mostly* avoid unsafe code, but `map::core::raw` allows it to use `RawTable` buckets.
2#![deny(unsafe_code)]
3#![warn(rust_2018_idioms)]
4#![doc(html_root_url = "https://docs.rs/indexmap/1/")]
5#![no_std]
6
7//! A variant of the `indexmap` crate that amortizes the cost of resizes.
8//!
9//! [`IndexMap`] is a hash table where the iteration order of the key-value
10//! pairs is independent of the hash values of the keys.
11//!
12//! [`IndexSet`] is a corresponding hash set using the same implementation and
13//! with similar properties.
14//!
15//! [`IndexMap`]: map/struct.IndexMap.html
16//! [`IndexSet`]: set/struct.IndexSet.html
17//!
18//! ### Amortization
19//!
20//! This crate is an ongoing fork of [`indexmap`] that amortizes the cost of resizes.
21//! If you're unsure if you need this, take a look at the documentation of [`griddle`]
22//! and [`atone`], which provide the underlying amortization.
23//!
24//! [`indexmap`]: https://github.com/bluss/indexmap/
25//! [`griddle`]: https://github.com/jonhoo/griddle/
26//! [`atone`]: https://github.com/jonhoo/atone/
27//!
28//! ### Feature Highlights
29//!
30//! [`IndexMap`] and [`IndexSet`] are drop-in compatible with the std `HashMap`
31//! and `HashSet`, but they also have some features of note:
32//!
33//! - The ordering semantics (see their documentation for details)
34//! - Sorting methods and the [`.pop()`][IndexMap::pop] methods.
35//! - The [`Equivalent`] trait, which offers more flexible equality definitions
36//! between borrowed and owned versions of keys.
37//! - The [`MutableKeys`][map::MutableKeys] trait, which gives opt-in mutable
38//! access to hash map keys.
39//!
40//! ### Alternate Hashers
41//!
42//! [`IndexMap`] and [`IndexSet`] have a default hasher type `S = RandomState`,
43//! just like the standard `HashMap` and `HashSet`, which is resistant to
44//! HashDoS attacks but not the most performant. Type aliases can make it easier
45//! to use alternate hashers:
46//!
47//! ```
48//! use fnv::FnvBuildHasher;
49//! use fxhash::FxBuildHasher;
50//! use indexmap_amortized::{IndexMap, IndexSet};
51//!
52//! type FnvIndexMap<K, V> = IndexMap<K, V, FnvBuildHasher>;
53//! type FnvIndexSet<T> = IndexSet<T, FnvBuildHasher>;
54//!
55//! type FxIndexMap<K, V> = IndexMap<K, V, FxBuildHasher>;
56//! type FxIndexSet<T> = IndexSet<T, FxBuildHasher>;
57//!
58//! let std: IndexSet<i32> = (0..100).collect();
59//! let fnv: FnvIndexSet<i32> = (0..100).collect();
60//! let fx: FxIndexSet<i32> = (0..100).collect();
61//! assert_eq!(std, fnv);
62//! assert_eq!(std, fx);
63//! ```
64//!
65//! ### Rust Version
66//!
67//! This version of indexmap requires Rust 1.48 or later.
68//! This version of indexmap requires Rust 1.48+.
69//!
70//! The indexmap 1.x release series will use a carefully considered version
71//! upgrade policy, where in a later 1.x version, we will raise the minimum
72//! required Rust version.
73//!
74//! ## No Standard Library Targets
75//!
76//! This crate supports being built without `std`, requiring
77//! `alloc` instead. This is enabled automatically when it is detected that
78//! `std` is not available. There is no crate feature to enable/disable to
79//! trigger this. It can be tested by building for a std-less target.
80//!
81//! - Creating maps and sets using [`new`][IndexMap::new] and
82//! [`with_capacity`][IndexMap::with_capacity] is unavailable without `std`.
83//! Use methods [`IndexMap::default`][def],
84//! [`with_hasher`][IndexMap::with_hasher],
85//! [`with_capacity_and_hasher`][IndexMap::with_capacity_and_hasher] instead.
86//! A no-std compatible hasher will be needed as well, for example
87//! from the crate `twox-hash`.
88//! - Macros [`indexmap!`] and [`indexset!`] are unavailable without `std`.
89//!
90//! [def]: map/struct.IndexMap.html#impl-Default
91
92#[cfg(not(has_std))]
93extern crate alloc;
94
95#[cfg(has_std)]
96#[macro_use]
97extern crate std;
98
99#[cfg(not(has_std))]
100#[allow(unused_imports)]
101use alloc::vec::{self, Vec};
102
103#[cfg(has_std)]
104#[allow(unused_imports)]
105use std::vec::{self, Vec};
106
107#[macro_use]
108mod macros;
109mod equivalent;
110mod mutable_keys;
111#[cfg(feature = "serde")]
112mod serde;
113#[cfg(feature = "serde")]
114pub mod serde_seq;
115mod util;
116
117pub mod map;
118pub mod set;
119
120// Placed after `map` and `set` so new `rayon` methods on the types
121// are documented after the "normal" methods.
122#[cfg(feature = "rayon")]
123mod rayon;
124
125pub use crate::equivalent::Equivalent;
126pub use crate::map::IndexMap;
127pub use crate::set::IndexSet;
128
129// shared private items
130
131type EntryVec<T> = atone::Vc<T>;
132
133/// Hash value newtype. Not larger than usize, since anything larger
134/// isn't used for selecting position anyway.
135#[derive(Clone, Copy, Debug, PartialEq)]
136struct HashValue(usize);
137
138impl HashValue {
139 #[inline(always)]
140 fn get(self) -> u64 {
141 self.0 as u64
142 }
143}
144
145#[derive(Copy, Debug)]
146struct Bucket<K, V> {
147 hash: HashValue,
148 key: K,
149 value: V,
150}
151
152impl<K, V> Clone for Bucket<K, V>
153where
154 K: Clone,
155 V: Clone,
156{
157 fn clone(&self) -> Self {
158 Bucket {
159 hash: self.hash,
160 key: self.key.clone(),
161 value: self.value.clone(),
162 }
163 }
164
165 fn clone_from(&mut self, other: &Self) {
166 self.hash = other.hash;
167 self.key.clone_from(&other.key);
168 self.value.clone_from(&other.value);
169 }
170}
171
172impl<K, V> Bucket<K, V> {
173 // field accessors -- used for `f` instead of closures in `.map(f)`
174 fn key_ref(&self) -> &K {
175 &self.key
176 }
177 fn value_ref(&self) -> &V {
178 &self.value
179 }
180 fn value_mut(&mut self) -> &mut V {
181 &mut self.value
182 }
183 fn key(self) -> K {
184 self.key
185 }
186 fn key_value(self) -> (K, V) {
187 (self.key, self.value)
188 }
189 fn refs(&self) -> (&K, &V) {
190 (&self.key, &self.value)
191 }
192 fn ref_mut(&mut self) -> (&K, &mut V) {
193 (&self.key, &mut self.value)
194 }
195 fn muts(&mut self) -> (&mut K, &mut V) {
196 (&mut self.key, &mut self.value)
197 }
198}
199
200trait Entries {
201 type Entry;
202 fn into_entries(self) -> EntryVec<Self::Entry>;
203 fn as_entries(&self) -> &EntryVec<Self::Entry>;
204 fn as_entries_mut(&mut self) -> &mut EntryVec<Self::Entry>;
205 fn with_entries<F>(&mut self, f: F)
206 where
207 F: FnOnce(&mut EntryVec<Self::Entry>);
208}