1use core::cmp::Ord;
2
3pub trait MemoryAddr:
13 Copy
15 + From<usize>
17 + Into<usize>
18 + Ord
20{
21 #[inline]
29 #[must_use = "this returns a new address, without modifying the original"]
30 fn align_down<U>(self, align: U) -> Self
31 where
32 U: Into<usize>,
33 {
34 Self::from(crate::align_down(self.into(), align.into()))
35 }
36
37 #[inline]
39 #[must_use = "this returns a new address, without modifying the original"]
40 fn align_up<U>(self, align: U) -> Self
41 where
42 U: Into<usize>,
43 {
44 Self::from(crate::align_up(self.into(), align.into()))
45 }
46
47 #[inline]
49 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
50 fn align_offset<U>(self, align: U) -> usize
51 where
52 U: Into<usize>,
53 {
54 crate::align_offset(self.into(), align.into())
55 }
56
57 #[inline]
59 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
60 fn is_aligned<U>(self, align: U) -> bool
61 where
62 U: Into<usize>,
63 {
64 crate::is_aligned(self.into(), align.into())
65 }
66
67 #[inline]
69 #[must_use = "this returns a new address, without modifying the original"]
70 fn align_down_4k(self) -> Self {
71 Self::from(crate::align_down(self.into(), crate::PAGE_SIZE_4K))
72 }
73
74 #[inline]
76 #[must_use = "this returns a new address, without modifying the original"]
77 fn align_up_4k(self) -> Self {
78 Self::from(crate::align_up(self.into(), crate::PAGE_SIZE_4K))
79 }
80
81 #[inline]
83 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
84 fn align_offset_4k(self) -> usize {
85 crate::align_offset(self.into(), crate::PAGE_SIZE_4K)
86 }
87
88 #[inline]
90 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
91 fn is_aligned_4k(self) -> bool {
92 crate::is_aligned(self.into(), crate::PAGE_SIZE_4K)
93 }
94
95 #[inline]
105 #[must_use = "this returns a new address, without modifying the original"]
106 fn offset(self, offset: isize) -> Self {
107 Self::from(usize::checked_add_signed(self.into(), offset).expect("overflow in `MemoryAddr::offset`"))
109 }
110
111 #[inline]
115 #[must_use = "this returns a new address, without modifying the original"]
116 fn wrapping_offset(self, offset: isize) -> Self {
117 Self::from(usize::wrapping_add_signed(self.into(), offset))
118 }
119
120 #[inline]
126 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
127 fn offset_from(self, base: Self) -> isize {
128 let result = usize::wrapping_sub(self.into(), base.into()) as isize;
129 if (result > 0) ^ (base < self) {
130 panic!("overflow in `MemoryAddr::offset_from`");
132 } else {
133 result
134 }
135 }
136
137 #[inline]
145 #[must_use = "this returns a new address, without modifying the original"]
146 fn add(self, rhs: usize) -> Self {
147 Self::from(usize::checked_add(self.into(), rhs).expect("overflow in `MemoryAddr::add`"))
148 }
149
150 #[inline]
154 #[must_use = "this returns a new address, without modifying the original"]
155 fn wrapping_add(self, rhs: usize) -> Self {
156 Self::from(usize::wrapping_add(self.into(), rhs))
157 }
158
159 #[inline]
164 #[must_use = "this returns a new address, without modifying the original"]
165 fn overflowing_add(self, rhs: usize) -> (Self, bool) {
166 let (result, overflow) = self.into().overflowing_add(rhs);
167 (Self::from(result), overflow)
168 }
169
170 #[inline]
174 #[must_use = "this returns a new address, without modifying the original"]
175 fn checked_add(self, rhs: usize) -> Option<Self> {
176 usize::checked_add(self.into(), rhs).map(Self::from)
177 }
178
179 #[inline]
187 #[must_use = "this returns a new address, without modifying the original"]
188 fn sub(self, rhs: usize) -> Self {
189 Self::from(usize::checked_sub(self.into(), rhs).expect("overflow in `MemoryAddr::sub`"))
190 }
191
192 #[inline]
196 #[must_use = "this returns a new address, without modifying the original"]
197 fn wrapping_sub(self, rhs: usize) -> Self {
198 Self::from(usize::wrapping_sub(self.into(), rhs))
199 }
200
201 #[inline]
206 #[must_use = "this returns a new address, without modifying the original"]
207 fn overflowing_sub(self, rhs: usize) -> (Self, bool) {
208 let (result, overflow) = self.into().overflowing_sub(rhs);
209 (Self::from(result), overflow)
210 }
211
212 #[inline]
216 #[must_use = "this returns a new address, without modifying the original"]
217 fn checked_sub(self, rhs: usize) -> Option<Self> {
218 usize::checked_sub(self.into(), rhs).map(Self::from)
219 }
220
221 #[inline]
227 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
228 fn sub_addr(self, rhs: Self) -> usize {
229 usize::checked_sub(self.into(), rhs.into()).expect("overflow in `MemoryAddr::sub_addr`")
230 }
231
232 #[inline]
236 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
237 fn wrapping_sub_addr(self, rhs: Self) -> usize {
238 usize::wrapping_sub(self.into(), rhs.into())
239 }
240
241 #[inline]
246 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
247 fn overflowing_sub_addr(self, rhs: Self) -> (usize, bool) {
248 usize::overflowing_sub(self.into(), rhs.into())
249 }
250
251 #[inline]
255 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
256 fn checked_sub_addr(self, rhs: Self) -> Option<usize> {
257 usize::checked_sub(self.into(), rhs.into())
258 }
259}
260
261impl<T> MemoryAddr for T where T: Copy + From<usize> + Into<usize> + Ord {}
264
265#[macro_export]
306macro_rules! def_usize_addr {
307 (
308 $(#[$meta:meta])*
309 $vis:vis type $name:ident;
310
311 $($tt:tt)*
312 ) => {
313 #[repr(transparent)]
314 #[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)]
315 $(#[$meta])*
316 pub struct $name(usize);
317
318 impl $name {
319 #[doc = concat!("Converts an `usize` to an [`", stringify!($name), "`].")]
320 #[inline]
321 pub const fn from_usize(addr: usize) -> Self {
322 Self(addr)
323 }
324
325 #[doc = concat!("Converts an [`", stringify!($name), "`] to an `usize`.")]
326 #[inline]
327 pub const fn as_usize(self) -> usize {
328 self.0
329 }
330 }
331
332 impl From<usize> for $name {
333 #[inline]
334 fn from(addr: usize) -> Self {
335 Self(addr)
336 }
337 }
338
339 impl From<$name> for usize {
340 #[inline]
341 fn from(addr: $name) -> usize {
342 addr.0
343 }
344 }
345
346 impl core::ops::Add<usize> for $name {
347 type Output = Self;
348 #[inline]
349 fn add(self, rhs: usize) -> Self {
350 Self(self.0 + rhs)
351 }
352 }
353
354 impl core::ops::AddAssign<usize> for $name {
355 #[inline]
356 fn add_assign(&mut self, rhs: usize) {
357 self.0 += rhs;
358 }
359 }
360
361 impl core::ops::Sub<usize> for $name {
362 type Output = Self;
363 #[inline]
364 fn sub(self, rhs: usize) -> Self {
365 Self(self.0 - rhs)
366 }
367 }
368
369 impl core::ops::SubAssign<usize> for $name {
370 #[inline]
371 fn sub_assign(&mut self, rhs: usize) {
372 self.0 -= rhs;
373 }
374 }
375
376 impl core::ops::Sub<$name> for $name {
377 type Output = usize;
378 #[inline]
379 fn sub(self, rhs: $name) -> usize {
380 self.0 - rhs.0
381 }
382 }
383
384 $crate::def_usize_addr!($($tt)*);
385 };
386 () => {};
387}
388
389#[macro_export]
424macro_rules! def_usize_addr_formatter {
425 (
426 $name:ident = $format:literal;
427
428 $($tt:tt)*
429 ) => {
430 impl core::fmt::Debug for $name {
431 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
432 f.write_fmt(format_args!($format, format_args!("{:#x}", self.0)))
433 }
434 }
435
436 impl core::fmt::LowerHex for $name {
437 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
438 f.write_fmt(format_args!($format, format_args!("{:#x}", self.0)))
439 }
440 }
441
442 impl core::fmt::UpperHex for $name {
443 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
444 f.write_fmt(format_args!($format, format_args!("{:#X}", self.0)))
445 }
446 }
447
448 $crate::def_usize_addr_formatter!($($tt)*);
449 };
450 () => {};
451}
452
453def_usize_addr! {
454 pub type PhysAddr;
456
457 pub type VirtAddr;
459}
460
461def_usize_addr_formatter! {
462 PhysAddr = "PA:{}";
463 VirtAddr = "VA:{}";
464}
465
466impl VirtAddr {
467 #[inline]
469 pub fn from_ptr_of<T>(ptr: *const T) -> Self {
470 Self(ptr as usize)
471 }
472
473 #[inline]
475 pub fn from_mut_ptr_of<T>(ptr: *mut T) -> Self {
476 Self(ptr as usize)
477 }
478
479 #[inline]
481 pub const fn as_ptr(self) -> *const u8 {
482 self.0 as *const u8
483 }
484
485 #[inline]
487 pub const fn as_ptr_of<T>(self) -> *const T {
488 self.0 as *const T
489 }
490
491 #[inline]
493 pub const fn as_mut_ptr(self) -> *mut u8 {
494 self.0 as *mut u8
495 }
496
497 #[inline]
500 pub const fn as_mut_ptr_of<T>(self) -> *mut T {
501 self.0 as *mut T
502 }
503}
504
505#[macro_export]
507macro_rules! pa {
508 ($addr:expr) => {
509 $crate::PhysAddr::from_usize($addr)
510 };
511}
512
513#[macro_export]
515macro_rules! va {
516 ($addr:expr) => {
517 $crate::VirtAddr::from_usize($addr)
518 };
519}
520
521#[cfg(test)]
522mod test {
523
524 use super::*;
525
526 def_usize_addr! {
527 pub type ExampleAddr;
529 pub type AnotherAddr;
531 }
532
533 def_usize_addr_formatter! {
534 ExampleAddr = "EA:{}";
535 AnotherAddr = "AA:{}";
536 }
537
538 #[test]
539 pub fn test_alignment() {
540 let alignment = 0x1000usize;
541 let base = alignment * 2;
542 let offset = 0x123usize;
543 let addr = ExampleAddr::from_usize(base + offset);
544
545 assert_eq!(addr.align_down(alignment), ExampleAddr::from_usize(base));
546 assert_eq!(
547 addr.align_up(alignment),
548 ExampleAddr::from_usize(base + alignment)
549 );
550 assert_eq!(addr.align_offset(alignment), offset);
551 assert!(!addr.is_aligned(alignment));
552 assert!(ExampleAddr::from_usize(base).is_aligned(alignment));
553 assert_eq!(
554 ExampleAddr::from_usize(base).align_up(alignment),
555 ExampleAddr::from_usize(base)
556 );
557 }
558
559 #[test]
560 pub fn test_addr_wrapping_arithmetic() {
561 let base = usize::MAX - 0x100usize;
562 let offset = 0x200usize;
563 let with_offset = base.wrapping_add(offset);
564
565 let addr = ExampleAddr::from_usize(base);
566 let offset_addr = ExampleAddr::from_usize(with_offset);
567
568 assert_eq!(addr.wrapping_offset(offset as isize), offset_addr);
569 assert_eq!(offset_addr.wrapping_offset(-(offset as isize)), addr);
570 assert_eq!(addr.wrapping_add(offset), offset_addr);
571 assert_eq!(offset_addr.wrapping_sub(offset), addr);
572 assert_eq!(offset_addr.wrapping_sub_addr(addr), offset);
573 }
574
575 #[test]
576 pub fn test_addr_checked_arithmetic() {
577 let low_addr = ExampleAddr::from_usize(0x100usize);
578 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
579 let small_offset = 0x50usize;
580 let large_offset = 0x200usize;
581
582 assert_eq!(
583 low_addr.checked_sub(small_offset),
584 Some(low_addr.wrapping_sub(small_offset))
585 );
586 assert_eq!(low_addr.checked_sub(large_offset), None);
587 assert_eq!(
588 high_addr.checked_add(small_offset),
589 Some(high_addr.wrapping_add(small_offset))
590 );
591 assert_eq!(high_addr.checked_add(large_offset), None);
592
593 assert_eq!(
594 high_addr.checked_sub_addr(low_addr),
595 Some(usize::MAX - 0x200usize)
596 );
597 assert_eq!(low_addr.checked_sub_addr(high_addr), None);
598 }
599
600 #[test]
601 pub fn test_addr_overflowing_arithmetic() {
602 let low_addr = ExampleAddr::from_usize(0x100usize);
603 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
604 let small_offset = 0x50usize;
605 let large_offset = 0x200usize;
606
607 assert_eq!(
608 low_addr.overflowing_sub(small_offset),
609 (low_addr.wrapping_sub(small_offset), false)
610 );
611 assert_eq!(
612 low_addr.overflowing_sub(large_offset),
613 (low_addr.wrapping_sub(large_offset), true)
614 );
615 assert_eq!(
616 high_addr.overflowing_add(small_offset),
617 (high_addr.wrapping_add(small_offset), false)
618 );
619 assert_eq!(
620 high_addr.overflowing_add(large_offset),
621 (high_addr.wrapping_add(large_offset), true)
622 );
623 assert_eq!(
624 high_addr.overflowing_sub_addr(low_addr),
625 (high_addr.wrapping_sub_addr(low_addr), false)
626 );
627 assert_eq!(
628 low_addr.overflowing_sub_addr(high_addr),
629 (low_addr.wrapping_sub_addr(high_addr), true)
630 );
631 }
632
633 #[test]
634 #[should_panic]
635 pub fn test_addr_offset_overflow() {
636 let addr = ExampleAddr::from_usize(usize::MAX);
637 let _ = addr.offset(1);
638 }
639
640 #[test]
641 #[should_panic]
642 pub fn test_addr_offset_from_overflow() {
643 let addr = ExampleAddr::from_usize(usize::MAX);
644 let _ = addr.offset_from(ExampleAddr::from_usize(0));
645 }
646
647 #[test]
648 #[should_panic]
649 pub fn test_addr_offset_from_underflow() {
650 let addr = ExampleAddr::from_usize(0);
651 let _ = addr.offset_from(ExampleAddr::from_usize(usize::MAX));
652 }
653
654 #[test]
655 #[should_panic]
656 pub fn test_addr_add_overflow() {
657 let addr = ExampleAddr::from_usize(usize::MAX);
658 let _ = addr.add(1);
659 }
660
661 #[test]
662 #[should_panic]
663 pub fn test_addr_sub_underflow() {
664 let addr = ExampleAddr::from_usize(0);
665 let _ = addr.sub(1);
666 }
667
668 #[test]
669 #[should_panic]
670 pub fn test_addr_sub_addr_overflow() {
671 let addr = ExampleAddr::from_usize(0);
672 let _ = addr.sub_addr(ExampleAddr::from_usize(1));
673 }
674}