1use std;
2
3const MAX: u32 = 0x_8000_0000;
4
5#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26pub struct SerialNumber(pub u32);
27
28impl SerialNumber {
29 pub fn as_u32(&self) -> u32 {
30 self.0
31 }
32}
33
34impl std::fmt::Display for SerialNumber {
35 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
36 self.0.fmt(f)
37 }
38}
39
40impl From<SerialNumber> for u32 {
41 fn from(x: SerialNumber) -> Self {
42 x.0
43 }
44}
45
46impl PartialOrd for SerialNumber {
47 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
48
49 const MAX: u32 = 0x_8000_0000;
50
51 let i1 = self.0; let i2 = other.0; if i1 == i2 {
55 Some(std::cmp::Ordering::Equal)
56 } else if (i1 < i2 && i2 - i1 < MAX) || (i1 > i2 && i1 - i2 > MAX) {
57 Some(std::cmp::Ordering::Less)
58 } else if (i1 < i2 && i2 - i1 > MAX) || (i1 > i2 && i1 - i2 < MAX) {
59 Some(std::cmp::Ordering::Greater)
60 } else {
61 debug_assert!((i1 < i2 && i2 - i1 == 0x_8000_0000) || (i1 > i2 && i1 - i2 == 0x_8000_0000));
62
63 None
71 }
72 }
73}
74
75impl std::ops::Add for SerialNumber {
76 type Output = Self;
77 fn add(self, other: Self) -> Self::Output {
78 debug_assert!(other.0 < MAX);
79 SerialNumber(self.0.wrapping_add(other.0))
80 }
81}
82
83impl std::ops::AddAssign for SerialNumber {
84 fn add_assign(&mut self, other: Self) {
85 debug_assert!(other.0 < MAX);
86 self.0 = self.0.wrapping_add(other.0);
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn serial_number_display() {
96 let got = format!("{}", SerialNumber(1234));
97 let expected = "1234";
98 assert_eq!(got, expected);
99 }
100
101 #[test]
102 fn u32_from_serial_number() {
103 let x = SerialNumber(1234);
104 let got = u32::from(x);
105 let expected = 1234;
106 assert_eq!(got, expected);
107 }
108
109 #[test]
110 fn serial_number_partial_cmp() {
111 use std::cmp::Ordering::*;
112
113 let f = |x, y| SerialNumber(x).partial_cmp(&SerialNumber(y));
114
115 assert_eq!(f(0, 0), Some(Equal));
118 assert_eq!(f(1, 1), Some(Equal));
119 assert_eq!(f(0x_7fff_ffff, 0x_7fff_ffff), Some(Equal));
120 assert_eq!(f(0x_8000_0000, 0x_8000_0000), Some(Equal));
121 assert_eq!(f(0x_ffff_ffff, 0x_ffff_ffff), Some(Equal));
122
123 assert_eq!(f(0, 1), Some(Less));
126 assert_eq!(f(1, 0), Some(Greater));
127
128 assert_eq!(f(0, 44), Some(Less));
129 assert_eq!(f(44, 0), Some(Greater));
130
131 assert_eq!(f(0, 100), Some(Less));
132 assert_eq!(f(100, 0), Some(Greater));
133
134 assert_eq!(f(44, 100), Some(Less));
135 assert_eq!(f(100, 44), Some(Greater));
136
137 assert_eq!(f(0x_ffff_ffff, 0x_0000_0000), Some(Less));
138 assert_eq!(f(0x_0000_0000, 0x_ffff_ffff), Some(Greater));
139
140 assert_eq!(f(0x_0000_0000, 0x_7fff_ffff), Some(Less));
141 assert_eq!(f(0x_7fff_ffff, 0x_0000_0000), Some(Greater));
142
143 assert_eq!(f(0x_0000_0001, 0x_8000_0000), Some(Less));
144 assert_eq!(f(0x_8000_0000, 0x_0000_0001), Some(Greater));
145
146 assert_eq!(f(0x_4000_0000, 0x_bfff_ffff), Some(Less));
147 assert_eq!(f(0x_bfff_ffff, 0x_4000_0000), Some(Greater));
148
149 assert_eq!(f(0x_0000_0000, 0x_8000_0000), None);
152 assert_eq!(f(0x_8000_0000, 0x_0000_0000), None);
153
154 assert_eq!(f(0x_0000_0001, 0x_8000_0001), None);
155 assert_eq!(f(0x_8000_0001, 0x_0000_0001), None);
156
157 assert_eq!(f(0x_4000_0000, 0x_c000_0000), None);
158 assert_eq!(f(0x_c000_0000, 0x_4000_0000), None);
159
160 assert_eq!(f(0x_7fff_ffff, 0x_ffff_ffff), None);
161 assert_eq!(f(0x_ffff_ffff, 0x_7fff_ffff), None);
162 }
163
164 #[test]
165 fn serial_number_add() {
166 let f = |x, y| SerialNumber(x) + SerialNumber(y);
167 assert_eq!(f(0, 0), SerialNumber(0));
168 assert_eq!(f(0, 1), SerialNumber(1));
169 assert_eq!(f(0, 42), SerialNumber(42));
170 assert_eq!(f(0, 0x_7fff_ffff), SerialNumber(0x_7fff_ffff));
171 assert_eq!(f(0x_ffff_ffff, 1), SerialNumber(0));
172 assert_eq!(f(0x_ffff_ffff, 2), SerialNumber(1));
173 assert_eq!(f(0x_ffff_ffff, 0x_7fff_ffff), SerialNumber(0x_7fff_fffe));
174 }
175
176 #[test]
177 fn serial_number_add_assign() {
178 let f = |x, y| {
179 let mut x = SerialNumber(x);
180 x += SerialNumber(y);
181 x
182 };
183 assert_eq!(f(0, 0), SerialNumber(0));
184 assert_eq!(f(0, 1), SerialNumber(1));
185 assert_eq!(f(0, 42), SerialNumber(42));
186 assert_eq!(f(0, 0x_7fff_ffff), SerialNumber(0x_7fff_ffff));
187 assert_eq!(f(0x_ffff_ffff, 1), SerialNumber(0));
188 assert_eq!(f(0x_ffff_ffff, 2), SerialNumber(1));
189 assert_eq!(f(0x_ffff_ffff, 0x_7fff_ffff), SerialNumber(0x_7fff_fffe));
190 }
191}