1use core::ops::{BitAnd, BitOr, BitXor, Not};
2
3use crate::{BitFlag, BitFlags, BitFlagsExt, BitFlagsSpec, util};
4
5pub trait BitFlagExt<T, U>: Sized
12where
13 U: ?Sized,
14{
15 #[must_use]
25 fn try_from_flags(flags: BitFlags<T, U>) -> Option<Self>
26 where
27 T: Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
28 U: BitFlagsSpec<T>;
29
30 #[must_use]
38 fn try_from_bit(i: u8) -> Option<Self>
39 where
40 T: PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
41 U: BitFlagsSpec<T>;
42
43 #[must_use]
50 fn try_from_bits(bits: T) -> Option<Self>
51 where
52 T: PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
53 U: BitFlagsSpec<T>;
54
55 #[must_use]
62 fn try_from_bits_retain(bits: T) -> Option<Self>
63 where
64 T: util::IntOpsExt;
65
66 #[must_use]
74 fn is_valid(&self) -> bool
75 where
76 T: Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
77 U: BitFlagsSpec<T>;
78
79 #[must_use]
86 fn mask(&self) -> Option<T>
87 where
88 T: util::IntOpsExt;
89
90 #[must_use]
96 fn intersection(self, other: Self) -> BitFlags<T, U>
97 where
98 T: Copy + BitAnd<T, Output = T> + util::IntOpsExt;
99
100 #[must_use]
105 fn union(self, other: Self) -> BitFlags<T, U>
106 where
107 T: Copy + BitOr<T, Output = T> + util::IntOpsExt;
108
109 #[must_use]
117 fn difference(self, other: Self) -> BitFlags<T, U>
118 where
119 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt;
120
121 #[must_use]
128 fn symmetric_difference(self, other: Self) -> BitFlags<T, U>
129 where
130 T: Copy + BitXor<T, Output = T> + util::IntOpsExt;
131
132 #[must_use]
138 fn complement(self) -> BitFlags<T, U>
139 where
140 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
141 U: BitFlagsSpec<T>;
142}
143
144impl<T, U> BitFlagExt<T, U> for BitFlag<T, U>
145where
146 U: ?Sized,
147{
148 #[inline]
149 fn try_from_flags(flags: BitFlags<T, U>) -> Option<Self>
150 where
151 T: Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
152 U: BitFlagsSpec<T>,
153 {
154 Self::try_from_bits(flags.bits())
155 }
156
157 #[inline]
158 fn try_from_bit(i: u8) -> Option<Self>
159 where
160 T: PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
161 U: BitFlagsSpec<T>,
162 {
163 let bits = T::ONE.checked_shl(u32::from(i))?;
164 ((i < T::BITS) && (bits & !U::VALID_BITS_MASK) == T::ZERO).then(|| Self::from_bit_retain(i))
165 }
166
167 #[inline]
168 fn try_from_bits(bits: T) -> Option<Self>
169 where
170 T: PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
171 U: BitFlagsSpec<T>,
172 {
173 if bits.count_ones() == 1
174 && let Some(bit) = bits.lowest_one()
175 && let Ok(bit) = u8::try_from(bit)
176 {
177 Self::try_from_bit(bit)
178 } else {
179 None
180 }
181 }
182
183 #[inline]
184 fn try_from_bits_retain(bits: T) -> Option<Self>
185 where
186 T: util::IntOpsExt,
187 {
188 if bits.count_ones() == 1
189 && let Some(bit) = bits.lowest_one()
190 && let Ok(bit) = u8::try_from(bit)
191 {
192 Some(Self::from_bit_retain(bit))
193 } else {
194 None
195 }
196 }
197
198 #[inline]
199 fn is_valid(&self) -> bool
200 where
201 T: Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
202 U: BitFlagsSpec<T>,
203 {
204 (self.bit() < T::BITS) && BitFlags::<T, U>::from_flag(*self).is_valid()
205 }
206
207 #[inline]
208 fn mask(&self) -> Option<T>
209 where
210 T: util::IntOpsExt,
211 {
212 T::ONE.checked_shl(u32::from(self.bit()))
213 }
214
215 #[inline]
216 fn intersection(self, other: Self) -> BitFlags<T, U>
217 where
218 T: Copy + BitAnd<T, Output = T> + util::IntOpsExt,
219 {
220 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
221 .intersection(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
222 }
223
224 #[inline]
225 fn union(self, other: Self) -> BitFlags<T, U>
226 where
227 T: Copy + BitOr<T, Output = T> + util::IntOpsExt,
228 {
229 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
230 .union(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
231 }
232
233 #[inline]
234 fn difference(self, other: Self) -> BitFlags<T, U>
235 where
236 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
237 {
238 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
239 .difference(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
240 }
241
242 #[inline]
243 fn symmetric_difference(self, other: Self) -> BitFlags<T, U>
244 where
245 T: Copy + BitXor<T, Output = T> + util::IntOpsExt,
246 {
247 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
248 .symmetric_difference(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
249 }
250
251 #[inline]
252 fn complement(self) -> BitFlags<T, U>
253 where
254 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
255 U: BitFlagsSpec<T>,
256 {
257 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self).complement()
258 }
259}