1pub use flags_derive::derive_flags;
2use std::{
3 fmt::Debug,
4 marker::PhantomData,
5 ops::{BitAnd, BitOr, BitXor, Deref, Not, Shl, Shr},
6};
7
8pub trait FlagPrimitive:
11 Sized
12 + Not<Output = Self>
13 + BitAnd<Self, Output = Self>
14 + BitOr<Self, Output = Self>
15 + BitAnd<Self, Output = Self>
16 + BitXor<Self, Output = Self>
17 + Shl<Self, Output = Self>
18 + Shr<Self, Output = Self>
19 + Clone
20 + Copy
21 + Debug
22 + Eq
23{
24 const ZERO: Self;
26 const ONE: Self;
28}
29impl FlagPrimitive for u8 {
30 const ZERO: Self = 0;
31 const ONE: Self = 1;
32}
33impl FlagPrimitive for u16 {
34 const ZERO: Self = 0;
35 const ONE: Self = 1;
36}
37impl FlagPrimitive for u32 {
38 const ZERO: Self = 0;
39 const ONE: Self = 1;
40}
41impl FlagPrimitive for u64 {
42 const ZERO: Self = 0;
43 const ONE: Self = 1;
44}
45impl FlagPrimitive for u128 {
46 const ZERO: Self = 0;
47 const ONE: Self = 1;
48}
49impl FlagPrimitive for usize {
50 const ZERO: Self = 0;
51 const ONE: Self = 1;
52}
53pub trait FlagValue: Sized + Debug + Clone + Copy + AsRef<Self::Collection> {
55 type Bits: FlagPrimitive;
57 type Collection: FlagValueCollection<Self>;
59 const MASK: Self::Bits;
61 fn to_primitive(&self) -> Self::Bits;
62 fn from_primitive(value: &Self::Bits) -> Option<Self>;
63 fn all() -> Self::Collection {
64 Self::Collection::from_primitive(&Self::MASK)
65 }
66 fn contains<T: Into<Self::Collection>>(&self, needle: T) -> bool {
67 let needle: Self::Bits = needle.into().to_primitive();
68 let haystack: Self::Bits = self.to_primitive();
69 needle & haystack == needle
70 }
71}
72pub trait FlagValueCollection<E: FlagValue>:
74 Sized + Deref<Target = E::Bits> + AsRef<E::Bits> + From<E>
75{
76 fn to_primitive(&self) -> E::Bits;
77 fn from_primitive(value: &E::Bits) -> Self;
78 fn into_iter(&self) -> FlagIterator<E::Bits, E, Self> {
79 FlagIterator::new(self.to_primitive())
80 }
81 fn len(&self) -> u32;
82 fn contains<T: Into<Self>>(&self, needle: T) -> bool {
83 let needle: E::Bits = needle.into().to_primitive();
84 let haystack: E::Bits = self.to_primitive();
85 needle & haystack == needle
86 }
87}
88pub struct FlagIterator<T: FlagPrimitive, V: FlagValue<Bits = T>, C: FlagValueCollection<V>> {
89 mask: T,
90 current_bit: T,
91 value: T,
92 phantom: PhantomData<V>,
93 collection: PhantomData<C>,
94}
95impl<T: FlagPrimitive, V: FlagValue<Bits = T>, C: FlagValueCollection<V>> FlagIterator<T, V, C> {
96 pub fn new(value: T) -> Self {
97 FlagIterator {
98 mask: V::MASK,
99 current_bit: T::ONE,
100 value,
101 phantom: PhantomData,
102 collection: PhantomData,
103 }
104 }
105}
106
107impl<T: FlagPrimitive, V: FlagValue<Bits = T>, C: FlagValueCollection<V>> Iterator
108 for FlagIterator<T, V, C>
109{
110 type Item = V;
111
112 fn next(&mut self) -> Option<Self::Item> {
113 if self.mask == T::ZERO {
114 return None;
115 }
116 while self.mask & self.current_bit == T::ZERO {
117 self.current_bit = self.current_bit << T::ONE;
118 }
119 self.mask = self.mask & !self.current_bit & self.value;
120 V::from_primitive(&self.current_bit)
121 }
122}
123
124#[cfg(test)]
125mod test {
126 use flags_derive::derive_flags;
127 derive_flags! {
128 #[derive(Debug)]
129 #[flag]
130 pub enum Flag {
131 A = 2,B = 4,C = 8,D = 16
132 }
133 #[flags]
134 pub struct Flags(u8);
135 }
136 #[test]
137 fn test() {
138 dbg!(Flag::A | Flag::B);
139 }
140}