Skip to main content

nexus_bits/
flag.rs

1//! Single-bit flag extraction and packing.
2
3/// A single-bit flag within a packed integer.
4///
5/// Simpler than `BitField` for boolean flags - no overflow checking needed.
6///
7/// # Example
8///
9/// ```
10/// use nexus_bits::Flag;
11///
12/// const IS_BUY: Flag<u64> = Flag::<u64>::new(0);
13/// const IS_IOC: Flag<u64> = Flag::<u64>::new(1);
14///
15/// let mut flags: u64 = 0;
16/// flags = IS_BUY.set(flags);
17/// flags = IS_IOC.set(flags);
18///
19/// assert!(IS_BUY.is_set(flags));
20/// assert!(IS_IOC.is_set(flags));
21///
22/// flags = IS_IOC.clear(flags);
23/// assert!(!IS_IOC.is_set(flags));
24/// ```
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26pub struct Flag<T> {
27    bit: u32,
28    mask: T,
29}
30
31macro_rules! impl_flag {
32    ($($ty:ty),*) => {
33        $(
34            impl Flag<$ty> {
35                /// Creates a flag at bit position `bit`.
36                ///
37                /// # Panics
38                ///
39                /// Panics if `bit` >= type's bit width.
40                #[inline]
41                pub const fn new(bit: u32) -> Self {
42                    assert!(bit < <$ty>::BITS, "bit position exceeds integer bounds");
43                    let mask = 1 << bit;
44                    Self { bit, mask }
45                }
46
47                /// Bit position.
48                #[inline]
49                pub const fn bit(self) -> u32 {
50                    self.bit
51                }
52
53                /// Mask with 1 at flag position.
54                #[inline]
55                pub const fn mask(self) -> $ty {
56                    self.mask
57                }
58
59                /// Returns true if flag is set.
60                #[inline]
61                pub const fn is_set(self, val: $ty) -> bool {
62                    (val & self.mask) != 0
63                }
64
65                /// Set flag to 1.
66                #[inline]
67                pub const fn set(self, val: $ty) -> $ty {
68                    val | self.mask
69                }
70
71                /// Set flag to 0.
72                #[inline]
73                pub const fn clear(self, val: $ty) -> $ty {
74                    val & !self.mask
75                }
76
77                /// Flip flag.
78                #[inline]
79                pub const fn toggle(self, val: $ty) -> $ty {
80                    val ^ self.mask
81                }
82
83                /// Set flag to given boolean value.
84                #[inline]
85                pub const fn set_to(self, val: $ty, enabled: bool) -> $ty {
86                    if enabled {
87                        self.set(val)
88                    } else {
89                        self.clear(val)
90                    }
91                }
92            }
93        )*
94    };
95}
96
97impl_flag!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);