Coverage Report

Created: 2025-11-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/indexmap-2.12.0/src/lib.rs
Line
Count
Source
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
102
extern crate alloc;
103
104
#[cfg(feature = "std")]
105
#[macro_use]
106
extern crate std;
107
108
mod arbitrary;
109
#[macro_use]
110
mod macros;
111
#[cfg(feature = "borsh")]
112
mod borsh;
113
#[cfg(feature = "serde")]
114
mod serde;
115
#[cfg(feature = "sval")]
116
mod sval;
117
mod util;
118
119
pub mod map;
120
pub 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")]
125
mod rayon;
126
127
pub use crate::map::IndexMap;
128
pub use crate::set::IndexSet;
129
pub 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)]
136
struct HashValue(usize);
137
138
impl HashValue {
139
    #[inline(always)]
140
714k
    fn get(self) -> u64 {
141
714k
        self.0 as u64
142
714k
    }
143
}
144
145
#[derive(Copy, Debug)]
146
struct Bucket<K, V> {
147
    hash: HashValue,
148
    key: K,
149
    value: V,
150
}
151
152
impl<K, V> Clone for Bucket<K, V>
153
where
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
172
impl<K, V> Bucket<K, V> {
173
    // field accessors -- used for `f` instead of closures in `.map(f)`
174
475M
    fn key_ref(&self) -> &K {
175
475M
        &self.key
176
475M
    }
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Expression>, alloc::string::String>>::key_ref
<indexmap::Bucket<naga::ir::Type, ()>>::key_ref
Line
Count
Source
174
475M
    fn key_ref(&self) -> &K {
175
475M
        &self.key
176
475M
    }
<indexmap::Bucket<naga::front::wgsl::parse::ast::Dependency, ()>>::key_ref
Line
Count
Source
174
163
    fn key_ref(&self) -> &K {
175
163
        &self.key
176
163
    }
177
0
    fn value_ref(&self) -> &V {
178
0
        &self.value
179
0
    }
180
1
    fn value_mut(&mut self) -> &mut V {
181
1
        &mut self.value
182
1
    }
183
113
    fn key(self) -> K {
184
113
        self.key
185
113
    }
186
    fn value(self) -> V {
187
        self.value
188
    }
189
72.3k
    fn key_value(self) -> (K, V) {
190
72.3k
        (self.key, self.value)
191
72.3k
    }
<indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Expression>, alloc::string::String>>::key_value
Line
Count
Source
189
36.1k
    fn key_value(self) -> (K, V) {
190
36.1k
        (self.key, self.value)
191
36.1k
    }
<indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Expression>, (alloc::string::String, naga::span::Span)>>::key_value
Line
Count
Source
189
36.1k
    fn key_value(self) -> (K, V) {
190
36.1k
        (self.key, self.value)
191
36.1k
    }
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::GlobalVariable>, alloc::vec::Vec<alloc::string::String>>>::key_value
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Type>, alloc::vec::Vec<alloc::string::String>>>::key_value
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Constant>, alloc::vec::Vec<alloc::string::String>>>::key_value
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Function>, alloc::vec::Vec<alloc::string::String>>>::key_value
Unexecuted instantiation: <indexmap::Bucket<naga::diagnostic_filter::FilterableTriggeringRule, (naga::diagnostic_filter::Severity, naga::span::Span)>>::key_value
Unexecuted instantiation: <indexmap::Bucket<(naga::arena::handle::Handle<naga::ir::Type>, usize), alloc::vec::Vec<alloc::string::String>>>::key_value
192
36.1k
    fn refs(&self) -> (&K, &V) {
193
36.1k
        (&self.key, &self.value)
194
36.1k
    }
<indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Expression>, alloc::string::String>>::refs
Line
Count
Source
192
36.1k
    fn refs(&self) -> (&K, &V) {
193
36.1k
        (&self.key, &self.value)
194
36.1k
    }
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::GlobalVariable>, alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Type>, alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Constant>, alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<naga::arena::handle::Handle<naga::ir::Function>, alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<naga::diagnostic_filter::FilterableTriggeringRule, (naga::diagnostic_filter::Severity, naga::span::Span)>>::refs
<indexmap::Bucket<naga::ir::PredeclaredType, naga::arena::handle::Handle<naga::ir::Type>>>::refs
Line
Count
Source
192
1
    fn refs(&self) -> (&K, &V) {
193
1
        (&self.key, &self.value)
194
1
    }
Unexecuted instantiation: <indexmap::Bucket<(naga::arena::handle::Handle<naga::ir::Type>, usize), alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<usize, alloc::vec::Vec<alloc::string::String>>>::refs
Unexecuted instantiation: <indexmap::Bucket<u32, alloc::vec::Vec<(u32, petgraph::graphmap::CompactDirection)>>>::refs
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)]
205
pub struct TryReserveError {
206
    kind: TryReserveErrorKind,
207
}
208
209
#[derive(Clone, PartialEq, Eq, Debug)]
210
enum 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.
218
impl 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
239
impl 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
255
impl 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)]
265
pub 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
272
impl 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
283
impl core::error::Error for GetDisjointMutError {}