1use super::{PhysicalAddress, Pointer};
6use crate::types::ByteSwap;
7
8use core::convert::TryInto;
9use std::default::Default;
10use std::fmt;
11use std::hash;
12use std::ops;
13
14#[cfg(feature = "64_bit_mem")]
26#[allow(non_camel_case_types)]
27pub type umem = u64;
28#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
29#[allow(non_camel_case_types)]
30pub type umem = u128;
31#[cfg(all(not(feature = "64_bit_mem"), not(feature = "128_bit_mem")))]
32#[allow(non_camel_case_types)]
33pub type umem = usize;
34#[cfg(feature = "64_bit_mem")]
35#[allow(non_camel_case_types)]
36pub type imem = i64;
37#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
38#[allow(non_camel_case_types)]
39pub type imem = i128;
40#[cfg(all(not(feature = "64_bit_mem"), not(feature = "128_bit_mem")))]
41#[allow(non_camel_case_types)]
42pub type imem = isize;
43
44pub const UMEM_BITS: u8 = core::mem::size_of::<umem>() as u8 * 8;
45
46const _: [u8; (core::mem::size_of::<usize>() <= core::mem::size_of::<umem>()) as usize] = [0; 1];
49
50pub const fn clamp_to_usize(val: umem) -> usize {
51 let max = usize::MAX as umem;
52
53 let ret = if max < val { max } else { val };
54
55 ret as usize
56}
57
58pub const fn clamp_to_isize(val: imem) -> isize {
59 let max = isize::MAX as imem;
60 let min = isize::MIN as imem;
61
62 let ret = if max < val {
63 max
64 } else if min > val {
65 min
66 } else {
67 val
68 };
69
70 ret as isize
71}
72
73pub trait PrimitiveAddress:
77 Copy
78 + Eq
79 + PartialEq
80 + Ord
81 + PartialOrd
82 + hash::Hash
83 + fmt::LowerHex
84 + fmt::UpperHex
85 + ByteSwap
86 + ops::Add<Output = Self>
87 + ops::Sub<Output = Self>
88{
89 fn null() -> Self;
90 fn invalid() -> Self;
91
92 fn min() -> Self;
93 fn max() -> Self;
94
95 fn from_umem(frm: umem) -> Self;
96 fn from_imem(frm: imem) -> Self;
97
98 fn wrapping_add(self, rhs: Self) -> Self;
99 fn wrapping_sub(self, rhs: Self) -> Self;
100 fn saturating_sub(self, rhs: Self) -> Self;
101 fn overflowing_shr(self, rhs: u32) -> (Self, bool);
102
103 fn to_umem(self) -> umem;
104 fn to_imem(self) -> imem;
105
106 #[inline]
107 fn is_null(self) -> bool {
108 self.eq(&Self::null())
109 }
110}
111
112#[macro_export]
113macro_rules! impl_primitive_address {
114 ($type_name:ident) => {
115 impl PrimitiveAddress for $type_name {
116 #[inline]
117 fn null() -> Self {
118 0 as $type_name
119 }
120
121 #[inline]
122 fn invalid() -> Self {
123 !Self::null()
124 }
125
126 #[inline]
127 fn min() -> Self {
128 Self::MIN
129 }
130
131 #[inline]
132 fn max() -> Self {
133 Self::MAX
134 }
135
136 #[inline]
137 fn from_umem(frm: umem) -> Self {
138 frm as Self
139 }
140
141 #[inline]
142 fn from_imem(frm: imem) -> Self {
143 frm as Self
144 }
145
146 #[inline]
147 fn wrapping_add(self, rhs: Self) -> Self {
148 self.wrapping_add(rhs)
149 }
150
151 #[inline]
152 fn wrapping_sub(self, rhs: Self) -> Self {
153 self.wrapping_sub(rhs)
154 }
155
156 #[inline]
157 fn saturating_sub(self, rhs: Self) -> Self {
158 self.saturating_sub(rhs)
159 }
160
161 #[inline]
162 fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
163 self.overflowing_shr(rhs)
164 }
165
166 #[inline]
167 fn to_umem(self) -> umem {
168 self as umem
169 }
170
171 #[inline]
172 fn to_imem(self) -> imem {
173 self as imem
174 }
175 }
176 };
177}
178
179impl_primitive_address!(u16);
180impl_primitive_address!(u32);
181impl_primitive_address!(u64);
182#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
183impl_primitive_address!(u128);
184
185#[repr(transparent)]
191#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
192#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
193#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
194pub struct Address(umem);
195
196impl Address {
197 pub const NULL: Address = Address(0);
207
208 pub const INVALID: Address = Address(!0);
218
219 #[inline]
229 pub const fn null() -> Self {
230 Address::NULL
231 }
232
233 pub fn bit_mask<T>(bits: ops::RangeInclusive<T>) -> Address
244 where
245 T: TryInto<u8> + Copy,
246 {
247 Address(
248 (!0 >> ((UMEM_BITS - 1) - (*bits.end()).try_into().ok().unwrap()))
249 & !((1 << (*bits.start()).try_into().ok().unwrap()) - 1),
250 )
251 }
252
253 pub const fn bit_mask_u8(bits: ops::RangeInclusive<u8>) -> Address {
264 Address((!0 >> (UMEM_BITS - 1 - *bits.end())) & !((1 << *bits.start()) - 1))
265 }
266
267 #[inline]
278 pub const fn is_null(self) -> bool {
279 self.0 == 0
280 }
281
282 #[inline]
293 pub fn non_null(self) -> Option<Address> {
294 if self.is_null() {
295 None
296 } else {
297 Some(self)
298 }
299 }
300
301 #[inline]
311 pub const fn invalid() -> Self {
312 Address::INVALID
313 }
314
315 #[inline]
326 pub const fn is_valid(self) -> bool {
327 self.0 != !0
328 }
329
330 #[inline]
342 pub const fn to_umem(self) -> umem {
343 self.0
344 }
345
346 pub const fn as_mem_aligned(self, mem_size: umem) -> Self {
359 Self(self.0 - self.0 % mem_size)
360 }
361
362 pub const fn as_page_aligned(self, page_size: usize) -> Self {
363 self.as_mem_aligned(page_size as umem)
364 }
365
366 pub const fn bit_at(self, idx: u8) -> bool {
379 (self.0 & (1 << idx)) != 0
380 }
381
382 pub fn extract_bits<T>(self, bits: ops::RangeInclusive<T>) -> Address
394 where
395 T: TryInto<u8> + Copy,
396 {
397 (self.0 & Address::bit_mask(bits).to_umem()).into()
398 }
399
400 pub const fn wrapping_add(self, other: Self) -> Self {
403 Self(self.0.wrapping_add(other.0))
404 }
405
406 pub const fn wrapping_sub(self, other: Self) -> Self {
409 Self(self.0.wrapping_sub(other.0))
410 }
411}
412
413impl Default for Address {
423 fn default() -> Self {
424 Self::null()
425 }
426}
427
428impl ByteSwap for Address {
430 fn byte_swap(&mut self) {
431 self.0.byte_swap();
432 }
433}
434
435#[macro_export]
436macro_rules! impl_address_from {
437 ($type_name:ident) => {
438 impl From<$type_name> for Address {
439 fn from(item: $type_name) -> Self {
440 Self { 0: item as umem }
441 }
442 }
443
444 impl<T: ?Sized> From<Pointer<$type_name, T>> for Address {
445 #[inline(always)]
446 fn from(ptr: Pointer<$type_name, T>) -> Self {
447 Self {
448 0: ptr.inner as umem,
449 }
450 }
451 }
452 };
453}
454
455impl_address_from!(i8);
457impl_address_from!(u8);
458impl_address_from!(i16);
459impl_address_from!(i32);
461impl_address_from!(i64);
463impl_address_from!(usize);
465#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
466impl_address_from!(i128);
467
468impl<U: PrimitiveAddress> From<U> for Address {
470 #[inline(always)]
471 fn from(val: U) -> Self {
472 Self(val.to_umem())
473 }
474}
475
476impl From<PhysicalAddress> for Address {
478 fn from(address: PhysicalAddress) -> Self {
479 address.address
480 }
481}
482
483impl<U: PrimitiveAddress, T: ?Sized> From<Pointer<U, T>> for Address {
485 #[inline(always)]
486 fn from(ptr: Pointer<U, T>) -> Self {
487 Self(ptr.inner.to_umem())
488 }
489}
490
491#[macro_export]
492macro_rules! impl_address_arithmetic_unsigned {
493 ($type_name:ident) => {
494 impl ops::Add<$type_name> for Address {
495 type Output = Self;
496
497 fn add(self, other: $type_name) -> Self {
498 Self {
499 0: self.0 + (other as umem),
500 }
501 }
502 }
503
504 impl ops::AddAssign<$type_name> for Address {
505 fn add_assign(&mut self, other: $type_name) {
506 *self = Self {
507 0: self.0 + (other as umem),
508 }
509 }
510 }
511
512 impl ops::Sub<$type_name> for Address {
513 type Output = Address;
514
515 fn sub(self, other: $type_name) -> Address {
516 Self {
517 0: self.0 - (other as umem),
518 }
519 }
520 }
521
522 impl ops::SubAssign<$type_name> for Address {
523 fn sub_assign(&mut self, other: $type_name) {
524 *self = Self {
525 0: self.0 - (other as umem),
526 }
527 }
528 }
529 };
530}
531
532#[macro_export]
533macro_rules! impl_address_arithmetic_signed {
534 ($type_name:ident) => {
535 impl ops::Add<$type_name> for Address {
536 type Output = Self;
537
538 fn add(self, other: $type_name) -> Self {
539 if other >= 0 {
540 Self {
541 0: self.0 + (other as umem),
542 }
543 } else {
544 Self {
545 0: self.0 - (-other as umem),
546 }
547 }
548 }
549 }
550
551 impl ops::AddAssign<$type_name> for Address {
552 fn add_assign(&mut self, other: $type_name) {
553 if other >= 0 {
554 *self = Self {
555 0: self.0 + (other as umem),
556 }
557 } else {
558 *self = Self {
559 0: self.0 - (-other as umem),
560 }
561 }
562 }
563 }
564
565 impl ops::Sub<$type_name> for Address {
566 type Output = Address;
567
568 fn sub(self, other: $type_name) -> Address {
569 if other >= 0 {
570 Self {
571 0: self.0 - (other as umem),
572 }
573 } else {
574 Self {
575 0: self.0 + (-other as umem),
576 }
577 }
578 }
579 }
580
581 impl ops::SubAssign<$type_name> for Address {
582 fn sub_assign(&mut self, other: $type_name) {
583 if other >= 0 {
584 *self = Self {
585 0: self.0 - (other as umem),
586 }
587 } else {
588 *self = Self {
589 0: self.0 + (-other as umem),
590 }
591 }
592 }
593 }
594 };
595}
596
597impl_address_arithmetic_signed!(i8);
598impl_address_arithmetic_signed!(i16);
599impl_address_arithmetic_signed!(i32);
600impl_address_arithmetic_signed!(i64);
601#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
602impl_address_arithmetic_signed!(i128);
603impl_address_arithmetic_signed!(isize);
604impl_address_arithmetic_unsigned!(u8);
605impl_address_arithmetic_unsigned!(u16);
606impl_address_arithmetic_unsigned!(u32);
607impl_address_arithmetic_unsigned!(u64);
608#[cfg(all(feature = "128_bit_mem", not(feature = "64_bit_mem")))]
609impl_address_arithmetic_unsigned!(u128);
610impl_address_arithmetic_unsigned!(usize);
611
612impl<'a, T: Into<umem> + Copy> ops::Add<&'a T> for Address {
614 type Output = Self;
615
616 fn add(self, other: &'a T) -> Self {
617 Self(self.0 + (*other).into())
618 }
619}
620
621impl<'a, T: Into<umem> + Copy> ops::Sub<&'a T> for Address {
623 type Output = Self;
624
625 fn sub(self, other: &'a T) -> Self {
626 Self(self.0 - (*other).into())
627 }
628}
629
630impl ops::Sub for Address {
640 type Output = imem;
641
642 fn sub(self, other: Self) -> imem {
643 if self.0 > other.0 {
644 (self.0 - other.0) as imem
645 } else {
646 -((other.0 - self.0) as imem)
647 }
648 }
649}
650
651impl fmt::Debug for Address {
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
653 write!(f, "{:x}", self.0)
654 }
655}
656impl fmt::UpperHex for Address {
657 #[inline(always)]
658 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
659 write!(f, "{:X}", self.0)
660 }
661}
662impl fmt::LowerHex for Address {
663 #[inline(always)]
664 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
665 write!(f, "{:x}", self.0)
666 }
667}
668impl fmt::Display for Address {
669 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
670 write!(f, "{:x}", self.0)
671 }
672}
673
674#[cfg(test)]
675mod tests {
676 use super::super::size;
677 use super::*;
678
679 #[test]
680 fn test_null_valid() {
681 assert!(Address::null().is_null());
682 assert!(!Address::invalid().is_valid());
683 }
684
685 #[test]
686 fn test_from() {
687 assert_eq!(Address::from(1337_u32).to_umem(), 1337);
688 assert_eq!(Address::from(4321_u64).to_umem(), 4321);
689 }
690
691 #[test]
692 fn test_alignment() {
693 assert_eq!(
694 Address::from(0x1234_u64).as_page_aligned(size::kb(4)),
695 Address::from(0x1000_u64)
696 );
697 assert_eq!(
698 Address::from(0xFFF1_2345_u64).as_page_aligned(0x10000),
699 Address::from(0xFFF1_0000_u64)
700 );
701 }
702
703 #[test]
704 fn test_bits() {
705 assert!(Address::from(1_u64).bit_at(0));
706 assert!(!Address::from(1_u64).bit_at(1));
707 assert!(!Address::from(1_u64).bit_at(2));
708 assert!(!Address::from(1_u64).bit_at(3));
709
710 assert!(!Address::from(2_u64).bit_at(0));
711 assert!(Address::from(2_u64).bit_at(1));
712 assert!(!Address::from(2_u64).bit_at(2));
713 assert!(!Address::from(2_u64).bit_at(3));
714
715 assert!(Address::from(13_u64).bit_at(0));
716 assert!(!Address::from(13_u64).bit_at(1));
717 assert!(Address::from(13_u64).bit_at(2));
718 assert!(Address::from(13_u64).bit_at(3));
719 }
720
721 #[test]
722 fn test_bit_mask() {
723 assert_eq!(Address::bit_mask(0..=11).to_umem(), 0xfff);
724 assert_eq!(Address::bit_mask(12..=20).to_umem(), 0x001f_f000);
725 assert_eq!(Address::bit_mask(21..=29).to_umem(), 0x3fe0_0000);
726 assert_eq!(Address::bit_mask(30..=38).to_umem(), 0x007f_c000_0000);
727 assert_eq!(Address::bit_mask(39..=47).to_umem(), 0xff80_0000_0000);
728 assert_eq!(Address::bit_mask(12..=51).to_umem(), 0x000f_ffff_ffff_f000);
729 }
730
731 #[test]
732 fn test_bit_mask_u8() {
733 assert_eq!(Address::bit_mask_u8(0..=11).to_umem(), 0xfff);
734 assert_eq!(Address::bit_mask_u8(12..=20).to_umem(), 0x001f_f000);
735 assert_eq!(Address::bit_mask_u8(21..=29).to_umem(), 0x3fe0_0000);
736 assert_eq!(Address::bit_mask_u8(30..=38).to_umem(), 0x007f_c000_0000);
737 assert_eq!(Address::bit_mask_u8(39..=47).to_umem(), 0xff80_0000_0000);
738 assert_eq!(
739 Address::bit_mask_u8(12..=51).to_umem(),
740 0x000f_ffff_ffff_f000
741 );
742 }
743
744 #[test]
745 fn test_ops() {
746 assert_eq!(Address::from(10_u64) + 5usize, Address::from(15_u64));
747
748 assert_eq!(Address::from(10_u64) - Address::from(5_u64), 5);
749 assert_eq!(Address::from(100_u64) - 5usize, Address::from(95_u64));
750 }
751}