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 use core::mem::size_of;
524
525 use super::*;
526
527 def_usize_addr! {
528 pub type ExampleAddr;
530 pub type AnotherAddr;
532 }
533
534 def_usize_addr_formatter! {
535 ExampleAddr = "EA:{}";
536 AnotherAddr = "AA:{}";
537 }
538
539 #[test]
540 fn test_addr() {
541 let addr = va!(0x2000);
542 assert!(addr.is_aligned_4k());
543 assert!(!addr.is_aligned(0x10000usize));
544 assert_eq!(addr.align_offset_4k(), 0);
545 assert_eq!(addr.align_down_4k(), va!(0x2000));
546 assert_eq!(addr.align_up_4k(), va!(0x2000));
547
548 let addr = va!(0x2fff);
549 assert!(!addr.is_aligned_4k());
550 assert_eq!(addr.align_offset_4k(), 0xfff);
551 assert_eq!(addr.align_down_4k(), va!(0x2000));
552 assert_eq!(addr.align_up_4k(), va!(0x3000));
553
554 let align = 0x100000;
555 let addr = va!(align * 5) + 0x2000;
556 assert!(addr.is_aligned_4k());
557 assert!(!addr.is_aligned(align));
558 assert_eq!(addr.align_offset(align), 0x2000);
559 assert_eq!(addr.align_down(align), va!(align * 5));
560 assert_eq!(addr.align_up(align), va!(align * 6));
561 }
562
563 #[test]
564 pub fn test_addr_convert_and_comparison() {
565 let example1 = ExampleAddr::from_usize(0x1234);
566 let example2 = ExampleAddr::from(0x5678);
567 let another1 = AnotherAddr::from_usize(0x9abc);
568 let another2 = AnotherAddr::from(0xdef0);
569
570 assert_eq!(example1.as_usize(), 0x1234);
571 assert_eq!(Into::<usize>::into(example2), 0x5678);
572 assert_eq!(Into::<usize>::into(another1), 0x9abc);
573 assert_eq!(another2.as_usize(), 0xdef0);
574
575 assert_eq!(example1, ExampleAddr::from(0x1234));
576 assert_eq!(example2, ExampleAddr::from_usize(0x5678));
577 assert_eq!(another1, AnotherAddr::from_usize(0x9abc));
578 assert_eq!(another2, AnotherAddr::from(0xdef0));
579
580 assert!(example1 < example2);
581 assert!(example1 <= example2);
582 assert!(example2 > example1);
583 assert!(example2 >= example1);
584 assert!(example1 != example2);
585 }
586
587 #[test]
588 pub fn test_addr_fmt() {
589 assert_eq!(format!("{:?}", ExampleAddr::from(0x1abc)), "EA:0x1abc");
590 assert_eq!(format!("{:x}", AnotherAddr::from(0x1abc)), "AA:0x1abc");
591 assert_eq!(format!("{:X}", ExampleAddr::from(0x1abc)), "EA:0x1ABC");
592 }
593
594 #[test]
595 pub fn test_alignment() {
596 let alignment = 0x1000usize;
597 let base = alignment * 2;
598 let offset = 0x123usize;
599 let addr = ExampleAddr::from_usize(base + offset);
600
601 assert_eq!(addr.align_down(alignment), ExampleAddr::from_usize(base));
602 assert_eq!(
603 addr.align_up(alignment),
604 ExampleAddr::from_usize(base + alignment)
605 );
606 assert_eq!(addr.align_offset(alignment), offset);
607 assert!(!addr.is_aligned(alignment));
608 assert!(ExampleAddr::from_usize(base).is_aligned(alignment));
609 assert_eq!(
610 ExampleAddr::from_usize(base).align_up(alignment),
611 ExampleAddr::from_usize(base)
612 );
613 }
614
615 #[test]
616 pub fn test_addr_arithmetic() {
617 let base = 0x1234usize;
618 let offset = 0x100usize;
619 let with_offset = base + offset;
620
621 let addr = ExampleAddr::from_usize(base);
622 let offset_addr = ExampleAddr::from_usize(with_offset);
623
624 assert_eq!(addr.offset(offset as isize), offset_addr);
625 assert_eq!(addr.wrapping_offset(offset as isize), offset_addr);
626 assert_eq!(offset_addr.offset_from(addr), offset as isize);
627 assert_eq!(addr.add(offset), offset_addr);
628 assert_eq!(addr.wrapping_add(offset), offset_addr);
629 assert_eq!(offset_addr.sub(offset), addr);
630 assert_eq!(offset_addr.wrapping_sub(offset), addr);
631 assert_eq!(offset_addr.sub_addr(addr), offset);
632 assert_eq!(offset_addr.wrapping_sub_addr(addr), offset);
633
634 assert_eq!(addr + offset, offset_addr);
635 assert_eq!(offset_addr - offset, addr);
636 assert_eq!(offset_addr - addr, offset);
637 }
638
639 #[test]
640 pub fn test_addr_wrapping_arithmetic() {
641 let base = usize::MAX - 0x100usize;
642 let offset = 0x200usize;
643 let with_offset = base.wrapping_add(offset);
644
645 let addr = ExampleAddr::from_usize(base);
646 let offset_addr = ExampleAddr::from_usize(with_offset);
647
648 assert_eq!(addr.wrapping_offset(offset as isize), offset_addr);
649 assert_eq!(offset_addr.wrapping_offset(-(offset as isize)), addr);
650 assert_eq!(addr.wrapping_add(offset), offset_addr);
651 assert_eq!(offset_addr.wrapping_sub(offset), addr);
652 assert_eq!(offset_addr.wrapping_sub_addr(addr), offset);
653 }
654
655 #[test]
656 pub fn test_addr_checked_arithmetic() {
657 let low_addr = ExampleAddr::from_usize(0x100usize);
658 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
659 let small_offset = 0x50usize;
660 let large_offset = 0x200usize;
661
662 assert_eq!(
663 low_addr.checked_sub(small_offset),
664 Some(low_addr.wrapping_sub(small_offset))
665 );
666 assert_eq!(low_addr.checked_sub(large_offset), None);
667 assert_eq!(
668 high_addr.checked_add(small_offset),
669 Some(high_addr.wrapping_add(small_offset))
670 );
671 assert_eq!(high_addr.checked_add(large_offset), None);
672
673 assert_eq!(
674 high_addr.checked_sub_addr(low_addr),
675 Some(usize::MAX - 0x200usize)
676 );
677 assert_eq!(low_addr.checked_sub_addr(high_addr), None);
678 }
679
680 #[test]
681 pub fn test_addr_overflowing_arithmetic() {
682 let low_addr = ExampleAddr::from_usize(0x100usize);
683 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
684 let small_offset = 0x50usize;
685 let large_offset = 0x200usize;
686
687 assert_eq!(
688 low_addr.overflowing_sub(small_offset),
689 (low_addr.wrapping_sub(small_offset), false)
690 );
691 assert_eq!(
692 low_addr.overflowing_sub(large_offset),
693 (low_addr.wrapping_sub(large_offset), true)
694 );
695 assert_eq!(
696 high_addr.overflowing_add(small_offset),
697 (high_addr.wrapping_add(small_offset), false)
698 );
699 assert_eq!(
700 high_addr.overflowing_add(large_offset),
701 (high_addr.wrapping_add(large_offset), true)
702 );
703 assert_eq!(
704 high_addr.overflowing_sub_addr(low_addr),
705 (high_addr.wrapping_sub_addr(low_addr), false)
706 );
707 assert_eq!(
708 low_addr.overflowing_sub_addr(high_addr),
709 (low_addr.wrapping_sub_addr(high_addr), true)
710 );
711 }
712
713 #[test]
714 #[should_panic]
715 pub fn test_addr_offset_overflow() {
716 let addr = ExampleAddr::from_usize(usize::MAX);
717 let _ = addr.offset(1);
718 }
719
720 #[test]
721 #[should_panic]
722 pub fn test_addr_offset_from_overflow() {
723 let addr = ExampleAddr::from_usize(usize::MAX);
724 let _ = addr.offset_from(ExampleAddr::from_usize(0));
725 }
726
727 #[test]
728 #[should_panic]
729 pub fn test_addr_offset_from_underflow() {
730 let addr = ExampleAddr::from_usize(0);
731 let _ = addr.offset_from(ExampleAddr::from_usize(usize::MAX));
732 }
733
734 #[test]
735 #[should_panic]
736 pub fn test_addr_add_overflow() {
737 let addr = ExampleAddr::from_usize(usize::MAX);
738 let _ = addr.add(1);
739 }
740
741 #[test]
742 #[should_panic]
743 pub fn test_addr_sub_underflow() {
744 let addr = ExampleAddr::from_usize(0);
745 let _ = addr.sub(1);
746 }
747
748 #[test]
749 #[should_panic]
750 pub fn test_addr_sub_addr_overflow() {
751 let addr = ExampleAddr::from_usize(0);
752 let _ = addr.sub_addr(ExampleAddr::from_usize(1));
753 }
754
755 #[test]
756 pub fn test_virt_addr_ptr() {
757 let a: [usize; 4] = [0x1234, 0x5678, 0x9abc, 0xdef0];
758
759 let va0 = VirtAddr::from_ptr_of(&a as *const usize);
760 let va1 = va0.add(size_of::<usize>());
761 let va2 = va1.add(size_of::<usize>());
762 let va3 = va2.add(size_of::<usize>());
763
764 let p0 = va0.as_ptr() as *const usize;
765 let p1 = va1.as_ptr_of::<usize>();
766 let p2 = va2.as_mut_ptr() as *mut usize;
767 let p3 = va3.as_mut_ptr_of::<usize>();
768
769 assert_eq!(va0, VirtAddr::from_ptr_of(p0));
771 assert_eq!(va1, VirtAddr::from_ptr_of(p1));
772 assert_eq!(va2, VirtAddr::from_mut_ptr_of(p2));
773 assert_eq!(va3, VirtAddr::from_mut_ptr_of(p3));
774
775 assert!(unsafe { *p0 } == a[0]);
777 assert!(unsafe { *p1 } == a[1]);
778 assert!(unsafe { *p2 } == a[2]);
779 assert!(unsafe { *p3 } == a[3]);
780
781 unsafe {
782 *p2 = 0xdeadbeef;
783 }
784 unsafe {
785 *p3 = 0xcafebabe;
786 }
787 assert_eq!(a[2], 0xdeadbeef);
788 assert_eq!(a[3], 0xcafebabe);
789 }
790}