sdmmc_core/macros/
bitfield.rs1#[macro_export]
12macro_rules! lib_bitfield {
13 (
14 $(#[$doc:meta])+
15 $ty_vis:vis $ty:ident ($base:ty): $ret:ty {
16 $(
17 $(#[$field_doc:meta])*
18 $field_vis:vis $field:ident: $msb:expr $(, $lsb:expr)?;
19 )+
20 }
21 ) => {
22 paste::paste! {
23 $(#[$doc])+
24 #[repr(C)]
25 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
26 $ty_vis struct $ty($base);
27
28 impl $ty {
29 #[doc = "Gets the bit value for [" $ty "]."]
30 pub const fn bits(&self) -> $base {
31 self.0
32 }
33
34 $(
35 $crate::lib_bitfield_impl! {
36 $ty ( $base ): $ret,
37 $(#[$field_doc])*
38 $field_vis $field: $msb $(, $lsb)?;
39 }
40 )+
41 }
42 }
43 };
44
45 (
46 $(#[$doc:meta])+
47 $ty_vis:vis $ty:ident (MSB0 [$base:ty; $N:expr]): $ret:ty {
48 $(
49 $(#[$field_doc:meta])*
50 $field_vis:vis $field:ident: $msb:expr $(, $lsb:expr)?;
51 )+
52 }
53 ) => {
54 paste::paste! {
55 $(#[$doc])+
56 #[repr(C)]
57 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
58 $ty_vis struct $ty(pub [$base; $N]);
59
60 impl $ty {
61 #[doc = "Gets the byte value for [" $ty "]."]
62 pub const fn bytes(&self) -> [$base; $N] {
63 self.0
64 }
65
66 $(
67 $crate::lib_bitfield_impl! {
68 $ty (MSB0 [$base; $N]): $ret,
69 $(#[$field_doc])*
70 $field_vis $field: $msb $(, $lsb)?;
71 }
72 )+
73 }
74 }
75 };
76
77 (
78 $(#[$doc:meta])+
79 $bitfield_ty:ident: $base:ty,
80 mask: $mask:expr,
81 default: $default:expr,
82 {
83 $(
84 $(#[$field_doc:meta])*
85 $field:ident: $msb:literal$(, $lsb:literal)?;
86 )+
87 }$(,)?
88 ) => {
89 ::paste::paste! {
90 $crate::lib_bitfield! {
91 $(#[$doc])+
92 pub $bitfield_ty($base): $base {
93 $(pub $field: $msb $(, $lsb)?;)+
94 }
95 }
96
97 impl $bitfield_ty {
98 #[doc = "Represents the bitmask for the [" $bitfield_ty "]."]
99 pub const MASK: $base = $mask;
100 #[doc = "Represents the default value for the [" $bitfield_ty "]."]
101 pub const DEFAULT: $base = $default;
102
103 #[doc = "Creates a new [" $bitfield_ty "]."]
104 pub const fn new() -> Self {
105 Self(Self::DEFAULT)
106 }
107
108 #[doc = "Converts an inner representation into a [" $bitfield_ty "]."]
109 pub const fn from_inner(val: $base) -> Self {
110 Self(val & Self::MASK)
111 }
112
113 #[doc = "Attempts to convert an inner representation into a [" $bitfield_ty "]."]
114 pub const fn try_from_inner(val: $base) -> $crate::result::Result<Self> {
115 Ok(Self::from_inner(val))
116 }
117
118 #[doc = "Converts a [" $bitfield_ty "] into an inner representation."]
119 pub const fn into_inner(self) -> $base {
120 self.0
121 }
122 }
123
124 impl Default for $bitfield_ty {
125 fn default() -> Self {
126 Self::new()
127 }
128 }
129
130 impl From<$base> for $bitfield_ty {
131 fn from(val: $base) -> Self {
132 Self::from_inner(val)
133 }
134 }
135
136 impl From<$bitfield_ty> for $base {
137 fn from(val: $bitfield_ty) -> Self {
138 val.into_inner()
139 }
140 }
141 }
142 };
143
144 (
145 $(#[$doc:meta])+
146 $bitfield_ty:ident: $base:ty,
147 mask: $mask:expr,
148 default: $default:expr,
149 {
150 $(
151 $(#[$field_doc:meta])*
152 $field:ident: $field_ty:ident, $msb:expr$(, $lsb:expr)?;
153 )+
154 }$(,)?
155 ) => {
156 ::paste::paste! {
157 $crate::lib_bitfield! {
158 $(#[$doc])+
159 pub $bitfield_ty($base): $base {
160 $([<raw_ $field>]: $msb $(, $lsb)?;)+
161 }
162 }
163
164 impl $bitfield_ty {
165 #[doc = "Represents the bitmask for the [" $bitfield_ty "]."]
166 pub const MASK: $base = $mask;
167 #[doc = "Represents the default value for the [" $bitfield_ty "]."]
168 pub const DEFAULT: $base = $default;
169
170 #[doc = "Creates a new [" $bitfield_ty "]."]
171 pub const fn new() -> Self {
172 Self(Self::DEFAULT)
173 }
174
175 $(
176 #[doc = "Gets the " $field " of the [" $bitfield_ty "]."]
177 $(
178 #[doc = ""]
179 #[$field_doc]
180 )*
181 pub const fn $field(&self) -> $crate::result::Result<$field_ty> {
182 $field_ty::try_from_inner(self.[<raw_ $field>]())
183 }
184
185 #[doc = "Sets the " $field " of the [" $bitfield_ty "]."]
186 $(
187 #[doc = ""]
188 #[$field_doc]
189 )*
190 pub fn [<set_ $field>](&mut self, val: $field_ty) {
191 self.[<set_raw_ $field>](val.into_inner())
192 }
193 )+
194
195 #[doc = "Attempts to convert an inner representation into a [" $bitfield_ty "]."]
196 pub const fn try_from_inner(val: $base) -> $crate::result::Result<Self> {
197 match Self(val & Self::MASK) {
198 $(
199 v if v.$field().is_err() => Err($crate::result::Error::invalid_field_variant(stringify!($bitfield_ty::$field), v.[<raw_ $field>]() as usize)),
200 )+
201 v => Ok(v),
202 }
203 }
204
205 #[doc = "Converts a [" $bitfield_ty "] into an inner representation."]
206 pub const fn into_inner(self) -> $base {
207 self.0
208 }
209 }
210
211 impl Default for $bitfield_ty {
212 fn default() -> Self {
213 Self::new()
214 }
215 }
216
217 impl TryFrom<$base> for $bitfield_ty {
218 type Error = $crate::result::Error;
219
220 fn try_from(val: $base) -> $crate::result::Result<Self> {
221 Self::try_from_inner(val)
222 }
223 }
224
225 impl From<$bitfield_ty> for $base {
226 fn from(val: $bitfield_ty) -> Self {
227 val.into_inner()
228 }
229 }
230 }
231 };
232}
233
234#[macro_export]
236macro_rules! lib_bitfield_impl {
237 (
238 $ty:ident ( $base:ty ): $ret:ty,
239 $(#[$field_doc:meta])*
240 $field_vis:vis $field:ident: $msb:expr, $lsb:expr;
241 ) => {
242 paste::paste! {
243 #[doc = "Getter for " $field " field of [" $ty "]."]
244 $(
245 #[doc = ""]
246 #[$field_doc]
247 )*
248 $field_vis const fn $field(&self) -> $ret {
249 $crate::check_bitfield!($msb, $lsb, $base, $ret);
250
251 let mask = ((1u128 << ($msb - $lsb + 1)) - 1) as $base;
252 ((self.0 & (mask << $lsb)) >> $lsb) as $ret
253 }
254
255 #[doc = "Setter for " $field " field of [" $ty "]."]
256 $(
257 #[doc = ""]
258 #[$field_doc]
259 )*
260 $field_vis fn [<set_ $field>](&mut self, val: $base) {
261 $crate::check_bitfield!($msb, $lsb, $base, $ret);
262
263 let mask = ((1u128 << ($msb - $lsb + 1)) - 1) as $base;
264 self.0 = (self.0 & !(mask << $lsb)) | ((val & mask) << $lsb);
265 }
266 }
267 };
268
269 (
270 $ty:ident ( $base:ty ): $ret:ty,
271 $(#[$field_doc:meta])*
272 $field_vis:vis $field:ident: $bit:expr;
273 ) => {
274 paste::paste! {
275 #[doc = "Getter for " $field " field of [" $ty "]."]
276 $(
277 #[doc = ""]
278 #[$field_doc]
279 )*
280 $field_vis const fn $field(&self) -> bool {
281 $crate::check_bitfield!($bit, $base);
282
283 let mask = (1u128 << $bit) as $base;
284 ((self.0 & mask) >> $bit) != 0
285 }
286
287 #[doc = "Setter for " $field " field of [" $ty "]."]
288 $(
289 #[doc = ""]
290 #[$field_doc]
291 )*
292 $field_vis fn [<set_ $field>](&mut self, val: bool) {
293 $crate::check_bitfield!($bit, $base);
294
295 let mask = (1u128 << $bit) as $base;
296 self.0 = (self.0 & !mask) | ((val as $base) << $bit);
297 }
298 }
299 };
300
301 (
302 $ty:ident (MSB0 [$base:ty; $N:expr] ): $ret:ty,
303 $(#[$field_doc:meta])*
304 $field_vis:vis $field:ident: $msb:expr, $lsb:expr;
305 ) => {
306 paste::paste! {
307 #[doc = "Getter for `" $field "` field of [" $ty "]."]
308 $(
309 #[doc = ""]
310 #[$field_doc]
311 )*
312 $field_vis const fn $field(&self) -> $ret {
313 $crate::check_bitfield!($msb, $lsb, $base, $N, $ret);
314
315 let msb_idx = $N - ($msb / _BASE_BITS) - 1;
316 let mut msb_bit = $msb % _BASE_BITS;
317
318 let lsb_idx = $N - ($lsb / _BASE_BITS) - 1;
319
320 let mut idx = msb_idx;
321 let mut bits = ($msb - $lsb + 1) as usize;
322
323 let mut ret = 0;
324
325 while idx <= lsb_idx {
326 let lsb_bit = if idx == lsb_idx {
327 $lsb % _BASE_BITS
328 } else {
329 0
330 };
331
332 let (width, bit) = (msb_bit - lsb_bit + 1, lsb_bit);
333
334 let mask = ((1u128 << width) - 1) as $base;
335
336 bits = bits.saturating_sub(width);
337
338 ret |= (((self.0[idx] & (mask << bit)) as $ret) >> bit) << bits;
339
340 idx += 1;
341 msb_bit = _BASE_BITS - 1;
342 }
343
344 ret
345 }
346
347 #[doc = "Setter for `" $field "` field of [" $ty "]."]
348 $(
349 #[doc = ""]
350 #[$field_doc]
351 )*
352 $field_vis fn [<set_ $field>](&mut self, val: $ret) {
353 $crate::check_bitfield!($msb, $lsb, $base, $N, $ret);
354
355 let msb_idx = $N - ($msb / _BASE_BITS) - 1;
356 let mut msb_bit = $msb % _BASE_BITS;
357
358 let lsb_idx = $N - ($lsb / _BASE_BITS) - 1;
359
360 let mut idx = msb_idx;
361 let mut bits = ($msb - $lsb + 1) as usize;
362
363 while idx <= lsb_idx {
364 let lsb_bit = if idx == lsb_idx {
365 $lsb % _BASE_BITS
366 } else {
367 0
368 };
369
370 let (width, bit) = (msb_bit - lsb_bit + 1, lsb_bit);
371
372 let mask = ((1u128 << width) - 1) as $base;
373
374 bits = bits.saturating_sub(width);
375
376 let val_base = ((val >> bits) as $base) << bit;
377 self.0[idx] = (self.0[idx] & !(mask << bit)) | val_base;
378
379 idx += 1;
380 msb_bit = _BASE_BITS - 1;
381 }
382 }
383 }
384 };
385
386 (
387 $ty:ident (MSB0 [$base:ty; $N:expr] ): $ret:ty,
388 $(#[$field_doc:meta])*
389 $field_vis:vis $field:ident: $bit:expr;
390 ) => {
391 paste::paste! {
392 #[doc = "Getter for `" $field "` field of [" $ty "]."]
393 $(
394 #[doc = ""]
395 #[$field_doc]
396 )*
397 $field_vis const fn $field(&self) -> bool {
398 $crate::check_bitfield!($bit, $base, $N);
399
400 let idx = $N - ($bit / _BASE_BITS) - 1;
401 let bit = $bit % _BASE_BITS;
402
403 let mask = (1u128 << bit) as $base;
404
405 (self.0[idx] & mask) != 0
406 }
407
408 #[doc = "Setter for `" $field "` field of [" $ty "]."]
409 $(
410 #[doc = ""]
411 #[$field_doc]
412 )*
413 $field_vis fn [<set_ $field>](&mut self, val: bool) {
414 $crate::check_bitfield!($bit, $base, $N);
415
416 let idx = $N - ($bit / _BASE_BITS) - 1;
417 let bit = $bit % _BASE_BITS;
418
419 let mask = (1u128 << bit) as $base;
420
421 self.0[idx] = (self.0[idx] & !mask) | ((val as $base) << bit);
422 }
423 }
424 };
425}
426
427#[macro_export]
429macro_rules! check_bitfield {
430 (
431 $msb:expr, $lsb:expr, $base:ty, $ret:ty$(,)?
432 ) => {
433 const _BASE_BITS: usize = <$base>::BITS as usize;
434 const _RET_BITS: usize = <$ret>::BITS as usize;
435 const _WIDTH: usize = $msb - $lsb + 1;
436
437 const _: () = assert!($lsb <= $msb);
438 const _: () = assert!(($msb as usize) < _BASE_BITS);
439 const _: () = assert!(($msb - $lsb) < _RET_BITS);
440 };
441
442 (
443 $bit:expr, $base:ty$(,)?
444 ) => {
445 const _BASE_BITS: usize = <$base>::BITS as usize;
446 const _RET_BITS: usize = 1;
447 const _WIDTH: usize = 1;
448
449 const _: () = assert!(($bit as usize) < _BASE_BITS);
450 };
451
452 (
453 $msb:expr, $lsb:expr, $base:ty, $N:expr, $ret:ty$(,)?
454 ) => {
455 const _BASE_BITS: usize = <$base>::BITS as usize;
456 const _TOTAL_BITS: usize = _BASE_BITS * $N;
457 const _RET_BITS: usize = <$ret>::BITS as usize;
458 const _WIDTH: usize = $msb - $lsb + 1;
459
460 const _: () = assert!($lsb <= $msb);
461 const _: () = assert!(($msb as usize) < _TOTAL_BITS);
462 const _: () = assert!(($msb - $lsb) < _RET_BITS);
463 };
464
465 (
466 $bit:expr, $base:ty, $N:expr$(,)?
467 ) => {
468 const _BASE_BITS: usize = <$base>::BITS as usize;
469 const _TOTAL_BITS: usize = _BASE_BITS * $N;
470
471 const _: () = assert!(($bit as usize) < _TOTAL_BITS);
472 };
473}