slotmap_careful/
key_data.rs

1//! Hacks to extract the version and index from a slotmap key, using serde.
2//!
3//! This approach may fail in the future if `slotmap` changes its serde output;
4//! but that would probably break a bunch other tools that depend on `slotmap`.
5//!
6//! ## Performance
7//!
8//! This serde-based approach might look inefficient, but the compiler is smart:
9//! it can inline all of the code and turn `key_data_parts` into direct data lookups.
10//!
11//! (Note that this performance property requires us to use `opt-level = 2` for this crate,
12//! in contrast with the rest of Arti, which currently prefers `opt-level = "s"`.)
13//!
14//!
15//! To conform that performance is likely acceptable, run
16//! `cargo asm slotmap_careful::key_data::key_data_parts`,
17//! and confirm that the result would fit on a napkin.
18use serde::{
19    ser::{Impossible, SerializeStruct},
20    Serialize,
21};
22use slotmap::Key;
23
24/// Return the version encoded in `key`.
25///
26/// (This version that starts with 0 when a slot is first created, and increments by 1 every
27/// time the slot is re-used.  It cannot grow larger than `0x7fff_ffff`.)
28pub(crate) fn key_version_serde<K: Key>(key: K) -> u32 {
29    key_data_parts(key.data())
30        .expect("Slotmap has changed its serde format")
31        .0
32        >> 1
33}
34
35/// Decode a `slotmap::KeyData` into its `version` and `index` components.
36///
37/// Note that the `version` value here will include the trailing LSB=1 value,
38/// to indicate that it is for an occupied slot.
39/// The caller should right-shift the version result by 1
40/// to get the actual "version" of the slot
41/// (as we define "version"  in the rest of this crate).
42pub(crate) fn key_data_parts(key_data: slotmap::KeyData) -> Result<(u32, u32), Failed> {
43    let mut s = Ser {
44        version: None,
45        index: None,
46    };
47
48    key_data.serialize(&mut s)?;
49    Ok((s.version.ok_or(Failed)?, s.index.ok_or(Failed)?))
50}
51
52/// Serializer for slotmap::KeyData, to extract the version and index of a key.
53struct Ser {
54    /// If present, a version we have found.
55    version: Option<u32>,
56    /// If present, a slot index we have found.
57    index: Option<u32>,
58}
59
60/// An unexpected failure from serializing a key.
61#[derive(Clone, Debug, thiserror::Error)]
62#[error("slotmap keydata did not serialize as expected")]
63pub(crate) struct Failed;
64
65impl serde::ser::Error for Failed {
66    fn custom<T>(_msg: T) -> Self
67    where
68        T: std::fmt::Display,
69    {
70        Failed
71    }
72}
73
74#[allow(unused_variables)] // for all the function arguments we'll ignore
75impl<'a> serde::Serializer for &'a mut Ser {
76    type Ok = ();
77    type Error = Failed;
78
79    type SerializeSeq = Impossible<(), Failed>;
80    type SerializeTuple = Impossible<(), Failed>;
81    type SerializeTupleStruct = Impossible<(), Failed>;
82    type SerializeTupleVariant = Impossible<(), Failed>;
83    type SerializeMap = Impossible<(), Failed>;
84    type SerializeStruct = Self;
85    type SerializeStructVariant = Impossible<(), Failed>;
86
87    fn serialize_struct(
88        self,
89        name: &'static str,
90        len: usize,
91    ) -> Result<Self::SerializeStruct, Self::Error> {
92        Ok(self)
93    }
94
95    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
96        Err(Failed)
97    }
98    shared_no_ops! {}
99}
100
101impl<'a> SerializeStruct for &'a mut Ser {
102    type Ok = ();
103
104    type Error = Failed;
105
106    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
107    where
108        T: ?Sized + Serialize,
109    {
110        if key == "version" {
111            self.version = Some(value.serialize(&mut SerU32)?);
112        } else if key == "idx" {
113            self.index = Some(value.serialize(&mut SerU32)?);
114        }
115
116        Ok(())
117    }
118
119    fn end(self) -> Result<Self::Ok, Self::Error> {
120        Ok(())
121    }
122}
123
124/// Serializer that extracts a u32, and rejects anything else.
125struct SerU32;
126
127#[allow(unused_variables)] // for all the function arguments we'll ignore
128impl<'a> serde::Serializer for &'a mut SerU32 {
129    type Ok = u32;
130    type Error = Failed;
131
132    type SerializeSeq = Impossible<u32, Failed>;
133    type SerializeTuple = Impossible<u32, Failed>;
134    type SerializeTupleStruct = Impossible<u32, Failed>;
135    type SerializeTupleVariant = Impossible<u32, Failed>;
136    type SerializeMap = Impossible<u32, Failed>;
137    type SerializeStruct = Impossible<u32, Failed>;
138    type SerializeStructVariant = Impossible<u32, Failed>;
139
140    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
141        Ok(v)
142    }
143
144    fn serialize_struct(
145        self,
146        name: &'static str,
147        len: usize,
148    ) -> Result<Self::SerializeStruct, Self::Error> {
149        Err(Failed)
150    }
151
152    shared_no_ops! {}
153}
154
155/// Helper: Define the common members of `Ser` and `SerU32`.
156///
157/// (These are just a bunch of methods that return `Err(Failed)`)
158macro_rules! shared_no_ops {
159    {} => {
160
161        fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
162            Err(Failed)
163        }
164        fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
165            Err(Failed)
166        }
167        fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
168            Err(Failed)
169        }
170        fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
171            Err(Failed)
172        }
173        fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
174            Err(Failed)
175        }
176        fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
177            Err(Failed)
178        }
179        fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
180            Err(Failed)
181        }
182        fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
183            Err(Failed)
184        }
185        fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
186            Err(Failed)
187        }
188        fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
189            Err(Failed)
190        }
191        fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
192            Err(Failed)
193        }
194        fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
195            Err(Failed)
196        }
197        fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
198            Err(Failed)
199        }
200        fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
201            Err(Failed)
202        }
203        fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
204        where
205            T: ?Sized + Serialize,
206        {
207            Err(Failed)
208        }
209        fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
210            Err(Failed)
211        }
212        fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
213            Err(Failed)
214        }
215        fn serialize_unit_variant(
216            self,
217            name: &'static str,
218            variant_index: u32,
219            variant: &'static str,
220        ) -> Result<Self::Ok, Self::Error> {
221            Err(Failed)
222        }
223        fn serialize_newtype_struct<T>(
224            self,
225            name: &'static str,
226            value: &T,
227        ) -> Result<Self::Ok, Self::Error>
228        where
229            T: ?Sized + Serialize,
230        {
231            Err(Failed)
232        }
233        fn serialize_newtype_variant<T>(
234            self,
235            name: &'static str,
236            variant_index: u32,
237            variant: &'static str,
238            value: &T,
239        ) -> Result<Self::Ok, Self::Error>
240        where
241            T: ?Sized + Serialize,
242        {
243            Err(Failed)
244        }
245        fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
246            Err(Failed)
247        }
248        fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
249            Err(Failed)
250        }
251        fn serialize_tuple_struct(
252            self,
253            name: &'static str,
254            len: usize,
255        ) -> Result<Self::SerializeTupleStruct, Self::Error> {
256            Err(Failed)
257        }
258        fn serialize_tuple_variant(
259            self,
260            name: &'static str,
261            variant_index: u32,
262            variant: &'static str,
263            len: usize,
264        ) -> Result<Self::SerializeTupleVariant, Self::Error> {
265            Err(Failed)
266        }
267        fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
268            Err(Failed)
269        }
270        fn serialize_struct_variant(
271            self,
272            name: &'static str,
273            variant_index: u32,
274            variant: &'static str,
275            len: usize,
276        ) -> Result<Self::SerializeStructVariant, Self::Error> {
277            Err(Failed)
278        }
279    }
280}
281use shared_no_ops;