sti/
bit.rs

1#[inline(always)]
2pub const fn splat_4(b: u8) -> u32 {
3    u32::from_ne_bytes([b; 4])
4}
5
6#[inline(always)]
7pub const fn splat_8(b: u8) -> u64 {
8    u64::from_ne_bytes([b; 8])
9}
10
11
12macro_rules! bitmask_impl {
13    ($name:ident, $ty:ident, $splat:ident) => {
14        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
15        pub struct $name($ty);
16
17        impl $name {
18            pub const NONE: Self = Self(0);
19            pub const ALL: Self = Self($splat(0x80));
20
21            #[inline(always)]
22            pub const fn from_bits(bits: $ty) -> Self { Self(bits) }
23
24
25            #[inline(always)]
26            pub const fn none(self) -> bool { self.0 == 0 }
27
28            #[inline(always)]
29            pub const fn any(self) -> bool { self.0 != 0 }
30
31            #[inline(always)]
32            pub const fn all(self) -> bool { self.0 == $splat(0x80) }
33
34
35            #[inline(always)]
36            pub fn not(self) -> Self {
37                Self(self.0 ^ $splat(0x80))
38            }
39
40
41            #[inline]
42            pub fn find_zero_bytes(value: $ty) -> Self {
43                // https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
44                let zero_or_high = value.wrapping_sub($splat(1));
45                let not_high = !value & $splat(0x80);
46                let mask = zero_or_high & not_high;
47                Self(mask)
48            }
49
50            #[inline(always)]
51            pub fn find_equal_bytes(value: $ty, byte: u8) -> Self {
52                Self::find_zero_bytes(value ^ $splat(byte))
53            }
54
55            #[inline(always)]
56            pub fn find_high_bit_bytes(value: $ty) -> Self {
57                Self(value & $splat(0x80))
58            }
59        }
60
61        impl Iterator for $name {
62            type Item = usize;
63
64            #[inline(always)]
65            fn next(&mut self) -> Option<Self::Item> {
66                if self.0 != 0 {
67                    let i = self.0.trailing_zeros() / 8;
68                    self.0 &= self.0 - 1;
69                    return Some(i as usize);
70                }
71                return None;
72            }
73        }
74
75        impl core::ops::BitAnd for $name {
76            type Output = Self;
77
78            #[inline(always)]
79            fn bitand(self, rhs: Self) -> Self {
80                Self(self.0 & rhs.0)
81            }
82        }
83
84        impl core::ops::BitOr for $name {
85            type Output = Self;
86
87            #[inline(always)]
88            fn bitor(self, rhs: Self) -> Self {
89                Self(self.0 | rhs.0)
90            }
91        }
92
93        impl core::ops::Not for $name {
94            type Output = Self;
95
96            #[inline(always)]
97            fn not(self) -> Self {
98                Self::not(self)
99            }
100        }
101    }
102}
103
104bitmask_impl!(Bitmask4, u32, splat_4);
105bitmask_impl!(Bitmask8, u64, splat_8);
106