memory_addresses/
macros.rs

1//! Helper macros
2
3/// Macro that implements the functionalities that every address type has.
4/// Inspired/adopted from https://github.com/rust-vmm/vm-memory
5macro_rules! impl_address {
6    ($T:ident, $V:ty) => {
7        impl $crate::MemoryAddress for $T {
8            type RAW = $V;
9
10            fn raw(self) -> Self::RAW {
11                self.0
12            }
13        }
14
15        impl $T {
16            /// Creates a new address, without any checks.
17            ///
18            /// # Safety
19            ///
20            /// If `addr` does not comply with the platforms requirements for
21            /// this address type, this can lead to UB in functions relying on
22            /// the compliance or when using the requirements.
23            #[inline]
24            pub const unsafe fn new_unsafe(addr: $V) -> $T {
25                $T(addr)
26            }
27
28            #[inline]
29            /// Convenience method for checking if an address is null.
30            pub const fn is_null(self) -> bool {
31                self.0 == 0
32            }
33
34            /// Creates an address that points to `0`.
35            #[inline]
36            pub const fn zero() -> $T {
37                $T::new(0)
38            }
39
40            paste::paste! {
41                #[doc = "Converts the address to an `" $V "`."]
42                #[inline]
43                pub const fn [< as_ $V >] (self) -> $V {
44                    self.0
45                }
46            }
47        }
48
49        impl core::ops::Add<$V> for $T {
50            type Output = Self;
51            #[inline]
52            fn add(self, rhs: $V) -> Self::Output {
53                $T::new(self.0 + rhs)
54            }
55        }
56
57        impl core::ops::AddAssign<$V> for $T {
58            #[inline]
59            fn add_assign(&mut self, rhs: $V) {
60                *self = *self + rhs;
61            }
62        }
63
64        impl core::ops::Sub<$V> for $T {
65            type Output = Self;
66            #[inline]
67            fn sub(self, rhs: $V) -> Self::Output {
68                $T::new(self.0.checked_sub(rhs).unwrap())
69            }
70        }
71
72        impl core::ops::SubAssign<$V> for $T {
73            #[inline]
74            fn sub_assign(&mut self, rhs: $V) {
75                *self = *self - rhs;
76            }
77        }
78
79        impl core::ops::Sub<$T> for $T {
80            type Output = $V;
81            #[inline]
82            fn sub(self, rhs: $T) -> Self::Output {
83                paste::paste! {
84                    self.[< as _$V >]().checked_sub(rhs.[< as_ $V >]()).unwrap()
85                }
86            }
87        }
88
89        impl core::ops::BitOr<$V> for $T {
90            type Output = $V;
91            #[inline]
92            fn bitor(self, rhs: $V) -> Self::Output {
93                self.0 | rhs
94            }
95        }
96
97        impl core::ops::BitOrAssign<$V> for $T {
98            #[inline]
99            fn bitor_assign(&mut self, rhs: $V) {
100                *self = Self::new_truncate(self.0 | rhs);
101            }
102        }
103
104        impl core::ops::BitAnd<$V> for $T {
105            type Output = $V;
106            #[inline]
107            fn bitand(self, rhs: $V) -> Self::Output {
108                self.0 & rhs
109            }
110        }
111
112        impl core::ops::BitAndAssign<$V> for $T {
113            #[inline]
114            fn bitand_assign(&mut self, rhs: $V) {
115                *self = Self::new_truncate(self.0 & rhs);
116            }
117        }
118
119        impl core::ops::BitXor<$V> for $T {
120            type Output = $V;
121            #[inline]
122            fn bitxor(self, rhs: $V) -> Self::Output {
123                self.0 ^ rhs
124            }
125        }
126
127        impl core::ops::BitXorAssign<$V> for $T {
128            #[inline]
129            fn bitxor_assign(&mut self, rhs: $V) {
130                *self = Self::new_truncate(self.0 ^ rhs);
131            }
132        }
133
134        impl core::ops::Shl<usize> for $T {
135            type Output = $T;
136            #[inline]
137            fn shl(self, rhs: usize) -> Self::Output {
138                Self::new_truncate(self.0 << rhs)
139            }
140        }
141
142        impl core::ops::Shr<usize> for $T {
143            type Output = $T;
144            #[inline]
145            fn shr(self, rhs: usize) -> Self::Output {
146                Self::new_truncate(self.0 >> rhs)
147            }
148        }
149
150        impl core::ops::ShlAssign<usize> for $T {
151            #[inline]
152            fn shl_assign(&mut self, rhs: usize) {
153                *self = Self::new_truncate(self.0 << rhs);
154            }
155        }
156
157        impl core::ops::ShrAssign<usize> for $T {
158            #[inline]
159            fn shr_assign(&mut self, rhs: usize) {
160                *self = Self::new_truncate(self.0 >> rhs);
161            }
162        }
163
164        impl From<$V> for $T {
165            #[inline]
166            fn from(addr: $V) -> $T {
167                Self::new_truncate(addr)
168            }
169        }
170
171        impl core::fmt::Debug for $T {
172            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173                f.debug_tuple(stringify!($T))
174                    .field(&format_args!("{:#x}", self.0))
175                    .finish()
176            }
177        }
178
179        impl core::fmt::Binary for $T {
180            #[inline]
181            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
182                fmt::Binary::fmt(&self.0, f)
183            }
184        }
185
186        impl core::fmt::LowerHex for $T {
187            #[inline]
188            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189                fmt::LowerHex::fmt(&self.0, f)
190            }
191        }
192
193        impl core::fmt::Octal for $T {
194            #[inline]
195            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196                fmt::Octal::fmt(&self.0, f)
197            }
198        }
199
200        impl core::fmt::UpperHex for $T {
201            #[inline]
202            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203                fmt::UpperHex::fmt(&self.0, f)
204            }
205        }
206
207        impl core::fmt::Pointer for $T {
208            #[inline]
209            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210                fmt::Pointer::fmt(&(self.0 as *const ()), f)
211            }
212        }
213    };
214}
215
216pub(crate) use impl_address;