1use std::cmp::{Eq, Ord, PartialEq, PartialOrd};
22use std::fmt::Debug;
23use std::ops::{Add, BitAnd, BitOr, Not, Sub};
24
25pub trait AddressValue {
27 type V: Copy
29 + PartialEq
30 + Eq
31 + PartialOrd
32 + Ord
33 + Not<Output = Self::V>
34 + Add<Output = Self::V>
35 + Sub<Output = Self::V>
36 + BitAnd<Output = Self::V>
37 + BitOr<Output = Self::V>
38 + Debug
39 + From<u8>;
40
41 fn zero() -> Self::V {
43 0u8.into()
44 }
45
46 fn one() -> Self::V {
48 1u8.into()
49 }
50}
51
52pub trait Address:
64 AddressValue
65 + Sized
66 + Default
67 + Copy
68 + Eq
69 + PartialEq
70 + Ord
71 + PartialOrd
72 + BitAnd<<Self as AddressValue>::V, Output = Self>
73 + BitOr<<Self as AddressValue>::V, Output = Self>
74{
75 fn new(addr: Self::V) -> Self;
77
78 fn raw_value(&self) -> Self::V;
80
81 fn mask(&self, mask: Self::V) -> Self::V {
83 self.raw_value() & mask
84 }
85
86 fn checked_offset_from(&self, base: Self) -> Option<Self::V>;
90
91 fn unchecked_offset_from(&self, base: Self) -> Self::V {
108 self.raw_value() - base.raw_value()
109 }
110
111 fn checked_align_up(&self, power_of_two: Self::V) -> Option<Self> {
113 let mask = power_of_two - Self::one();
114 assert_ne!(power_of_two, Self::zero());
115 assert_eq!(power_of_two & mask, Self::zero());
116 self.checked_add(mask).map(|x| x & !mask)
117 }
118
119 fn unchecked_align_up(&self, power_of_two: Self::V) -> Self {
122 let mask = power_of_two - Self::one();
123 self.unchecked_add(mask) & !mask
124 }
125
126 fn checked_add(&self, other: Self::V) -> Option<Self>;
128
129 fn overflowing_add(&self, other: Self::V) -> (Self, bool);
135
136 fn unchecked_add(&self, offset: Self::V) -> Self;
144
145 fn checked_sub(&self, other: Self::V) -> Option<Self>;
147
148 fn overflowing_sub(&self, other: Self::V) -> (Self, bool);
154
155 fn unchecked_sub(&self, other: Self::V) -> Self;
163}
164
165macro_rules! impl_address_ops {
166 ($T:ident, $V:ty) => {
167 impl AddressValue for $T {
168 type V = $V;
169 }
170
171 impl Address for $T {
172 fn new(value: $V) -> $T {
173 $T(value)
174 }
175
176 fn raw_value(&self) -> $V {
177 self.0
178 }
179
180 fn checked_offset_from(&self, base: $T) -> Option<$V> {
181 self.0.checked_sub(base.0)
182 }
183
184 fn checked_add(&self, other: $V) -> Option<$T> {
185 self.0.checked_add(other).map($T)
186 }
187
188 fn overflowing_add(&self, other: $V) -> ($T, bool) {
189 let (t, ovf) = self.0.overflowing_add(other);
190 ($T(t), ovf)
191 }
192
193 fn unchecked_add(&self, offset: $V) -> $T {
194 $T(self.0 + offset)
195 }
196
197 fn checked_sub(&self, other: $V) -> Option<$T> {
198 self.0.checked_sub(other).map($T)
199 }
200
201 fn overflowing_sub(&self, other: $V) -> ($T, bool) {
202 let (t, ovf) = self.0.overflowing_sub(other);
203 ($T(t), ovf)
204 }
205
206 fn unchecked_sub(&self, other: $V) -> $T {
207 $T(self.0 - other)
208 }
209 }
210
211 impl Default for $T {
212 fn default() -> $T {
213 Self::new(0 as $V)
214 }
215 }
216
217 impl BitAnd<$V> for $T {
218 type Output = $T;
219
220 fn bitand(self, other: $V) -> $T {
221 $T(self.0 & other)
222 }
223 }
224
225 impl BitOr<$V> for $T {
226 type Output = $T;
227
228 fn bitor(self, other: $V) -> $T {
229 $T(self.0 | other)
230 }
231 }
232 };
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
240 struct MockAddress(pub u64);
241 impl_address_ops!(MockAddress, u64);
242
243 #[test]
244 fn test_new() {
245 assert_eq!(MockAddress::new(0), MockAddress(0));
246 assert_eq!(MockAddress::new(std::u64::MAX), MockAddress(std::u64::MAX));
247 }
248
249 #[test]
250 fn test_offset_from() {
251 let base = MockAddress(0x100);
252 let addr = MockAddress(0x150);
253 assert_eq!(addr.unchecked_offset_from(base), 0x50u64);
254 assert_eq!(addr.checked_offset_from(base), Some(0x50u64));
255 assert_eq!(base.checked_offset_from(addr), None);
256 }
257
258 #[test]
259 fn test_equals() {
260 let a = MockAddress(0x300);
261 let b = MockAddress(0x300);
262 let c = MockAddress(0x301);
263 assert_eq!(a, MockAddress(a.raw_value()));
264 assert_eq!(a, b);
265 assert_eq!(b, a);
266 assert_ne!(a, c);
267 assert_ne!(c, a);
268 }
269
270 #[test]
271 fn test_cmp() {
272 let a = MockAddress(0x300);
273 let b = MockAddress(0x301);
274 assert!(a < b);
275 }
276
277 #[test]
278 fn test_checked_align_up() {
279 assert_eq!(
280 MockAddress::new(0x128).checked_align_up(8),
281 Some(MockAddress(0x128))
282 );
283 assert_eq!(
284 MockAddress::new(0x128).checked_align_up(16),
285 Some(MockAddress(0x130))
286 );
287 assert_eq!(
288 MockAddress::new(std::u64::MAX - 0x3fff).checked_align_up(0x10000),
289 None
290 );
291 }
292
293 #[test]
294 #[should_panic]
295 fn test_checked_align_up_invalid() {
296 let _ = MockAddress::new(0x128).checked_align_up(12);
297 }
298
299 #[test]
300 fn test_unchecked_align_up() {
301 assert_eq!(
302 MockAddress::new(0x128).unchecked_align_up(8),
303 MockAddress(0x128)
304 );
305 assert_eq!(
306 MockAddress::new(0x128).unchecked_align_up(16),
307 MockAddress(0x130)
308 );
309 }
310
311 #[test]
312 fn test_mask() {
313 let a = MockAddress(0x5050);
314 assert_eq!(MockAddress(0x5000), a & 0xff00u64);
315 assert_eq!(0x5000, a.mask(0xff00u64));
316 assert_eq!(MockAddress(0x5055), a | 0x0005u64);
317 }
318
319 fn check_add(a: u64, b: u64, expected_overflow: bool, expected_result: u64) {
320 assert_eq!(
321 (MockAddress(expected_result), expected_overflow),
322 MockAddress(a).overflowing_add(b)
323 );
324 if expected_overflow {
325 assert!(MockAddress(a).checked_add(b).is_none());
326 #[cfg(debug_assertions)]
327 assert!(std::panic::catch_unwind(|| MockAddress(a).unchecked_add(b)).is_err());
328 } else {
329 assert_eq!(
330 Some(MockAddress(expected_result)),
331 MockAddress(a).checked_add(b)
332 );
333 assert_eq!(
334 MockAddress(expected_result),
335 MockAddress(a).unchecked_add(b)
336 );
337 }
338 }
339
340 #[test]
341 fn test_add() {
342 check_add(10, 10, false, 20);
345 check_add(std::u64::MAX - 1, 1, false, std::u64::MAX);
347
348 check_add(std::u64::MAX, 1, true, 0);
350 }
351
352 fn check_sub(a: u64, b: u64, expected_overflow: bool, expected_result: u64) {
353 assert_eq!(
354 (MockAddress(expected_result), expected_overflow),
355 MockAddress(a).overflowing_sub(b)
356 );
357 if expected_overflow {
358 assert!(MockAddress(a).checked_sub(b).is_none());
359 assert!(MockAddress(a).checked_offset_from(MockAddress(b)).is_none());
360 #[cfg(debug_assertions)]
361 assert!(std::panic::catch_unwind(|| MockAddress(a).unchecked_sub(b)).is_err());
362 } else {
363 assert_eq!(
364 Some(MockAddress(expected_result)),
365 MockAddress(a).checked_sub(b)
366 );
367 assert_eq!(
368 Some(expected_result),
369 MockAddress(a).checked_offset_from(MockAddress(b))
370 );
371 assert_eq!(
372 MockAddress(expected_result),
373 MockAddress(a).unchecked_sub(b)
374 );
375 }
376 }
377
378 #[test]
379 fn test_sub() {
380 check_sub(20, 10, false, 10);
383 check_sub(1, 1, false, 0);
385
386 check_sub(0, 1, true, std::u64::MAX);
388 }
389
390 #[test]
391 fn test_default() {
392 assert_eq!(MockAddress::default(), MockAddress(0));
393 }
394
395 #[test]
396 fn test_bit_and() {
397 let a = MockAddress(0x0ff0);
398 assert_eq!(a & 0xf00f, MockAddress(0));
399 }
400
401 #[test]
402 fn test_bit_or() {
403 let a = MockAddress(0x0ff0);
404 assert_eq!(a | 0xf00f, MockAddress(0xffff));
405 }
406}