tokenlock/
rc.rs

1//! [`Rc`]-based tokens
2//!
3//! [`Rc`]: std::rc::Rc
4use alloc::rc::Rc;
5use core::hash;
6
7use super::{Token, Unsync};
8
9/// An `Rc`-based unforgeable token used to access the contents of a
10/// `TokenLock`.
11///
12/// This type lacks a `Clone` implementation to ensure exclusive access to
13/// [`TokenLock`].
14///
15/// [`TokenLock`]: crate::TokenLock
16#[derive(Debug, PartialEq, Eq, Hash)]
17pub struct RcToken(UniqueId);
18
19impl RcToken {
20    pub fn new() -> Self {
21        RcToken(UniqueId::new())
22    }
23
24    /// Construct an [`RcTokenId`] that equates to `self`.
25    pub fn id(&self) -> RcTokenId {
26        RcTokenId(self.0.clone())
27    }
28}
29
30impl Default for RcToken {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36unsafe impl Token<RcTokenId> for RcToken {
37    fn eq_id(&self, id: &RcTokenId) -> bool {
38        self.0 == id.0
39    }
40}
41
42unsafe impl Unsync for RcToken {}
43
44/// Token that cannot be used to access the contents of a [`TokenLock`], but can
45/// be used to create a new `TokenLock`.
46///
47/// [`TokenLock`]: crate::TokenLock
48///
49/// # Examples
50///
51/// `RcTokenId` can be cloned while [`RcToken`] cannot:
52///
53/// ```
54/// # use tokenlock::*;
55/// let token = RcToken::new();
56/// let token_id = token.id();
57/// let lock1 = TokenLock::new(token_id.clone(), 1);
58/// let lock2 = TokenLock::new(token_id, 2);
59/// ```
60///
61#[derive(Debug, PartialEq, Eq, Clone, Hash)]
62pub struct RcTokenId(UniqueId);
63
64#[derive(Debug, Clone)]
65struct UniqueId(Rc<()>);
66
67impl PartialEq for UniqueId {
68    fn eq(&self, other: &Self) -> bool {
69        Rc::ptr_eq(&self.0, &other.0)
70    }
71}
72impl Eq for UniqueId {}
73
74impl hash::Hash for UniqueId {
75    fn hash<H: hash::Hasher>(&self, state: &mut H) {
76        (&*self.0 as *const ()).hash(state)
77    }
78}
79
80impl UniqueId {
81    pub fn new() -> Self {
82        UniqueId(Rc::new(()))
83    }
84}
85
86#[cfg(feature = "std")]
87#[test]
88fn unique_id_hash() {
89    let id1 = UniqueId::new();
90    let id2 = id1.clone();
91    let mut hm = std::collections::HashSet::new();
92    assert!(hm.insert(id1));
93    assert!(!hm.insert(id2)); // should have an identical hash
94}