Skip to content

Commit e367cd3

Browse files
authored
Implement serde support for our OOM-handling IndexMap (#12580)
1 parent e9a6def commit e367cd3

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

crates/environ/src/collections/index_map.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::{
44
cmp::Ordering,
55
fmt,
66
hash::{BuildHasher, Hash},
7+
marker::PhantomData,
78
mem,
89
ops::{Index, IndexMut, RangeBounds},
910
};
@@ -59,6 +60,70 @@ impl<K, V, S> From<indexmap::IndexMap<K, V, S>> for IndexMap<K, V, S> {
5960
}
6061
}
6162

63+
impl<K, V, H> serde::ser::Serialize for IndexMap<K, V, H>
64+
where
65+
K: serde::ser::Serialize,
66+
V: serde::ser::Serialize,
67+
{
68+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69+
where
70+
S: serde::Serializer,
71+
{
72+
use serde::ser::SerializeMap as _;
73+
let mut map = serializer.serialize_map(Some(self.len()))?;
74+
for (k, v) in self {
75+
map.serialize_entry(k, v)?;
76+
}
77+
map.end()
78+
}
79+
}
80+
81+
impl<'de, K, V> serde::de::Deserialize<'de> for IndexMap<K, V>
82+
where
83+
K: serde::de::Deserialize<'de> + Hash + Eq,
84+
V: serde::de::Deserialize<'de>,
85+
{
86+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87+
where
88+
D: serde::Deserializer<'de>,
89+
{
90+
struct Visitor<K, V>(PhantomData<fn() -> IndexMap<K, V>>);
91+
92+
impl<'de, K, V> serde::de::Visitor<'de> for Visitor<K, V>
93+
where
94+
K: serde::de::Deserialize<'de> + Hash + Eq,
95+
V: serde::de::Deserialize<'de>,
96+
{
97+
type Value = IndexMap<K, V>;
98+
99+
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
100+
f.write_str("an `IndexMap`")
101+
}
102+
103+
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
104+
where
105+
A: serde::de::MapAccess<'de>,
106+
{
107+
use serde::de::Error as _;
108+
109+
let mut result = IndexMap::<K, V>::new();
110+
111+
if let Some(len) = map.size_hint() {
112+
result.reserve(len).map_err(|oom| A::Error::custom(oom))?;
113+
}
114+
115+
while let Some((k, v)) = map.next_entry::<K, V>()? {
116+
result.insert(k, v).map_err(|oom| A::Error::custom(oom))?;
117+
}
118+
119+
Ok(result)
120+
}
121+
}
122+
123+
deserializer.deserialize_map(Visitor(PhantomData))
124+
}
125+
}
126+
62127
impl<K, V> IndexMap<K, V> {
63128
/// Same as [`indexmap::IndexMap::new`].
64129
pub fn new() -> Self {

0 commit comments

Comments
 (0)