1use std::cmp;
9use std::fmt;
10use std::sync::atomic;
11use std::sync::atomic::AtomicU32;
12use std::sync::Arc;
13
14#[derive(Clone)]
33pub struct VerLink {
34 inner: Arc<Inner>,
35}
36
37#[derive(Clone)]
38struct Inner {
39 parent: Option<VerLink>,
40
41 base: u32,
44
45 gen: u32,
49}
50
51impl VerLink {
52 pub fn new() -> Self {
55 let inner = Inner {
56 parent: None,
57 base: next_id(),
58 gen: 0,
59 };
60 Self {
61 inner: Arc::new(inner),
62 }
63 }
64
65 pub fn bump(&mut self) {
67 match Arc::get_mut(&mut self.inner) {
68 Some(_inner) => {
72 }
75 None => {
76 let next_inner = Inner {
77 parent: Some(self.clone()),
78 base: self.inner.base,
79 gen: self.inner.gen + 1,
80 };
81 let next = Self {
82 inner: Arc::new(next_inner),
83 };
84 *self = next;
85 }
86 }
87 }
88}
89
90impl PartialOrd for VerLink {
91 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
92 if self.inner.base != other.inner.base {
93 return None;
96 }
97 if self.inner.gen < other.inner.gen {
98 other.partial_cmp(self).map(|o| o.reverse())
99 } else {
100 debug_assert!(self.inner.gen >= other.inner.gen);
101 if Arc::ptr_eq(&self.inner, &other.inner) {
102 return Some(cmp::Ordering::Equal);
103 }
104 let mut cur = self.inner.parent.as_ref();
105 while let Some(this) = cur {
106 if this.inner.gen < other.inner.gen {
107 return None;
109 }
110 if Arc::ptr_eq(&this.inner, &other.inner) {
111 return Some(cmp::Ordering::Greater);
112 }
113 cur = this.inner.parent.as_ref();
114 }
115 None
116 }
117 }
118}
119
120impl PartialEq for VerLink {
121 fn eq(&self, other: &Self) -> bool {
122 Arc::ptr_eq(&self.inner, &other.inner)
123 }
124}
125
126impl fmt::Debug for VerLink {
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 let mut cur = Some(self);
129 while let Some(this) = cur {
130 write!(f, "{:p}", this.inner.as_ref())?;
131 cur = this.inner.parent.as_ref();
132 f.write_str("->")?;
133 if cur.is_none() {
134 write!(f, "{}", this.inner.base)?;
135 }
136 }
137 Ok(())
138 }
139}
140
141fn next_id() -> u32 {
142 static ID: AtomicU32 = AtomicU32::new(0);
143 ID.fetch_add(1, atomic::Ordering::AcqRel)
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_individual_news_are_incompatible() {
152 let a = VerLink::new();
153 let b = VerLink::new();
154 assert!(compatible(&a, &b).is_none());
155 }
156
157 #[test]
158 fn test_clone_compatible() {
159 let a = VerLink::new();
160 let b = a.clone();
161 assert_eq!(&a, &b);
162 assert_eq!(compatible(&a, &b), Some(&b));
163 }
164
165 #[test]
166 fn test_bump_is_different_and_backwards_compatible() {
167 let a = VerLink::new();
168 let mut b = a.clone();
169 b.bump();
170 assert_ne!(&b, &a);
171 assert_eq!(compatible(&a, &b), Some(&b));
172
173 b.bump();
174 b.bump();
175 assert_eq!(compatible(&a, &b), Some(&b));
176 }
177
178 #[test]
179 fn test_clone_bump_twice() {
180 let a = VerLink::new();
181 let mut b = a.clone();
182 b.bump();
183 let mut c = b.clone();
184 c.bump();
185 assert_eq!(compatible(&a, &c), Some(&c));
186 assert_eq!(compatible(&b, &c), Some(&c));
187 }
188
189 #[test]
190 fn test_bump_independently_become_incompatible() {
191 let mut a = VerLink::new();
192 let mut b = a.clone();
193 b.bump();
194 a.bump();
195 assert_eq!(compatible(&a, &b), None);
196 }
197
198 #[test]
199 fn test_bump_avoid_increase_len_if_possible() {
200 let a = VerLink::new();
201 let mut b = a.clone();
202 assert_eq!(a.chain_len(), 1);
203 assert_eq!(b.chain_len(), 1);
204 b.bump(); assert_eq!(b.chain_len(), 2);
206 b.bump(); b.bump();
208 assert_eq!(b.chain_len(), 2);
209 }
210
211 #[allow(clippy::neg_cmp_op_on_partial_ord)]
213 fn compatible<'a>(a: &'a VerLink, b: &'a VerLink) -> Option<&'a VerLink> {
214 if a == b {
215 assert!(!(a != b));
216 assert!(!(a < b));
217 assert!(!(b < a));
218 assert!(!(a > b));
219 assert!(!(b > a));
220 Some(a)
221 } else if a < b {
222 assert!(!(a == b));
223 assert!(a != b);
224 assert!(!(b < a));
225 assert!(!(a > b));
226 assert!(b > a);
227 Some(b)
228 } else if a > b {
229 assert!(!(a == b));
230 assert!(a != b);
231 assert!(!(a < b));
232 assert!(b < a);
233 assert!(!(b > a));
234 Some(a)
235 } else {
236 assert!(!(a == b));
237 assert!(a != b);
238 assert!(!(a < b));
239 assert!(!(a > b));
240 assert!(!(b < a));
241 assert!(!(b > a));
242 None
243 }
244 }
245
246 impl VerLink {
247 fn chain_len(&self) -> usize {
249 let mut len = 0;
250 let mut cur = Some(self);
251 while let Some(this) = cur {
252 len += 1;
253 cur = this.inner.parent.as_ref();
254 }
255 len
256 }
257 }
258}