vulkanalia_sys/
bitfields.rs

1// SPDX-License-Identifier: Apache-2.0
2
3/// Defines a sequence of bitfields packed into a `u32`.
4macro_rules! bitfields32 {
5    (
6        $(#[$outer:meta])*
7        struct $name:ident {
8            $(($get:ident, $with:ident)[$start:literal .. $end:literal]), *,
9        }
10    ) => (
11        $(#[$outer])*
12        #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
13        #[repr(transparent)]
14        pub struct $name(pub u32);
15
16        impl $name {
17            $(
18                #[inline]
19                pub const fn $get(self) -> u32 {
20                    let mask = (1 << ($end - $start)) - 1;
21                    (self.0 & (mask << $start)) >> $start
22                }
23
24                #[inline]
25                pub const fn $with(self, value: u32) -> Self {
26                    let mask = (1 << ($end - $start)) - 1;
27                    Self((self.0 & !(mask << $start)) | ((value & mask) << $start))
28                }
29            )*
30        }
31
32        impl ::core::fmt::Debug for $name {
33            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
34                f.debug_struct(stringify!($name))
35                    $(.field(stringify!($get), &self.$get()))*
36                    .finish()
37            }
38        }
39    );
40}
41
42#[cfg(test)]
43mod test {
44    use core::u32;
45
46    bitfields32! {
47        /// A test sequence of bitfields.
48        struct Bitfields {
49            (foo, with_foo)[0 .. 4],
50            (bar, with_bar)[15 .. 16],
51            (baz, with_baz)[16 .. 17],
52            (qux, with_qux)[28 .. 32],
53        }
54    }
55
56    #[test]
57    fn test_bitfields() {
58        let bf = Bitfields(0b00111100_01010101_01010101_00111100);
59
60        assert_eq!(bf.foo(), 0b1100);
61        assert_eq!(bf.bar(), 0);
62        assert_eq!(bf.baz(), 1);
63        assert_eq!(bf.qux(), 0b0011);
64
65        assert_eq!(bf.with_foo(0b0000).0, 0b00111100_01010101_01010101_00110000);
66        assert_eq!(bf.with_foo(0b1111).0, 0b00111100_01010101_01010101_00111111);
67        assert_eq!(
68            bf.with_foo(u32::MAX).0,
69            0b00111100_01010101_01010101_00111111
70        );
71
72        assert_eq!(bf.with_bar(0).0, 0b00111100_01010101_01010101_00111100);
73        assert_eq!(bf.with_bar(1).0, 0b00111100_01010101_11010101_00111100);
74        assert_eq!(
75            bf.with_bar(u32::MAX).0,
76            0b00111100_01010101_11010101_00111100
77        );
78
79        assert_eq!(bf.with_baz(0).0, 0b00111100_01010100_01010101_00111100);
80        assert_eq!(bf.with_baz(1).0, 0b00111100_01010101_01010101_00111100);
81        assert_eq!(
82            bf.with_baz(u32::MAX).0,
83            0b00111100_01010101_01010101_00111100
84        );
85
86        assert_eq!(bf.with_qux(0b0000).0, 0b00001100_01010101_01010101_00111100);
87        assert_eq!(bf.with_qux(0b1111).0, 0b11111100_01010101_01010101_00111100);
88        assert_eq!(
89            bf.with_qux(u32::MAX).0,
90            0b11111100_01010101_01010101_00111100
91        );
92
93        assert_eq!(
94            format!("{bf:?}"),
95            "Bitfields { foo: 12, bar: 0, baz: 1, qux: 3 }"
96        );
97    }
98}