chiark / gitweb /
changelog: document further make-release changes
[otter.git] / support / keydata.rs
1 // Copyright 2020-2021 Ian Jackson and contributors to Otter
2 // SPDX-License-Identifier: AGPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 #![allow(clippy::many_single_char_names)]
6
7 use crate::prelude::*;
8
9 type SKD = slotmap::KeyData;
10
11 #[macro_export]
12 macro_rules! display_consequential_impls {
13   ( $x:path ) => {
14     impl From<$x> for String {
15       fn from(p: $x) -> String { format!("{}",p) }
16     }
17     impl Debug for $x {
18       fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
19         <Self as Display>::fmt(self, f)
20       }
21     }
22   }
23 }
24 pub use crate::display_consequential_impls; // this is madness!
25
26 #[throws(AE)]
27 pub fn slotkey_parse(s: &str, sep: u8) -> SKD {
28   if s.as_bytes() == [b'0', sep, b'0', b'0'] { return default() }
29   let sep: char = sep.into();
30   let e = || anyhow!("could not deserialise visibile piece id");
31   let mut i = s.splitn(2, sep).map(|s| s.parse().map_err(|_| e()));
32   let l: u32 = i.next().ok_or_else(e)??;
33   let h: u32 = i.next().ok_or_else(e)??;
34   let v = ((h as u64) << 32) | (l as u64);
35   SKD::from_ffi(v)
36 }
37
38 #[throws(fmt::Error)]
39 pub fn slotkey_write(k: SKD, sep: u8, f: &mut fmt::Formatter) {
40   let sep: char = sep.into();
41   if k == default() { write!(f, "0{}00", sep)?; return; }
42   let v = k.as_ffi();
43   write!(f, "{}{}{}", v & 0xffffffff, sep, v >> 32)?
44 }
45
46 #[macro_export]
47 macro_rules! visible_slotmap_key {
48   ( $x:ident($sep:expr) ) => {
49
50     #[derive(Copy,Default,Clone,Eq,PartialEq,Ord,PartialOrd,Serialize,Deserialize,Hash)]
51     #[serde(into="String")]
52     #[serde(try_from="String")]
53     pub struct $x(pub slotmap::KeyData);
54
55     impl_for_slotmap_key!($x($sep));
56     hformat_as_display!{$x}
57   }
58 }
59 #[macro_export]
60 macro_rules! impl_for_slotmap_key {
61   ( $x:ident($sep:expr) ) => {
62     impl Display for $x {
63       #[throws(fmt::Error)]
64       fn fmt(&self, f: &mut fmt::Formatter) { slotkey_write(self.0,$sep,f)? }
65     }
66
67     impl TryFrom<&str> for $x {
68       type Error = AE;
69       #[throws(AE)]
70       fn try_from(s: &str) -> $x { $x(slotkey_parse(s,$sep)?) }
71     }
72     impl TryFrom<String> for $x {
73       type Error = AE;
74       #[throws(AE)]
75       fn try_from(s: String) -> $x { $x(slotkey_parse(&s,$sep)?) }
76     }
77
78     impl slotmap::Key for $x {
79       fn data(&self) -> slotmap::KeyData { self.0 }
80     }
81     impl From<slotmap::KeyData> for $x {
82       fn from(d: slotmap::KeyData) -> Self { $x(d) }
83     }
84     impl From<$x> for slotmap::KeyData {
85       fn from(p: $x) -> Self {
86         p.0
87       }
88     }
89
90     display_consequential_impls!{$x}
91   }
92 }
93 pub use crate::visible_slotmap_key; // this is madness!
94 pub use crate::impl_for_slotmap_key; // this is madness!