chiark / gitweb /
changelog: document further make-release changes
[otter.git] / support / slotmap-slot-idx.rs
1 // Copyright 2020-2021 Ian Jackson and contributors to Otter
2 // SPDX-License-Identifier: MIT-0 OR AGPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 #![allow(clippy::or_fun_call)]
6
7 //! Provides a [`get_idx_key`](trait.KeyDataExt.html#tymethod.get_idx_version) method on
8 //! `slotmap::KeyData`.  See [KeyDataExt::get_idx_version].
9
10 use crate::prelude::otter_base::misc::default;
11
12 /// Extension trait for `slotmap::KeyData`, providing `get_idx_version`.
13 ///
14 /// No-one is expected to implement this trait for anything else.
15 pub trait KeyDataExt {
16   /// Returns the slot index and version.  This is useful only in
17   /// unusual situations.
18   ///
19   /// At any one time, a slotmap has at most one entry with each
20   /// index.  The combination of index and version are unique across
21   /// time.  Indices are generally not significantly bigger than thw
22   /// maximum ever occupancy.  No other guarantees are made.
23   ///
24   /// For serialisation, use `serde` or `as_ffi`.
25   ///
26   /// ### panics: ###
27   ///
28   /// This function panics if the `slotmap::KeyData` `serde::ser::Serialize`
29   /// representation has changed too much.  This ought to be caught
30   /// by the tests, and would probably be a breaking change in the
31   /// underlying `slotmap` crate in any case.
32   ///
33   /// If you prefer to receive an error rather than panicing,
34   /// see [keydata_extract].
35   fn get_idx_version(self) -> (u32, u32);
36 }
37
38 impl KeyDataExt for slotmap::KeyData {
39   fn get_idx_version(self) -> (u32, u32) {
40     keydata_extract(self).expect(
41       "slotmap KeyData Serialize representation changed!"
42     )
43   }
44 }
45
46 /// Underlying extraction function.  Fails rather than panicing.
47 ///
48 /// Fails if the `slotmap::KeyData` `serde::ser::Serialize`
49 /// representation has changed too much.  Should not be able to fail
50 /// otherwise.
51 pub fn keydata_extract(key: slotmap::KeyData) -> Result<(u32, u32), Error> {
52   let mut m: MainExtractor = default();
53   key.serialize(&mut m)?;
54   Ok(( m.idx    .ok_or(error(line!()))?,
55        m.version.ok_or(error(line!()))? ))
56 }
57
58 #[derive(Debug)]
59 /// Problem with the `slotmap::KeyData` `Serialize` implementation.
60 ///
61 /// Not really helpful.  `Unexpected` gives the source line number
62 /// in `slotmap-slot-idx.rs`.  `WasCustomSerialize` threw the
63 /// actual error away.
64 pub enum Error {
65   WasCustomSerialize,
66   Unexpected(std::num::NonZeroU32),
67 }
68 impl std::error::Error for Error { }
69
70 //---------- implementation.  avert your eyes ----------
71
72 use std::convert::TryFrom;
73 use std::fmt;
74 use std::line;
75 use serde::ser::{self, *};
76
77 #[derive(Default)]
78 struct MainExtractor {
79   idx: Option<u32>,
80   version: Option<u32>,
81 }
82
83 struct ValueExtractor;
84
85 type R<Return> = Result<Return, Error>;
86 type ROk = R<()>;
87 use self::Error::*;
88
89 fn error(line: u32) -> Error { Unexpected(TryFrom::try_from(line).unwrap()) }
90 fn u<T>(line: u32) -> R<T> { Err(error(line)) }
91
92 type Imp = Impossible<(), Error>;
93 type RI = R<Imp>;
94
95 impl Serializer for &mut MainExtractor {
96   type Ok = ();
97   type Error = Error;
98
99   type SerializeStruct = Self;
100
101   type SerializeMap           = Imp;
102   type SerializeSeq           = Imp;
103   type SerializeTuple         = Imp;
104   type SerializeTupleStruct   = Imp;
105   type SerializeTupleVariant  = Imp;
106   type SerializeStructVariant = Imp;
107
108   fn serialize_struct(self, _:&str, _: usize) -> R<Self> { Ok(self) }
109
110   fn serialize_bool (self, _: bool )  -> ROk { u(line!()) }
111   fn serialize_i8   (self, _: i8   )  -> ROk { u(line!()) }
112   fn serialize_i16  (self, _: i16  )  -> ROk { u(line!()) }
113   fn serialize_i32  (self, _: i32  )  -> ROk { u(line!()) }
114   fn serialize_i64  (self, _: i64  )  -> ROk { u(line!()) }
115   fn serialize_u8   (self, _: u8   )  -> ROk { u(line!()) }
116   fn serialize_u16  (self, _: u16  )  -> ROk { u(line!()) }
117   fn serialize_u32  (self, _: u32  )  -> ROk { u(line!()) }
118   fn serialize_u64  (self, _: u64  )  -> ROk { u(line!()) }
119   fn serialize_f32  (self, _: f32  )  -> ROk { u(line!()) }
120   fn serialize_f64  (self, _: f64  )  -> ROk { u(line!()) }
121   fn serialize_char (self, _: char )  -> ROk { u(line!()) }
122   fn serialize_str  (self, _: &str )  -> ROk { u(line!()) }
123   fn serialize_bytes(self, _: &[u8 ]) -> ROk { u(line!()) }
124   fn serialize_none (self)            -> ROk { u(line!()) }
125   fn serialize_unit (self)            -> ROk { u(line!()) }
126
127   fn serialize_some<T>(self,                                   _: &T) -> ROk
128   where T: Serialize + ?Sized  { u(line!()) }
129   fn serialize_newtype_struct <T>(self, _:&str,                _: &T) -> ROk
130   where T: Serialize + ?Sized  { u(line!()) }
131   fn serialize_newtype_variant<T>(self, _:&str, _:u32, _:&str, _: &T) -> ROk
132   where T: Serialize + ?Sized  { u(line!()) }
133
134   fn serialize_unit_struct (self,_:&str             ) -> ROk { u(line!()) }
135   fn serialize_unit_variant(self,_:&str,_:u32,_:&str) -> ROk { u(line!()) }
136   fn serialize_seq         (self,_:Option<usize>    ) -> RI  { u(line!()) }
137   fn serialize_tuple       (self,_:usize            ) -> RI  { u(line!()) }
138   fn serialize_tuple_struct(self,_:&str, _:usize    ) -> RI  { u(line!()) }
139   fn serialize_map         (self,_:Option<usize>    ) -> RI  { u(line!()) }
140  fn serialize_tuple_variant (self,_:&str,_:u32,_:&str,_:usize)->RI{u(line!())}
141  fn serialize_struct_variant(self,_:&str,_:u32,_:&str,_:usize)->RI{u(line!())}
142 }
143
144 impl SerializeStruct for &mut MainExtractor {
145   type Ok = ();
146   type Error = Error;
147
148   fn serialize_field<T: Serialize + ?Sized> (
149     &mut self, key: &str, value: &T
150   ) -> R<()> {
151     if key == "idx"     { self.idx     = Some(value.serialize(ValueExtractor)?); }
152     if key == "version" { self.version = Some(value.serialize(ValueExtractor)?); }
153     Ok(())
154   }
155
156   fn end(self) -> ROk { Ok(()) }
157 }
158
159 type V = u32;
160 type ImpV = Impossible<V,Error>;
161 type RIV = R<ImpV>;
162
163 impl Serializer for ValueExtractor {
164   type Ok = V;
165   type Error = Error;
166   
167   fn serialize_u32(self, value: u32) -> R<V> { Ok(value) }
168
169   type SerializeStruct        = ImpV;
170   type SerializeMap           = ImpV;
171   type SerializeSeq           = ImpV;
172   type SerializeTuple         = ImpV;
173   type SerializeTupleStruct   = ImpV;
174   type SerializeTupleVariant  = ImpV;
175   type SerializeStructVariant = ImpV;
176
177   fn serialize_bool (self, _: bool )  -> R<V> { u(line!()) }
178   fn serialize_i8   (self, _: i8   )  -> R<V> { u(line!()) }
179   fn serialize_i16  (self, _: i16  )  -> R<V> { u(line!()) }
180   fn serialize_i32  (self, _: i32  )  -> R<V> { u(line!()) }
181   fn serialize_i64  (self, _: i64  )  -> R<V> { u(line!()) }
182   fn serialize_u8   (self, _: u8   )  -> R<V> { u(line!()) }
183   fn serialize_u16  (self, _: u16  )  -> R<V> { u(line!()) }
184   fn serialize_u64  (self, _: u64  )  -> R<V> { u(line!()) }
185   fn serialize_f32  (self, _: f32  )  -> R<V> { u(line!()) }
186   fn serialize_f64  (self, _: f64  )  -> R<V> { u(line!()) }
187   fn serialize_char (self, _: char )  -> R<V> { u(line!()) }
188   fn serialize_str  (self, _: &str )  -> R<V> { u(line!()) }
189   fn serialize_bytes(self, _: &[u8 ]) -> R<V> { u(line!()) }
190   fn serialize_none (self)            -> R<V> { u(line!()) }
191   fn serialize_unit (self)            -> R<V> { u(line!()) }
192
193   fn serialize_some           <T>(self,                        _: &T) -> R<V>
194   where T: Serialize + ?Sized  { u(line!()) }
195   fn serialize_newtype_struct <T>(self, _:&str,                _: &T) -> R<V>
196   where T: Serialize + ?Sized  { u(line!()) }
197   fn serialize_newtype_variant<T>(self, _:&str, _:u32, _:&str, _: &T) -> R<V>
198   where T: Serialize + ?Sized  { u(line!()) }
199
200   fn serialize_unit_struct   (self,_:&str             ) -> R<V>    { u(line!()) }
201   fn serialize_unit_variant  (self,_:&str,_:u32,_:&str) -> R<V>    { u(line!()) }
202   fn serialize_seq           (self,_:Option<usize>    ) -> RIV { u(line!()) }
203   fn serialize_tuple         (self,_:usize            ) -> RIV { u(line!()) }
204   fn serialize_tuple_struct  (self,_:&str, _: usize   ) -> RIV { u(line!()) }
205   fn serialize_struct        (self,_:&str, _: usize   ) -> RIV { u(line!()) }
206   fn serialize_map           (self,_:Option<usize>    ) -> RIV { u(line!()) }
207  fn serialize_tuple_variant (self,_:&str,_:u32,_:&str,_:usize)->RIV{u(line!())}
208  fn serialize_struct_variant(self,_:&str,_:u32,_:&str,_:usize)->RIV{u(line!())}
209 }
210
211 impl ser::Error for Error {
212   fn custom<T>(_msg: T) -> Self { Error::WasCustomSerialize }
213 }
214
215 impl fmt::Display for Error {
216   fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
217     fmt::Debug::fmt(self,f)
218   }
219 }
220
221 #[test]
222 fn check(){
223   fn t(v: u64) {
224     let kd = slotmap::KeyData::from_ffi(v);
225     let v = kd.as_ffi(); // KeyData is not transparent for all u64
226     let (idx,vsn) = self::KeyDataExt::get_idx_version(kd);
227     eprintln!("KeyData={:?} v=0x{:x?} idx={}=0x{:x} vsn={}=0x{:x}",
228               &kd, &v, idx,idx, vsn,vsn);
229     assert_eq!(v, ((vsn as u64) << 32) | (idx as u64));
230   }
231   t(0x0123456789abcdef);
232   t(0xfedcba9876543210);
233   t(0);
234   t(0xffffffff12345678);
235   t(0x12345678ffffffff);
236   t(0xffffffff00000000);
237   t(0x00000000ffffffff);
238   t(0x0000000012345678);
239   t(0x1234567800000000);
240 }