1#[macro_export]
3macro_rules! runtime_token {
4($vis: vis $id: ident) => {
5 $crate::paste! {
6 $vis use [<__ $id _mod__ >]::$id;
7 #[allow(nonstandard_style)]
8 mod [<__ $id _mod__ >] {
9 use core::convert::Infallible;
10 static COUNTER: $crate::atomics::AtomicU16 = $crate::atomics::AtomicU16::new(0);
11 pub struct $id(u16);
13 impl $crate::core::TokenTrait for $id {
14 type ConstructionError = Infallible;
15 type RunError = Infallible;
16 type Identifier = u16;
17 type ComparisonError = $crate::macros::IdMismatch;
18 type Branded<'a> = Self;
19 fn new() -> Result<Self, Self::ConstructionError> {
20 Ok($id(
21 COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed),
22 ))
23 }
24 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
25 Self::new().map(f)
26 }
27 fn identifier(&self) -> Self::Identifier {
28 self.0
29 }
30 fn compare(&self, id: &Self::Identifier) -> Result<(), Self::ComparisonError> {
31 if self.0 == *id {
32 Ok(())
33 } else {
34 Err($crate::macros::IdMismatch {
35 cell: *id,
36 token: self.0,
37 })
38 }
39 }
40 }
41 }
42 }
43};
44($($vis: vis $id: ident),*) => {
45 $($crate::runtime_token!($vis $id);)*
46}
47}
48
49#[macro_export]
53macro_rules! singleton_token {
54($vis: vis $id: ident) => {
55 $crate::paste! {
56 $vis use [<__ $id _mod__ >]::$id;
57 #[allow(nonstandard_style)]
58 mod [<__ $id _mod__ >] {
59 use core::{convert::Infallible, sync::atomic::AtomicBool};
60 use $crate::SingletonUnavailable;
61 static AVAILABLE: AtomicBool = AtomicBool::new(true);
62 pub struct $id(());
66 impl $crate::core::TokenTrait for $id {
67 type ConstructionError = SingletonUnavailable;
68 type RunError = SingletonUnavailable;
69 type Identifier = ();
70 type ComparisonError = Infallible;
71 fn new() -> Result<Self, Self::ConstructionError> {
72 if AVAILABLE.swap(false, core::sync::atomic::Ordering::Relaxed) {
73 Ok($id(()))
74 } else {
75 Err(SingletonUnavailable)
76 }
77 }
78 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
79 Self::new().map(f)
80 }
81 fn identifier(&self) -> Self::Identifier {
82 self.0
83 }
84 fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
85 Ok(())
86 }
87 }
88 impl ::core::ops::Drop for $id {
89 fn drop(&mut self) {
90 AVAILABLE.store(true, core::sync::atomic::Ordering::Relaxed);
91 }
92 }
93 }
94 }
95};
96($($vis: vis $id: ident),*) => {
97 $($crate::singleton_token!($vis $id);)*
98}
99}
100
101#[macro_export]
107macro_rules! unsafe_token {
108($vis: vis $id: ident) => {
109 $crate::paste! {
110 $vis use [<__ $id _mod__ >]::$id;
111 #[allow(nonstandard_style)]
112 mod [<__ $id _mod__ >] {
113 use core::convert::Infallible;
114 pub struct $id(());
120 impl $crate::core::TokenTrait for $id {
121 type ConstructionError = Infallible;
122 type RunError = Infallible;
123 type Identifier = ();
124 type ComparisonError = Infallible;
125 type Branded<'a> = Self;
126 fn new() -> Result<Self, Self::ConstructionError> {
127 Ok($id(()))
128 }
129 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
130 Self::new().map(f)
131 }
132 fn identifier(&self) -> Self::Identifier {
133 self.0
134 }
135 fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
136 Ok(())
137 }
138 }
139 }
140 }
141};
142($($vis: vis $id: ident),*) => {
143 $($crate::unsafe_token!($vis $id);)*
144}
145}
146pub use token::token;
147#[cfg(any(feature = "debug", debug_assertions))]
148mod token {
149 pub use crate::runtime_token as token;
150}
151#[cfg(not(any(feature = "debug", debug_assertions)))]
152mod token {
153 pub use crate::unsafe_token as token;
154}
155
156#[derive(Debug, Clone, Copy)]
158pub struct IdMismatch {
159 pub cell: u16,
161 pub token: u16,
163}
164impl ::core::fmt::Display for IdMismatch {
165 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
166 write!(f, "{:?}", self)
167 }
168}
169#[derive(Debug, Clone, Copy)]
171pub struct SingletonUnavailable;
172impl ::core::fmt::Display for SingletonUnavailable {
173 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
174 write!(f, "{:?}", self)
175 }
176}