Skip to content

Commit 4309fe3

Browse files
committed
Fix OOM-handling SecondaryMap's serialization/deserialization so that it matches cranelift_entity::SecondaryMap
1 parent 3621d3e commit 4309fe3

File tree

2 files changed

+125
-8
lines changed

2 files changed

+125
-8
lines changed

cranelift/entity/src/map.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ where
194194
Ok(())
195195
}
196196

197+
/// Get this map's underlying values as a slice.
198+
pub fn as_values_slice(&self) -> &[V] {
199+
&self.elems
200+
}
201+
202+
/// Get this map's default value.
203+
pub fn default_value(&self) -> &V {
204+
&self.default
205+
}
206+
197207
/// Slow path for `index_mut` which resizes the vector.
198208
#[cold]
199209
fn resize_for_index_mut(&mut self, i: usize) -> &mut V {

crates/environ/src/collections/secondary_map.rs

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{collections::Vec, error::OutOfMemory};
22
use core::{fmt, ops::Index};
33
use cranelift_entity::{EntityRef, SecondaryMap as Inner};
4-
use serde::ser::SerializeSeq;
54

65
/// Like [`cranelift_entity::SecondaryMap`] but all allocation is fallible.
76
pub struct SecondaryMap<K, V>
@@ -159,30 +158,138 @@ where
159158
impl<K, V> serde::ser::Serialize for SecondaryMap<K, V>
160159
where
161160
K: EntityRef,
162-
V: Clone + serde::ser::Serialize,
161+
V: Clone + PartialEq + serde::ser::Serialize,
163162
{
164163
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165164
where
166165
S: serde::Serializer,
167166
{
168-
let mut seq = serializer.serialize_seq(Some(self.capacity()))?;
169-
for elem in self.values() {
170-
seq.serialize_element(elem)?;
167+
use serde::ser::SerializeSeq as _;
168+
169+
// Ignore any trailing default values.
170+
let mut len = self.inner.as_values_slice().len();
171+
while len > 0 && &self[K::new(len - 1)] == self.inner.default_value() {
172+
len -= 1;
173+
}
174+
175+
// Plus one for the default value.
176+
let mut seq = serializer.serialize_seq(Some(len + 1))?;
177+
178+
// Always serialize the default value first.
179+
seq.serialize_element(self.inner.default_value())?;
180+
181+
for elem in self.values().take(len) {
182+
let elem = if elem == self.inner.default_value() {
183+
None
184+
} else {
185+
Some(elem)
186+
};
187+
seq.serialize_element(&elem)?;
171188
}
189+
172190
seq.end()
173191
}
174192
}
175193

176194
impl<'de, K, V> serde::de::Deserialize<'de> for SecondaryMap<K, V>
177195
where
178196
K: EntityRef,
179-
V: Clone + Default + serde::de::Deserialize<'de>,
197+
V: Clone + serde::de::Deserialize<'de>,
180198
{
181199
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
182200
where
183201
D: serde::Deserializer<'de>,
184202
{
185-
let values: Vec<V> = serde::de::Deserialize::deserialize(deserializer)?;
186-
Ok(Self::from(values))
203+
struct Visitor<K, V>(core::marker::PhantomData<fn() -> SecondaryMap<K, V>>)
204+
where
205+
K: EntityRef,
206+
V: Clone;
207+
208+
impl<'de, K, V> serde::de::Visitor<'de> for Visitor<K, V>
209+
where
210+
K: EntityRef,
211+
V: Clone + serde::de::Deserialize<'de>,
212+
{
213+
type Value = SecondaryMap<K, V>;
214+
215+
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
216+
f.write_str("struct SecondaryMap")
217+
}
218+
219+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
220+
where
221+
A: serde::de::SeqAccess<'de>,
222+
{
223+
// Minus one to account for the default element, which is always
224+
// the first in the sequence.
225+
let size_hint = seq.size_hint().and_then(|n| n.checked_sub(1));
226+
227+
let Some(default) = seq.next_element::<V>()? else {
228+
return Err(serde::de::Error::custom("Default value required"));
229+
};
230+
231+
let mut map = SecondaryMap::<K, V>::with_default(default.clone());
232+
233+
if let Some(n) = size_hint {
234+
map.resize(n).map_err(|oom| serde::de::Error::custom(oom))?;
235+
}
236+
237+
let mut idx = 0;
238+
while let Some(val) = seq.next_element::<Option<V>>()? {
239+
let key = K::new(idx);
240+
let val = match val {
241+
None => default.clone(),
242+
Some(val) => val,
243+
};
244+
245+
map.insert(key, val)
246+
.map_err(|oom| serde::de::Error::custom(oom))?;
247+
248+
idx += 1;
249+
}
250+
251+
Ok(map)
252+
}
253+
}
254+
255+
deserializer.deserialize_seq(Visitor(core::marker::PhantomData))
256+
}
257+
}
258+
259+
#[cfg(test)]
260+
mod tests {
261+
use super::*;
262+
use crate::error::Result;
263+
use alloc::vec;
264+
use alloc::vec::Vec;
265+
266+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
267+
struct K(u32);
268+
crate::entity_impl!(K);
269+
270+
fn k(i: usize) -> K {
271+
K::new(i)
272+
}
273+
274+
#[test]
275+
fn serialize_deserialize() -> Result<()> {
276+
let mut map = SecondaryMap::<K, u32>::with_default(99);
277+
map.insert(k(0), 33)?;
278+
map.insert(k(1), 44)?;
279+
map.insert(k(2), 55)?;
280+
map.insert(k(3), 99)?;
281+
map.insert(k(4), 99)?;
282+
283+
let bytes = postcard::to_allocvec(&map)?;
284+
let map2: SecondaryMap<K, u32> = postcard::from_bytes(&bytes)?;
285+
286+
for i in 0..10 {
287+
assert_eq!(map[k(i)], map2[k(i)]);
288+
}
289+
290+
// Trailing default entries were omitted from the serialization.
291+
assert_eq!(map2.keys().collect::<Vec<_>>(), vec![k(0), k(1), k(2)]);
292+
293+
Ok(())
187294
}
188295
}

0 commit comments

Comments
 (0)