indexmap/
lib.rs

1#![no_std]
2
3//! [`IndexMap`] is a hash table where the iteration order of the key-value
4//! pairs is independent of the hash values of the keys.
5//!
6//! [`IndexSet`] is a corresponding hash set using the same implementation and
7//! with similar properties.
8//!
9//! ### Highlights
10//!
11//! [`IndexMap`] and [`IndexSet`] are drop-in compatible with the std `HashMap`
12//! and `HashSet`, but they also have some features of note:
13//!
14//! - The ordering semantics (see their documentation for details)
15//! - Sorting methods and the [`.pop()`][IndexMap::pop] methods.
16//! - The [`Equivalent`] trait, which offers more flexible equality definitions
17//!   between borrowed and owned versions of keys.
18//! - The [`MutableKeys`][map::MutableKeys] trait, which gives opt-in mutable
19//!   access to map keys, and [`MutableValues`][set::MutableValues] for sets.
20//!
21//! ### Feature Flags
22//!
23//! To reduce the amount of compiled code in the crate by default, certain
24//! features are gated behind [feature flags]. These allow you to opt in to (or
25//! out of) functionality. Below is a list of the features available in this
26//! crate.
27//!
28//! * `std`: Enables features which require the Rust standard library. For more
29//!   information see the section on [`no_std`].
30//! * `rayon`: Enables parallel iteration and other parallel methods.
31//! * `serde`: Adds implementations for [`Serialize`] and [`Deserialize`]
32//!   to [`IndexMap`] and [`IndexSet`]. Alternative implementations for
33//!   (de)serializing [`IndexMap`] as an ordered sequence are available in the
34//!   [`map::serde_seq`] module.
35//! * `arbitrary`: Adds implementations for the [`arbitrary::Arbitrary`] trait
36//!   to [`IndexMap`] and [`IndexSet`].
37//! * `quickcheck`: Adds implementations for the [`quickcheck::Arbitrary`] trait
38//!   to [`IndexMap`] and [`IndexSet`].
39//! * `borsh` (**deprecated**): Adds implementations for [`BorshSerialize`] and
40//!   [`BorshDeserialize`] to [`IndexMap`] and [`IndexSet`]. Due to a cyclic
41//!   dependency that arose between [`borsh`] and `indexmap`, `borsh v1.5.6`
42//!   added an `indexmap` feature that should be used instead of enabling the
43//!   feature here.
44//!
45//! _Note: only the `std` feature is enabled by default._
46//!
47//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
48//! [`no_std`]: #no-standard-library-targets
49//! [`Serialize`]: `::serde_core::Serialize`
50//! [`Deserialize`]: `::serde_core::Deserialize`
51//! [`BorshSerialize`]: `::borsh::BorshSerialize`
52//! [`BorshDeserialize`]: `::borsh::BorshDeserialize`
53//! [`borsh`]: `::borsh`
54//! [`arbitrary::Arbitrary`]: `::arbitrary::Arbitrary`
55//! [`quickcheck::Arbitrary`]: `::quickcheck::Arbitrary`
56//!
57//! ### Alternate Hashers
58//!
59//! [`IndexMap`] and [`IndexSet`] have a default hasher type
60//! [`S = RandomState`][std::hash::RandomState],
61//! just like the standard `HashMap` and `HashSet`, which is resistant to
62//! HashDoS attacks but not the most performant. Type aliases can make it easier
63//! to use alternate hashers:
64//!
65//! ```
66//! use fnv::FnvBuildHasher;
67//! use indexmap::{IndexMap, IndexSet};
68//!
69//! type FnvIndexMap<K, V> = IndexMap<K, V, FnvBuildHasher>;
70//! type FnvIndexSet<T> = IndexSet<T, FnvBuildHasher>;
71//!
72//! let std: IndexSet<i32> = (0..100).collect();
73//! let fnv: FnvIndexSet<i32> = (0..100).collect();
74//! assert_eq!(std, fnv);
75//! ```
76//!
77//! ### Rust Version
78//!
79//! This version of indexmap requires Rust 1.82 or later.
80//!
81//! The indexmap 2.x release series will use a carefully considered version
82//! upgrade policy, where in a later 2.x version, we will raise the minimum
83//! required Rust version.
84//!
85//! ## No Standard Library Targets
86//!
87//! This crate supports being built without `std`, requiring `alloc` instead.
88//! This is chosen by disabling the default "std" cargo feature, by adding
89//! `default-features = false` to your dependency specification.
90//!
91//! - Creating maps and sets using [`new`][IndexMap::new] and
92//!   [`with_capacity`][IndexMap::with_capacity] is unavailable without `std`.
93//!   Use methods [`IndexMap::default`], [`with_hasher`][IndexMap::with_hasher],
94//!   [`with_capacity_and_hasher`][IndexMap::with_capacity_and_hasher] instead.
95//!   A no-std compatible hasher will be needed as well, for example
96//!   from the crate `twox-hash`.
97//! - Macros [`indexmap!`] and [`indexset!`] are unavailable without `std`. Use
98//!   the macros [`indexmap_with_default!`] and [`indexset_with_default!`] instead.
99
100#![cfg_attr(docsrs, feature(doc_cfg))]
101
102extern crate alloc;
103
104#[cfg(feature = "std")]
105#[macro_use]
106extern crate std;
107
108mod arbitrary;
109#[macro_use]
110mod macros;
111#[cfg(feature = "borsh")]
112mod borsh;
113#[cfg(feature = "serde")]
114mod serde;
115#[cfg(feature = "sval")]
116mod sval;
117mod util;
118
119pub mod map;
120pub mod set;
121
122// Placed after `map` and `set` so new `rayon` methods on the types
123// are documented after the "normal" methods.
124#[cfg(feature = "rayon")]
125mod rayon;
126
127pub use crate::map::IndexMap;
128pub use crate::set::IndexSet;
129pub use equivalent::Equivalent;
130
131// shared private items
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 value(self) -> V {
187        self.value
188    }
189    fn key_value(self) -> (K, V) {
190        (self.key, self.value)
191    }
192    fn refs(&self) -> (&K, &V) {
193        (&self.key, &self.value)
194    }
195    fn ref_mut(&mut self) -> (&K, &mut V) {
196        (&self.key, &mut self.value)
197    }
198    fn muts(&mut self) -> (&mut K, &mut V) {
199        (&mut self.key, &mut self.value)
200    }
201}
202
203/// The error type for [`try_reserve`][IndexMap::try_reserve] methods.
204#[derive(Clone, PartialEq, Eq, Debug)]
205pub struct TryReserveError {
206    kind: TryReserveErrorKind,
207}
208
209#[derive(Clone, PartialEq, Eq, Debug)]
210enum TryReserveErrorKind {
211    // The standard library's kind is currently opaque to us, otherwise we could unify this.
212    Std(alloc::collections::TryReserveError),
213    CapacityOverflow,
214    AllocError { layout: alloc::alloc::Layout },
215}
216
217// These are not `From` so we don't expose them in our public API.
218impl TryReserveError {
219    fn from_alloc(error: alloc::collections::TryReserveError) -> Self {
220        Self {
221            kind: TryReserveErrorKind::Std(error),
222        }
223    }
224
225    fn from_hashbrown(error: hashbrown::TryReserveError) -> Self {
226        Self {
227            kind: match error {
228                hashbrown::TryReserveError::CapacityOverflow => {
229                    TryReserveErrorKind::CapacityOverflow
230                }
231                hashbrown::TryReserveError::AllocError { layout } => {
232                    TryReserveErrorKind::AllocError { layout }
233                }
234            },
235        }
236    }
237}
238
239impl core::fmt::Display for TryReserveError {
240    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
241        let reason = match &self.kind {
242            TryReserveErrorKind::Std(e) => return core::fmt::Display::fmt(e, f),
243            TryReserveErrorKind::CapacityOverflow => {
244                " because the computed capacity exceeded the collection's maximum"
245            }
246            TryReserveErrorKind::AllocError { .. } => {
247                " because the memory allocator returned an error"
248            }
249        };
250        f.write_str("memory allocation failed")?;
251        f.write_str(reason)
252    }
253}
254
255impl core::error::Error for TryReserveError {}
256
257// NOTE: This is copied from the slice module in the std lib.
258/// The error type returned by [`get_disjoint_indices_mut`][`IndexMap::get_disjoint_indices_mut`].
259///
260/// It indicates one of two possible errors:
261/// - An index is out-of-bounds.
262/// - The same index appeared multiple times in the array.
263//    (or different but overlapping indices when ranges are provided)
264#[derive(Debug, Clone, PartialEq, Eq)]
265pub enum GetDisjointMutError {
266    /// An index provided was out-of-bounds for the slice.
267    IndexOutOfBounds,
268    /// Two indices provided were overlapping.
269    OverlappingIndices,
270}
271
272impl core::fmt::Display for GetDisjointMutError {
273    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
274        let msg = match self {
275            GetDisjointMutError::IndexOutOfBounds => "an index is out of bounds",
276            GetDisjointMutError::OverlappingIndices => "there were overlapping indices",
277        };
278
279        core::fmt::Display::fmt(msg, f)
280    }
281}
282
283impl core::error::Error for GetDisjointMutError {}