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.
18
use serde::{
19
    ser::{Impossible, SerializeStruct},
20
    Serialize,
21
};
22
use 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`.)
28
174098
pub(crate) fn key_version_serde<K: Key>(key: K) -> u32 {
29
174098
    key_data_parts(key.data())
30
174098
        .expect("Slotmap has changed its serde format")
31
174098
        .0
32
174098
        >> 1
33
174098
}
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).
42
431229
pub(crate) fn key_data_parts(key_data: slotmap::KeyData) -> Result<(u32, u32), Failed> {
43
431229
    let mut s = Ser {
44
431229
        version: None,
45
431229
        index: None,
46
431229
    };
47
431229

            
48
431229
    key_data.serialize(&mut s)?;
49
431229
    Ok((s.version.ok_or(Failed)?, s.index.ok_or(Failed)?))
50
431229
}
51

            
52
/// Serializer for slotmap::KeyData, to extract the version and index of a key.
53
struct 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")]
63
pub(crate) struct Failed;
64

            
65
impl 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
75
impl<'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
431229
    fn serialize_struct(
88
431229
        self,
89
431229
        name: &'static str,
90
431229
        len: usize,
91
431229
    ) -> Result<Self::SerializeStruct, Self::Error> {
92
431229
        Ok(self)
93
431229
    }
94

            
95
    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
96
        Err(Failed)
97
    }
98
    shared_no_ops! {}
99
}
100

            
101
impl<'a> SerializeStruct for &'a mut Ser {
102
    type Ok = ();
103

            
104
    type Error = Failed;
105

            
106
862458
    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
107
862458
    where
108
862458
        T: ?Sized + Serialize,
109
862458
    {
110
862458
        if key == "version" {
111
431229
            self.version = Some(value.serialize(&mut SerU32)?);
112
431229
        } else if key == "idx" {
113
431229
            self.index = Some(value.serialize(&mut SerU32)?);
114
        }
115

            
116
862458
        Ok(())
117
862458
    }
118

            
119
431229
    fn end(self) -> Result<Self::Ok, Self::Error> {
120
431229
        Ok(())
121
431229
    }
122
}
123

            
124
/// Serializer that extracts a u32, and rejects anything else.
125
struct SerU32;
126

            
127
#[allow(unused_variables)] // for all the function arguments we'll ignore
128
impl<'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
862458
    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
141
862458
        Ok(v)
142
862458
    }
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)`)
158
macro_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
}
281
use shared_no_ops;