Skip to main content

vfat_rs/
macros.rs

1/// A const time assertion.
2#[macro_export]
3macro_rules! const_assert {
4    ($cond:expr) => {
5        // Causes overflow if condition is false
6        let _ = [(); 0 - (!($cond) as usize)];
7    };
8    ($($xs:expr),+) => {
9        $crate::const_assert!($($xs)&&+);
10    };
11    ($($xs:expr);+ $(;)*) => {
12        $crate::const_assert!($($xs),+);
13    };
14}
15
16/// A compile time equality assertion
17#[macro_export]
18macro_rules! const_assert_eq {
19    ($x:expr, $($xs:expr),+) => {
20        const _: () = { $crate::const_assert!($($x == $xs),+);};
21    }
22}
23
24/// A compile time size assertion. Can be used to check the actual struct size.
25/// usage:
26/// const_assert_size!(<struct or enum name>, <amount-of-expected-bytes>);
27/// const_assert_size!(FatEntry, 8);
28#[macro_export]
29macro_rules! const_assert_size {
30    ($struct:ident, $size:expr) => {
31        $crate::const_assert_eq!(core::mem::size_of::<$struct>(), ($size));
32    };
33}
34
35/// Generates a bitmask.
36#[macro_export]
37macro_rules! define_mask {
38    ($end:expr, $beg:expr) => {
39        ((1 << $end) - (1 << $beg) + (1 << $end))
40    };
41}
42
43/// Used in Defreg and Defbit for creating fields.
44#[macro_export]
45macro_rules! define_bitfield {
46    ($field:ident, $size:ident, [$($end:tt - $beg:tt)|*]) => {
47        #[allow(non_upper_case_globals)]
48        pub const $field: $size = $( $crate::define_mask!($end, $beg) )|*;
49    };
50}
51
52/// Given a type bit, ease the bit fields manipulation.
53#[macro_export]
54macro_rules! defbit {
55    ($regname:ident) => { defbit!($regname, u64, []); };
56    ($regname:ident, $size:ident, [$($field:ident $bits:tt,)*]) => {
57        #[allow(non_snake_case)]
58        #[derive(Debug, Copy, Clone, Eq, PartialEq)]
59        #[repr(C)]
60        #[allow(missing_docs)]
61        pub struct $regname ($size);
62        #[allow(dead_code)]
63        #[allow(missing_docs)]
64        impl $regname {
65            #[inline(always)]
66            pub fn new(data: $size) -> $regname {
67                $regname(data)
68            }
69
70            #[inline(always)]
71            pub fn get(&self) -> $size {
72                self.0
73            }
74
75            #[inline(always)]
76            pub fn get_masked(&self, mask: $size) -> $size {
77                self.0 & mask
78            }
79
80            #[inline(always)]
81            pub fn get_value(&self, mask: $size) -> $size {
82                (self.0 & mask) >> (mask.trailing_zeros())
83            }
84
85            #[inline(always)]
86            pub fn set(&mut self, val: $size) -> &mut Self {
87                self.0 = val;
88                self
89            }
90
91            #[inline(always)]
92            pub fn set_masked(&mut self, val: $size, mask: $size) -> &mut Self {
93                self.0 = (self.0 & !mask) | (val & mask);
94                self
95            }
96
97            #[inline(always)]
98            pub fn set_value<T: Into<$size>>(&mut self, val: T, mask: $size) -> &mut Self {
99                let val:$size = val.into();
100                self.0 = (self.0 & !mask)
101                    | ((val << (mask.trailing_zeros())) & mask);
102                self
103            }
104
105            #[inline(always)]
106            pub fn set_bit(&mut self, mask: $size) -> &mut Self {
107                self.0 |= mask;
108                self
109            }
110
111            #[inline(always)]
112            pub fn clear_bit(&mut self, mask: $size) -> &mut Self {
113                self.0 &= !mask;
114                self
115            }
116
117            $( $crate::define_bitfield!($field, $size, $bits); )*
118        }
119    }
120}