1macro_rules! unwrap_opt_or_return {
2 ($opt:expr, $err:expr) => {
3 match $opt {
4 Some(val) => val,
5 None => return $err,
6 }
7 };
8}
9
10#[cfg(feature = "serde")]
12#[macro_export]
13macro_rules! serde_derive_impl {
14 ($def:item) => {
15 #[derive(Serialize, Deserialize)]
16 $def
17 };
18}
19
20#[cfg(not(feature = "serde"))]
21#[macro_export]
22macro_rules! serde_derive_impl {
23 ($def:item) => {
24 $def
25 };
26}
27
28#[macro_export]
30macro_rules! new_handle_type (($newtype:ident, $counter:ident) => (
31 static $counter: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
32
33 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
34 #[repr(transparent)]
35 pub struct $newtype(pub usize);
36
37 impl $newtype {
38 #[allow(dead_code)]
39 pub fn invalid() -> $newtype {
40 $newtype(0)
41 }
42
43 #[allow(dead_code)]
44 pub fn next() -> $newtype {
45 $newtype($counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) + 1)
46 }
47 }
48
49 impl std::fmt::Display for $newtype {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "{}({})", stringify!($newtype), self.0)
52 }
53 }
54
55 impl std::ops::Deref for $newtype {
56 type Target = usize;
57 fn deref(&self) -> &usize {
58 &self.0
59 }
60 }
61
62 impl PartialEq<usize> for $newtype {
63 fn eq(&self, other: &usize) -> bool {
64 self.0 == *other
65 }
66 }
67
68 impl $crate::Validatable for $newtype {
69 fn validate(&self) -> std::result::Result<(), $crate::ValidationError> {
70 if(**self == 0) {
71 Err("Invalid handle: zero".into())
72 } else {
73 Ok(())
74 }
75 }
76 }
77));
78
79#[cfg(test)]
80mod tests {
81 new_handle_type!(TestHandle, TEST_HANDLE_CTR);
82
83 #[test]
84 fn test_handle_seq() {
85 assert_eq!(TestHandle::next(), 1);
86 assert_eq!(TestHandle::next(), 2);
87 }
88}