1#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "README.md" ) ) ]
2
3use std::{pin::Pin, ptr};
4
5#[derive(Clone)]
6pub struct UniqueId {
7 inner: Pin<Box<u8>>,
10}
11
12impl Default for UniqueId {
13 fn default() -> Self {
14 Self { inner: Box::pin(0) }
15 }
16}
17
18impl core::fmt::Debug for UniqueId {
19 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
20 write!(f, "{}", self.as_usize())
21 }
22}
23impl core::hash::Hash for UniqueId {
24 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
25 self.as_usize().hash(state);
26 }
27}
28
29impl PartialEq for UniqueId {
30 fn eq(&self, other: &Self) -> bool {
31 ptr::eq(&*self.inner, &*other.inner)
32 }
33}
34
35impl PartialOrd for UniqueId {
36 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
37 Some(self.as_usize().cmp(&other.as_usize()))
38 }
39}
40
41impl Ord for UniqueId {
42 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
43 self.as_usize().cmp(&other.as_usize())
44 }
45}
46
47impl Eq for UniqueId {}
48
49impl UniqueId {
50 pub fn new() -> Self {
51 Self::default()
52 }
53
54 pub fn as_usize(&self) -> usize {
55 ptr::addr_of!(*self.inner) as usize
56 }
57}
58
59#[cfg(test)]
60mod test {
61 use std::sync::Arc;
62
63 use crate::UniqueId;
64
65 #[derive(Clone, Eq, PartialEq, Debug)]
66 struct Test {
67 id: UniqueId,
68 }
69
70 struct TestWrapper {
71 inner: Arc<Test>,
72 }
73
74 impl Clone for TestWrapper {
75 fn clone(&self) -> Self {
76 Self {
77 inner: self.inner.clone(),
78 }
79 }
80 }
81
82 impl TestWrapper {
83 fn new() -> Self {
84 Self {
85 inner: Test { id: <_>::default() }.into(),
86 }
87 }
88 fn id(&self) -> usize {
89 self.inner.id.as_usize()
90 }
91 }
92
93 #[cfg(not(debug_assertions))]
94 #[test]
95 fn test_stack() {
96 panic!(
97 "the test MUST be run for the debug target as there is still a chance the object
98generator may be inlined"
99 );
100 }
101 #[cfg(debug_assertions)]
102 #[test]
103 fn test_stack() {
104 #[inline(never)]
105 fn generate() -> (Test, usize) {
106 let t = Test { id: <_>::default() };
107 let n = t.id.as_usize();
108 (t, n)
109 }
110 let (t, n) = generate();
111 assert_eq!(t.id.as_usize(), n);
112 }
113 #[test]
114 fn test_clone_eq() {
115 let t = Test { id: <_>::default() };
116 let t2 = t.clone();
117 assert_ne!(t.id, t2.id);
118 assert_ne!(t.id.as_usize(), t2.id.as_usize());
119 assert_ne!(t, t2);
120 assert_eq!(t, t);
121 assert_eq!(t.id, t.id);
122 }
123 #[test]
124 fn test_heap_movement() {
125 let t = Test { id: <_>::default() };
126 let n = t.id.as_usize();
127 let mut x = vec![t];
128 assert_eq!(x[0].id.as_usize(), n);
129 let t_back = x.pop().unwrap();
130 assert_eq!(t_back.id.as_usize(), n);
131 }
132 #[test]
133 fn test_arc_covered() {
134 let t1 = TestWrapper::new();
135 let t2 = t1.clone();
136 assert_eq!(t1.id(), t2.id());
137 }
138}