Skip to main content

starlang_core/
reference.rs

1//! Unique reference type.
2//!
3//! A [`Ref`] is a unique identifier used for monitors, timers, and other
4//! one-time or cancellable operations.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8use std::sync::atomic::{AtomicU64, Ordering};
9
10/// Global counter for generating unique references.
11static REF_COUNTER: AtomicU64 = AtomicU64::new(0);
12
13/// A unique reference.
14///
15/// References are used to identify monitors, timers, and other operations
16/// that may need to be cancelled or matched against messages.
17///
18/// # Examples
19///
20/// ```
21/// use starlang_core::Ref;
22///
23/// let r = Ref::new();
24/// println!("Reference: {}", r);
25///
26/// // References are unique
27/// let r2 = Ref::new();
28/// assert_ne!(r, r2);
29/// ```
30#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct Ref(u64);
32
33impl Ref {
34    /// Creates a new unique reference.
35    ///
36    /// Each call to `new()` returns a globally unique `Ref`.
37    ///
38    /// # Examples
39    ///
40    /// ```
41    /// use starlang_core::Ref;
42    ///
43    /// let r1 = Ref::new();
44    /// let r2 = Ref::new();
45    /// assert_ne!(r1, r2);
46    /// ```
47    pub fn new() -> Self {
48        Self(REF_COUNTER.fetch_add(1, Ordering::Relaxed))
49    }
50
51    /// Creates a `Ref` from a raw value.
52    ///
53    /// This is primarily used for deserialization and testing.
54    pub const fn from_raw(value: u64) -> Self {
55        Self(value)
56    }
57
58    /// Returns the raw value of this reference.
59    #[inline]
60    pub const fn as_raw(&self) -> u64 {
61        self.0
62    }
63}
64
65impl Default for Ref {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71impl fmt::Debug for Ref {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        write!(f, "Ref({})", self.0)
74    }
75}
76
77impl fmt::Display for Ref {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        write!(f, "#{}", self.0)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn test_ref_uniqueness() {
89        let r1 = Ref::new();
90        let r2 = Ref::new();
91        assert_ne!(r1, r2);
92    }
93
94    #[test]
95    fn test_ref_from_raw() {
96        let r = Ref::from_raw(42);
97        assert_eq!(r.as_raw(), 42);
98    }
99
100    #[test]
101    fn test_ref_display() {
102        let r = Ref::from_raw(123);
103        assert_eq!(format!("{}", r), "#123");
104        assert_eq!(format!("{:?}", r), "Ref(123)");
105    }
106
107    #[test]
108    fn test_ref_serialization() {
109        let r = Ref::from_raw(999);
110        let bytes = postcard::to_allocvec(&r).unwrap();
111        let decoded: Ref = postcard::from_bytes(&bytes).unwrap();
112        assert_eq!(r, decoded);
113    }
114
115    #[test]
116    fn test_ref_hash() {
117        use std::collections::HashMap;
118
119        let mut map = HashMap::new();
120        let r1 = Ref::new();
121        let r2 = Ref::new();
122
123        map.insert(r1, "first");
124        map.insert(r2, "second");
125
126        assert_eq!(map.get(&r1), Some(&"first"));
127        assert_eq!(map.get(&r2), Some(&"second"));
128    }
129}