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: 'static + 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: 'static + 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: 'static + 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: 'static + 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]
95 fn mask_or_default(&self) -> T
96 where
97 T: Default + util::IntOpsExt;
98
99 #[must_use]
105 fn intersection(self, other: Self) -> BitFlags<T, U>
106 where
107 T: Copy + BitAnd<T, Output = T> + util::IntOpsExt;
108
109 #[must_use]
114 fn union(self, other: Self) -> BitFlags<T, U>
115 where
116 T: Copy + BitOr<T, Output = T> + util::IntOpsExt;
117
118 #[must_use]
126 fn difference(self, other: Self) -> BitFlags<T, U>
127 where
128 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt;
129
130 #[must_use]
137 fn symmetric_difference(self, other: Self) -> BitFlags<T, U>
138 where
139 T: Copy + BitXor<T, Output = T> + util::IntOpsExt;
140
141 #[must_use]
147 fn complement(self) -> BitFlags<T, U>
148 where
149 T: 'static + Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
150 U: BitFlagsSpec<T>;
151}
152
153impl<T, U> BitFlagExt<T, U> for BitFlag<T, U>
154where
155 U: ?Sized,
156{
157 #[inline]
158 fn try_from_flags(flags: BitFlags<T, U>) -> Option<Self>
159 where
160 T: 'static + Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
161 U: BitFlagsSpec<T>,
162 {
163 Self::try_from_bits(flags.bits())
164 }
165
166 #[inline]
167 fn try_from_bit(i: u8) -> Option<Self>
168 where
169 T: 'static + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
170 U: BitFlagsSpec<T>,
171 {
172 let bits = T::ONE.checked_shl(u32::from(i))?;
173 ((i < T::BITS) && (bits & !U::VALID_BITS_MASK) == T::ZERO).then(|| Self::from_bit_retain(i))
174 }
175
176 #[inline]
177 fn try_from_bits(bits: T) -> Option<Self>
178 where
179 T: 'static + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
180 U: BitFlagsSpec<T>,
181 {
182 if bits.count_ones() == 1
183 && let Some(bit) = bits.lowest_one()
184 && let Ok(bit) = u8::try_from(bit)
185 {
186 Self::try_from_bit(bit)
187 } else {
188 None
189 }
190 }
191
192 #[inline]
193 fn try_from_bits_retain(bits: T) -> Option<Self>
194 where
195 T: util::IntOpsExt,
196 {
197 if bits.count_ones() == 1
198 && let Some(bit) = bits.lowest_one()
199 && let Ok(bit) = u8::try_from(bit)
200 {
201 Some(Self::from_bit_retain(bit))
202 } else {
203 None
204 }
205 }
206
207 #[inline]
208 fn is_valid(&self) -> bool
209 where
210 T: 'static + Copy + PartialEq + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
211 U: BitFlagsSpec<T>,
212 {
213 (self.bit() < T::BITS) && BitFlags::<T, U>::from_flag(*self).is_valid()
214 }
215
216 #[inline]
217 fn mask(&self) -> Option<T>
218 where
219 T: util::IntOpsExt,
220 {
221 T::ONE.checked_shl(u32::from(self.bit()))
222 }
223
224 #[inline]
225 fn mask_or_default(&self) -> T
226 where
227 T: Default + util::IntOpsExt,
228 {
229 self.mask().unwrap_or_default()
230 }
231
232 #[inline]
233 fn intersection(self, other: Self) -> BitFlags<T, U>
234 where
235 T: Copy + BitAnd<T, Output = T> + util::IntOpsExt,
236 {
237 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
238 .intersection(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
239 }
240
241 #[inline]
242 fn union(self, other: Self) -> BitFlags<T, U>
243 where
244 T: Copy + BitOr<T, Output = T> + util::IntOpsExt,
245 {
246 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
247 .union(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
248 }
249
250 #[inline]
251 fn difference(self, other: Self) -> BitFlags<T, U>
252 where
253 T: Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
254 {
255 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
256 .difference(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
257 }
258
259 #[inline]
260 fn symmetric_difference(self, other: Self) -> BitFlags<T, U>
261 where
262 T: Copy + BitXor<T, Output = T> + util::IntOpsExt,
263 {
264 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self)
265 .symmetric_difference(<BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(other))
266 }
267
268 #[inline]
269 fn complement(self) -> BitFlags<T, U>
270 where
271 T: 'static + Copy + Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
272 U: BitFlagsSpec<T>,
273 {
274 <BitFlags<T, U> as BitFlagsExt<T, U>>::from_flag(self).complement()
275 }
276}