Skip to main content

otter_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
10use 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.
15pub 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
38impl 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.
51pub 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.
64pub enum Error {
65  WasCustomSerialize,
66  Unexpected(std::num::NonZeroU32),
67}
68impl std::error::Error for Error { }
69
70//---------- implementation.  avert your eyes ----------
71
72use std::convert::TryFrom;
73use std::fmt;
74use std::line;
75use serde::ser::{self, *};
76
77#[derive(Default)]
78struct MainExtractor {
79  idx: Option<u32>,
80  version: Option<u32>,
81}
82
83struct ValueExtractor;
84
85type R<Return> = Result<Return, Error>;
86type ROk = R<()>;
87use self::Error::*;
88
89fn error(line: u32) -> Error { Unexpected(TryFrom::try_from(line).unwrap()) }
90fn u<T>(line: u32) -> R<T> { Err(error(line)) }
91
92type Imp = Impossible<(), Error>;
93type RI = R<Imp>;
94
95impl 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
144impl 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
159type V = u32;
160type ImpV = Impossible<V,Error>;
161type RIV = R<ImpV>;
162
163impl 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
211impl ser::Error for Error {
212  fn custom<T>(_msg: T) -> Self { Error::WasCustomSerialize }
213}
214
215impl 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]
222fn 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}