nx/macros/util.rs
1#![macro_use]
2
3/// Aligns a value up based on the provided alignment which should be a power of two.
4///
5/// # Arguments
6///
7/// * `val`: Expression that should resolve to an unsigned primitive integer type
8/// * `alignement`: Alignement value, that should resolve to the same type as `$val`
9///
10/// # Examples
11///
12/// ```
13/// let new_buffer_with_aligned_size = nx::mem::alloc::Buffer::new(size_of::<u128>(), max_object_count);
14/// ```
15#[macro_export]
16macro_rules! align_up {
17 ($val:expr, $alignment:expr ) => {{
18 debug_assert!(
19 ($alignment).is_power_of_two(),
20 "Alignment value must be a power of two"
21 );
22 let align_mask = ($alignment) - 1;
23 (($val) + align_mask) & !align_mask
24 }};
25}
26
27/// Checks if the provided value is aligned to the provided alignment
28///
29/// # Arguments
30///
31/// * `val`: Expression that should resolve to an unsigned primitive integer type
32/// * `alignement`: Alignement value, that should resolve to the same type as `$val`
33///
34/// # Examples
35///
36/// ```
37/// debug_assert!(is_aligned!(buffer.ptr, align_of::<T>()));
38/// ```
39#[macro_export]
40macro_rules! is_aligned {
41 ($val:expr, $alignment:expr ) => {{
42 debug_assert!(
43 ($alignment).is_power_of_two(),
44 "Alignment value must be a power of two"
45 );
46 let align_mask = ($alignment) - 1;
47 ($val) & align_mask == 0
48 }};
49}
50
51/// Gets a value corresponding to the given bit
52///
53/// # Arguments
54///
55/// * `val`: Bit index
56///
57/// # Examples
58///
59/// ```
60/// assert_eq!(bit!(0), 0b1);
61/// assert_eq!(bit!(1), 0b10);
62/// assert_eq!(bit!(5), 0b100000);
63/// ```
64#[macro_export]
65macro_rules! bit {
66 ($val:expr) => {
67 (1 << $val)
68 };
69}
70
71/// Defines a type meant to serve as a bitflag enum-like type
72///
73/// # Examples
74///
75/// ```
76/// bit_enum! {
77/// Test (u32) {
78/// A = bit!(1),
79/// B = bit!(2)
80/// }
81/// }
82/// ```
83#[macro_export]
84macro_rules! define_bit_enum {
85 (
86 $(#[$a_meta:meta])*
87 $name:ident ($base:ty) {
88 $(
89 $(#[$b_meta:meta])*
90 $entry_name:ident = $entry_value:expr
91 ),*
92 }
93 ) => {
94 $(#[$a_meta])*
95 #[derive($crate::ipc::sf::Request, $crate::ipc::sf::Response, Copy, Clone, PartialEq, Eq, Debug, Default)]
96 #[repr(C)]
97 pub struct $name($base);
98
99 #[allow(non_snake_case)]
100 impl $name {
101 /// Creates a `$name` from the underlying base type `$base`
102 pub const fn from(val: $base) -> Self {
103 Self(val)
104 }
105
106 /// Checks if the provided `$name` has all of the set bits in `other` are set in `self`
107 pub const fn contains(self, other: Self) -> bool {
108 (self.0 & other.0) == other.0
109 }
110
111 /// Returns the value as the underlying type
112 pub const fn get(self) -> $base {
113 self.0
114 }
115
116 $(
117 /// Returns a `$name` where only the bit for `$entry_name` is set
118 $(#[$b_meta])*
119 pub const fn $entry_name() -> Self {
120 Self($entry_value)
121 }
122 )*
123 }
124
125 impl core::ops::BitOr for $name {
126 type Output = Self;
127
128 #[inline]
129 fn bitor(self, other: Self) -> Self {
130 Self(self.0 | other.0)
131 }
132 }
133
134 impl core::ops::BitAnd for $name {
135 type Output = Self;
136
137 #[inline]
138 fn bitand(self, other: Self) -> Self {
139 Self(self.0 & other.0)
140 }
141 }
142
143 impl core::ops::BitOrAssign for $name {
144 #[inline]
145 fn bitor_assign(&mut self, other: Self) {
146 self.0 |= other.0
147 }
148 }
149
150 impl core::ops::BitAndAssign for $name {
151 #[inline]
152 fn bitand_assign(&mut self, other: Self) {
153 self.0 &= other.0
154 }
155 }
156
157 impl core::ops::Not for $name {
158 type Output = Self;
159
160 #[inline]
161 fn not(self) -> Self {
162 Self(!self.0)
163 }
164 }
165 };
166}
167
168/// Constructs a `bit_enum` type value from various flags
169///
170/// # Examples
171///
172/// ```
173/// bit_enum! {
174/// Test (u32) {
175/// A = bit!(1),
176/// B = bit!(2)
177/// }
178/// }
179///
180/// // The equivalent to what would be "A | B"
181/// let test_ab = bit_group! { Test [A, B] };
182/// ```
183#[macro_export]
184macro_rules! bit_group {
185 ($base:ty [ $( $val:ident ),* ]) => {
186 <$base>::from( $( <$base>::$val().get() )|* )
187 };
188}
189
190/// Writes bits into a given value
191///
192/// # Arguments
193///
194/// * `start`: The start bit index (inclusive)
195/// * `end`: The end bit index (inclusive)
196/// * `value`: The value to write into
197/// * `data`: The value to set
198///
199/// # Examples
200///
201/// ```
202/// let value = 0u8;
203/// write_bits!(0, 3, value, 0b0110);
204/// write_bits!(4, 7, value, 0b1001);
205/// assert_eq!(value, 0b10010110);
206/// ```
207#[macro_export]
208macro_rules! write_bits {
209 ($start:expr, $end:expr, $value:expr, $data:expr) => {
210 $value = ($value & (!(((1 << ($end - $start + 1)) - 1) << $start))) | ($data << $start);
211 };
212}
213
214/// Reads bits from a given value
215///
216/// # Arguments
217///
218/// * `start`: The start bit index (inclusive)
219/// * `end`: The end bit index (inclusive)
220/// * `value`: The value
221///
222/// # Examples
223///
224/// ```
225/// let value = 0b11110000u8;
226/// assert_eq!(read_bits!(value, 0, 3), 0b0000);
227/// assert_eq!(read_bits!(value, 4, 7), 0b1111);
228/// ```
229#[macro_export]
230macro_rules! read_bits {
231 ($start:expr, $end:expr, $value:expr) => {
232 ($value & (((1 << ($end - $start + 1)) - 1) << $start)) >> $start
233 };
234}
235
236/// Creates a NUL-terminated string literal
237///
238/// # Arguments
239///
240/// * `lit`: The string literal
241///
242/// # Examples
243///
244/// ```
245/// assert_eq!("demo\0", nul!("demo"));
246/// ```
247#[macro_export]
248macro_rules! nul {
249 ($lit:literal) => {
250 concat!($lit, "\0")
251 };
252}
253
254/// Gets the current function name
255///
256/// # Examples
257///
258/// ```
259/// fn test() {
260/// assert_eq!(cur_fn_name!(), "test");
261/// }
262/// ```
263#[macro_export]
264macro_rules! cur_fn_name {
265 () => {{
266 fn dummy_fn() {}
267 const DUMMY_FN_EXTRA_SIZE: usize = "::dummy_fn".len();
268
269 fn type_name_of<T>(_: T) -> &'static str {
270 core::any::type_name::<T>()
271 }
272
273 let name = type_name_of(dummy_fn);
274 &name[..name.len() - DUMMY_FN_EXTRA_SIZE]
275 }};
276}