1use core::hash::{BuildHasher, Hash};
2
3use indexmap::IndexMap;
4use itertools::zip_eq;
5
6type BHImpl = hashbrown::DefaultHashBuilder;
10
11#[derive(Clone, Debug)]
12#[cfg_attr(
13 feature = "serde",
14 derive(serde::Deserialize, serde::Serialize),
15 serde(transparent),
16 serde(bound(
17 serialize = "Key: serde::Serialize, Value: serde::Serialize",
18 deserialize = "Key: serde::Deserialize<'de> + Hash + Eq, Value: serde::Deserialize<'de>, \
19 BH: BuildHasher + Default"
20 ))
21)]
22pub struct OrderedHashMap<Key, Value, BH = BHImpl>(IndexMap<Key, Value, BH>);
23
24impl<Key, Value, BH> core::ops::Deref for OrderedHashMap<Key, Value, BH> {
25 type Target = IndexMap<Key, Value, BH>;
26
27 fn deref(&self) -> &Self::Target {
28 &self.0
29 }
30}
31
32impl<Key, Value, BH> core::ops::DerefMut for OrderedHashMap<Key, Value, BH> {
33 fn deref_mut(&mut self) -> &mut Self::Target {
34 &mut self.0
35 }
36}
37
38#[cfg(feature = "salsa")]
39unsafe impl<Key: salsa::SalsaValue + Eq + Hash, Value: salsa::SalsaValue, BH: BuildHasher>
40 salsa::SalsaValue for OrderedHashMap<Key, Value, BH>
41{
42}
43
44impl<Key, Value, BH: Default> Default for OrderedHashMap<Key, Value, BH> {
45 #[cfg(feature = "std")]
46 fn default() -> Self {
47 Self(Default::default())
48 }
49 #[cfg(not(feature = "std"))]
50 fn default() -> Self {
51 Self(IndexMap::with_hasher(Default::default()))
52 }
53}
54
55impl<Key, Value, BH> OrderedHashMap<Key, Value, BH> {
56 pub fn is_empty(&self) -> bool {
58 self.0.is_empty()
59 }
60}
61
62impl<Key, Value, BH: BuildHasher + Default> OrderedHashMap<Key, Value, BH> {
63 pub fn with_capacity(capacity: usize) -> Self {
65 Self(IndexMap::with_capacity_and_hasher(capacity, Default::default()))
66 }
67}
68
69impl<Key: Eq + Hash, Value, BH: BuildHasher> OrderedHashMap<Key, Value, BH> {
70 pub fn eq_unordered(&self, other: &Self) -> bool
72 where
73 Value: Eq,
74 {
75 if self.len() != other.len() {
76 return false;
77 };
78 self.iter().all(|(k, v)| other.get(k) == Some(v))
79 }
80}
81
82pub type Entry<'a, Key, Value> = indexmap::map::Entry<'a, Key, Value>;
84
85impl<Key, Value, BH> IntoIterator for OrderedHashMap<Key, Value, BH> {
86 type Item = (Key, Value);
87 type IntoIter = indexmap::map::IntoIter<Key, Value>;
88 fn into_iter(self) -> Self::IntoIter {
89 let OrderedHashMap(inner) = self;
90 inner.into_iter()
91 }
92}
93
94impl<Key: Eq, Value: Eq, BH> PartialEq for OrderedHashMap<Key, Value, BH> {
95 fn eq(&self, other: &Self) -> bool {
96 if self.len() != other.len() {
97 return false;
98 };
99
100 zip_eq(self.iter(), other.iter()).all(|(a, b)| a == b)
101 }
102}
103
104impl<Key: Hash + Eq, Value: Eq, BH: BuildHasher> Eq for OrderedHashMap<Key, Value, BH> {}
105
106impl<Key: Hash, Value: Hash, BH> Hash for OrderedHashMap<Key, Value, BH> {
107 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
108 self.len().hash(state);
109 for e in self.iter() {
110 e.hash(state);
111 }
112 }
113}
114
115impl<Key: Hash + Eq, Value, BH: BuildHasher + Default> FromIterator<(Key, Value)>
116 for OrderedHashMap<Key, Value, BH>
117{
118 fn from_iter<T: IntoIterator<Item = (Key, Value)>>(iter: T) -> Self {
119 Self(iter.into_iter().collect())
120 }
121}
122
123impl<Key: Hash + Eq, Value, BH: BuildHasher + Default, const N: usize> From<[(Key, Value); N]>
124 for OrderedHashMap<Key, Value, BH>
125{
126 fn from(init_map: [(Key, Value); N]) -> Self {
127 Self(IndexMap::from_iter(init_map))
128 }
129}
130
131#[cfg(feature = "serde")]
132mod impl_serde {
133 use indexmap::map::serde_seq;
134 use serde::{Deserialize, Deserializer, Serialize, Serializer};
135
136 use super::*;
137
138 pub fn serialize_ordered_hashmap_vec<K, V, BH, S>(
139 v: &OrderedHashMap<K, V, BH>,
140 serializer: S,
141 ) -> Result<S::Ok, S::Error>
142 where
143 S: Serializer,
144 K: Serialize + Hash + Eq,
145 V: Serialize,
146 {
147 serde_seq::serialize(&v.0, serializer)
148 }
149
150 pub fn deserialize_ordered_hashmap_vec<'de, K, V, BH: BuildHasher + Default, D>(
151 deserializer: D,
152 ) -> Result<OrderedHashMap<K, V, BH>, D::Error>
153 where
154 D: Deserializer<'de>,
155 K: Deserialize<'de> + Hash + Eq,
156 V: Deserialize<'de>,
157 {
158 Ok(OrderedHashMap(serde_seq::deserialize(deserializer)?))
159 }
160}
161#[cfg(feature = "serde")]
162pub use impl_serde::*;