starlang_core/
reference.rs1use serde::{Deserialize, Serialize};
7use std::fmt;
8use std::sync::atomic::{AtomicU64, Ordering};
9
10static REF_COUNTER: AtomicU64 = AtomicU64::new(0);
12
13#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct Ref(u64);
32
33impl Ref {
34 pub fn new() -> Self {
48 Self(REF_COUNTER.fetch_add(1, Ordering::Relaxed))
49 }
50
51 pub const fn from_raw(value: u64) -> Self {
55 Self(value)
56 }
57
58 #[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}