1use core::{
6 fmt,
7 marker::PhantomData,
8 ops::{Deref, DerefMut},
9 pin::Pin,
10 ptr,
11 sync::atomic::{AtomicUsize, Ordering},
12};
13
14#[doc(hidden)]
15pub use crate::repr_hack::TokenId;
16
17pub unsafe trait Token {
40 type Id: Clone + Eq + TokenId;
42 fn id(&self) -> Self::Id;
44 fn is_unique(&mut self) -> bool;
46}
47
48pub struct PtrId<T: ?Sized>(*const T);
53
54impl<T: ?Sized> PtrId<T> {
55 #[inline]
57 pub fn new(ptr: *const T) -> Self {
58 Self(ptr)
59 }
60}
61
62impl<T: ?Sized> From<*const T> for PtrId<T> {
63 #[inline]
64 fn from(value: *const T) -> Self {
65 Self(value)
66 }
67}
68
69impl<T: ?Sized> From<*mut T> for PtrId<T> {
70 #[inline]
71 fn from(value: *mut T) -> Self {
72 Self(value)
73 }
74}
75
76impl<T: ?Sized> From<&T> for PtrId<T> {
77 #[inline]
78 fn from(value: &T) -> Self {
79 Self(value)
80 }
81}
82
83impl<T: ?Sized> From<&mut T> for PtrId<T> {
84 #[inline]
85 fn from(value: &mut T) -> Self {
86 Self(value)
87 }
88}
89
90unsafe impl<T: ?Sized> Send for PtrId<T> {}
92unsafe impl<T: ?Sized> Sync for PtrId<T> {}
94
95impl<T: ?Sized> fmt::Debug for PtrId<T> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 write!(f, "{:?}", self.0)
98 }
99}
100
101impl<T: ?Sized> Copy for PtrId<T> {}
102impl<T: ?Sized> Clone for PtrId<T> {
103 #[inline]
104 fn clone(&self) -> Self {
105 *self
106 }
107}
108
109impl<T: ?Sized> PartialEq for PtrId<T> {
110 #[inline]
111 fn eq(&self, other: &Self) -> bool {
112 ptr::eq(self.0, other.0)
113 }
114}
115impl<T: ?Sized> Eq for PtrId<T> {}
116
117#[macro_export]
124macro_rules! singleton_token {
125 ($name:ident) => {
126 $crate::singleton_token!(pub(self) struct $name;);
127 };
128 ($(#[$($attr:meta)*])* struct $name:ident;) => {
129 $crate::singleton_token!($(#[$($attr)*])* pub(self) struct $name;);
130 };
131 ($(#[$($attr:meta)*])* $vis:vis struct $name:ident;) => {
132 $(#[$($attr)*])*
133 #[allow(clippy::needless_pub_self)]
134 $vis struct $name;
135 #[allow(unused, clippy::needless_pub_self)]
136 const _: () = {
137 static INITIALIZED: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
138 impl $name {
139 #[allow(clippy::new_without_default)]
145 $vis fn new() -> Self {
146 Self::try_new().unwrap()
147 }
148
149 $vis fn try_new() -> Result<Self, $crate::error::AlreadyInitialized> {
151 match INITIALIZED.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) {
152 Ok(_) => Ok(Self),
153 Err(_) => Err($crate::error::AlreadyInitialized),
154 }
155 }
156 }
157
158 impl Drop for $name {
159 fn drop(&mut self) {
160 INITIALIZED.store(false, ::core::sync::atomic::Ordering::Release);
161 }
162 }
163
164 unsafe impl $crate::token::Token for $name {
166 type Id = ();
167
168 #[inline]
169 fn id(&self) -> Self::Id {}
170
171 #[inline]
172 fn is_unique(&mut self) -> bool {
173 true
174 }
175 }
176 };
177 };
178}
179
180static DYNAMIC_COUNTER: AtomicUsize = AtomicUsize::new(0);
181
182#[derive(Debug, Eq, PartialEq)]
193pub struct DynamicToken(usize);
194
195impl DynamicToken {
196 pub fn new() -> Self {
202 let incr = |c| (c != usize::MAX).then(|| c + 1);
203 match DYNAMIC_COUNTER.fetch_update(Ordering::Relaxed, Ordering::Relaxed, incr) {
204 Ok(c) => Self(c + 1),
205 Err(_) => panic!("No more dynamic token available"),
206 }
207 }
208}
209
210impl Default for DynamicToken {
211 fn default() -> Self {
212 Self::new()
213 }
214}
215
216unsafe impl Token for DynamicToken {
218 type Id = usize;
219
220 #[inline]
221 fn id(&self) -> Self::Id {
222 self.0
223 }
224
225 #[inline]
226 fn is_unique(&mut self) -> bool {
227 true
228 }
229}
230
231#[derive(Debug)]
236#[repr(transparent)]
237pub struct RefToken<T: ?Sized>(T);
238
239impl<T: ?Sized> RefToken<T> {
240 #[inline]
242 pub fn from_ref(t: &T) -> &Self
243 where
244 T: Unpin,
245 {
246 unsafe { &*(t as *const T as *const Self) }
248 }
249
250 #[inline]
252 pub fn from_mut(t: &mut T) -> &mut Self
253 where
254 T: Unpin,
255 {
256 unsafe { &mut *(t as *mut T as *mut Self) }
258 }
259
260 #[inline]
262 pub fn from_pin(t: Pin<&T>) -> &Self {
263 unsafe { &*(t.get_ref() as *const T as *const Self) }
265 }
266
267 #[inline]
269 pub fn from_pin_mut(t: Pin<&mut T>) -> &mut Self {
270 unsafe { &mut *(t.get_unchecked_mut() as *mut T as *mut Self) }
273 }
274
275 #[inline]
277 pub fn as_pin(&self) -> Pin<&T> {
278 unsafe { Pin::new_unchecked(&self.0) }
280 }
281
282 #[inline]
284 pub fn as_pin_mut(&mut self) -> Pin<&mut T> {
285 unsafe { Pin::new_unchecked(&mut self.0) }
287 }
288}
289
290impl<T: ?Sized> Deref for RefToken<T> {
291 type Target = T;
292
293 #[inline]
294 fn deref(&self) -> &Self::Target {
295 &self.0
296 }
297}
298
299impl<T: Unpin + ?Sized> DerefMut for RefToken<T> {
300 #[inline]
301 fn deref_mut(&mut self) -> &mut Self::Target {
302 &mut self.0
303 }
304}
305
306impl<T: ?Sized> AsRef<T> for RefToken<T> {
307 #[inline]
308 fn as_ref(&self) -> &T {
309 &self.0
310 }
311}
312
313impl<T: Unpin + ?Sized> AsMut<T> for RefToken<T> {
314 #[inline]
315 fn as_mut(&mut self) -> &mut T {
316 &mut self.0
317 }
318}
319
320impl<'a, T: Unpin + ?Sized> From<&'a T> for &'a RefToken<T> {
321 #[inline]
322 fn from(value: &'a T) -> Self {
323 RefToken::from_ref(value)
324 }
325}
326
327impl<'a, T: Unpin + ?Sized> From<&'a mut T> for &'a mut RefToken<T> {
328 #[inline]
329 fn from(value: &'a mut T) -> Self {
330 RefToken::from_mut(value)
331 }
332}
333
334impl<'a, T: ?Sized> From<Pin<&'a T>> for &'a RefToken<T> {
335 #[inline]
336 fn from(value: Pin<&'a T>) -> Self {
337 RefToken::from_pin(value)
338 }
339}
340
341impl<'a, T: ?Sized> From<Pin<&'a mut T>> for &'a mut RefToken<T> {
342 #[inline]
343 fn from(value: Pin<&'a mut T>) -> Self {
344 RefToken::from_pin_mut(value)
345 }
346}
347
348unsafe impl<T: ?Sized> Token for RefToken<T> {
350 type Id = PtrId<T>;
351
352 #[inline]
353 fn id(&self) -> Self::Id {
354 (&self.0).into()
355 }
356
357 #[inline]
358 fn is_unique(&mut self) -> bool {
359 true
360 }
361}
362
363#[cfg(feature = "alloc")]
364mod with_alloc {
365 extern crate alloc;
366 use alloc::{boxed::Box, rc::Rc, sync::Arc};
367
368 use crate::token::{PtrId, Token};
369
370 #[allow(dead_code)]
376 #[derive(Debug, Default)]
377 pub struct AllocatedToken(u8);
378
379 #[derive(Debug, Default)]
383 pub struct BoxToken(Box<AllocatedToken>);
384
385 impl BoxToken {
386 pub fn new() -> Self {
388 Self::default()
389 }
390 }
391
392 unsafe impl Token for BoxToken {
394 type Id = <Box<AllocatedToken> as Token>::Id;
395
396 #[inline]
397 fn id(&self) -> Self::Id {
398 self.0.id()
399 }
400
401 #[inline]
402 fn is_unique(&mut self) -> bool {
403 self.0.is_unique()
404 }
405 }
406
407 trait NotZeroSized<T> {
408 const ASSERT_SIZE_IS_NOT_ZERO: () = assert!(size_of::<T>() > 0);
409 }
410
411 impl<T> NotZeroSized<T> for T {}
412
413 macro_rules! check_not_zero_sized {
414 ($T:ty) => {
415 #[allow(path_statements)]
416 {
417 <$T>::ASSERT_SIZE_IS_NOT_ZERO;
418 }
419 };
420 }
421
422 unsafe impl<T> Token for Box<T> {
426 type Id = PtrId<T>;
427
428 #[inline]
429 fn id(&self) -> Self::Id {
430 check_not_zero_sized!(T);
431 self.as_ref().into()
432 }
433
434 #[inline]
435 fn is_unique(&mut self) -> bool {
436 check_not_zero_sized!(T);
437 true
438 }
439 }
440
441 unsafe impl<T> Token for Rc<T> {
445 type Id = PtrId<T>;
446
447 #[inline]
448 fn id(&self) -> Self::Id {
449 check_not_zero_sized!(T);
450 self.as_ref().into()
451 }
452
453 #[inline]
454 fn is_unique(&mut self) -> bool {
455 check_not_zero_sized!(T);
456 Rc::get_mut(self).is_some()
457 }
458 }
459
460 unsafe impl<T> Token for Arc<T> {
464 type Id = PtrId<T>;
465
466 #[inline]
467 fn id(&self) -> Self::Id {
468 check_not_zero_sized!(T);
469 self.as_ref().into()
470 }
471
472 #[inline]
473 fn is_unique(&mut self) -> bool {
474 check_not_zero_sized!(T);
475 Arc::get_mut(self).is_some()
476 }
477 }
478}
479#[cfg(feature = "alloc")]
480pub use with_alloc::*;
481
482#[cfg(feature = "std")]
483mod with_std {
484 use std::{
485 any::TypeId, cell::RefCell, collections::BTreeSet, fmt, fmt::Formatter,
486 marker::PhantomData, sync::Mutex,
487 };
488
489 use crate::{error::AlreadyInitialized, token::Token};
490
491 static TYPE_TOKENS: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new());
492
493 pub struct TypeToken<T: ?Sized + 'static>(PhantomData<fn(T) -> T>);
495
496 impl<T: ?Sized + 'static> fmt::Debug for TypeToken<T> {
497 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
498 f.debug_struct("TypeToken").finish()
499 }
500 }
501
502 impl<T: ?Sized + 'static> TypeToken<T> {
503 pub fn new() -> Self {
505 Self::try_new().unwrap()
506 }
507
508 pub fn try_new() -> Result<Self, AlreadyInitialized> {
510 if TYPE_TOKENS.lock().unwrap().insert(TypeId::of::<Self>()) {
511 Ok(Self(PhantomData))
512 } else {
513 Err(AlreadyInitialized)
514 }
515 }
516 }
517
518 impl<T: ?Sized + 'static> Drop for TypeToken<T> {
519 fn drop(&mut self) {
520 TYPE_TOKENS.lock().unwrap().remove(&TypeId::of::<Self>());
521 }
522 }
523
524 impl<T: ?Sized + 'static> Default for TypeToken<T> {
525 fn default() -> Self {
526 Self::new()
527 }
528 }
529
530 unsafe impl<T: ?Sized + 'static> Token for TypeToken<T> {
533 type Id = ();
534
535 fn id(&self) -> Self::Id {}
536
537 fn is_unique(&mut self) -> bool {
538 true
539 }
540 }
541
542 std::thread_local! {
543 static LOCAL_TYPE_TOKENS: RefCell<BTreeSet<TypeId>> = const { RefCell::new(BTreeSet::new()) };
544 }
545
546 pub struct LocalTypeToken<T: ?Sized + 'static>(PhantomData<*mut T>);
548
549 impl<T: ?Sized + 'static> fmt::Debug for LocalTypeToken<T> {
550 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
551 f.debug_struct("LocalTypeToken").finish()
552 }
553 }
554
555 impl<T: ?Sized + 'static> LocalTypeToken<T> {
556 pub fn new() -> Self {
558 Self::try_new().unwrap()
559 }
560
561 pub fn try_new() -> Result<Self, AlreadyInitialized> {
563 if LOCAL_TYPE_TOKENS.with_borrow_mut(|types| types.insert(TypeId::of::<Self>())) {
564 Ok(Self(PhantomData))
565 } else {
566 Err(AlreadyInitialized)
567 }
568 }
569 }
570
571 impl<T: ?Sized + 'static> Drop for LocalTypeToken<T> {
572 fn drop(&mut self) {
573 LOCAL_TYPE_TOKENS.with_borrow_mut(|types| types.remove(&TypeId::of::<Self>()));
574 }
575 }
576
577 impl<T: ?Sized + 'static> Default for LocalTypeToken<T> {
578 fn default() -> Self {
579 Self::new()
580 }
581 }
582
583 unsafe impl<T: ?Sized + 'static> Token for LocalTypeToken<T> {
586 type Id = ();
587
588 fn id(&self) -> Self::Id {}
589
590 fn is_unique(&mut self) -> bool {
591 true
592 }
593 }
594}
595
596#[cfg(feature = "std")]
597pub use with_std::*;
598
599#[derive(Debug, PartialEq, Eq)]
601pub struct LifetimeToken<'id>(PhantomData<fn(&'id ()) -> &'id ()>);
602
603impl LifetimeToken<'_> {
604 pub fn scope<R>(f: impl FnOnce(LifetimeToken) -> R) -> R {
607 f(Self(PhantomData))
608 }
609}
610
611unsafe impl Token for LifetimeToken<'_> {
615 type Id = ();
616
617 fn id(&self) -> Self::Id {}
618
619 fn is_unique(&mut self) -> bool {
620 true
621 }
622}
623
624#[cfg(feature = "generativity")]
625impl<'id> From<generativity::Guard<'id>> for LifetimeToken<'id> {
626 fn from(_: generativity::Guard<'id>) -> Self {
627 Self(PhantomData)
628 }
629}