1 | use core::{ |
2 | fmt, |
3 | ops::{BitAnd, BitOr, BitXor, Not}, |
4 | }; |
5 | |
6 | use crate::{ |
7 | iter, |
8 | parser::{ParseError, ParseHex, WriteHex}, |
9 | }; |
10 | |
11 | /** |
12 | A defined flags value that may be named or unnamed. |
13 | */ |
14 | pub struct Flag<B> { |
15 | name: &'static str, |
16 | value: B, |
17 | } |
18 | |
19 | impl<B> Flag<B> { |
20 | /** |
21 | Define a flag. |
22 | |
23 | If `name` is non-empty then the flag is named, otherwise it's unnamed. |
24 | */ |
25 | pub const fn new(name: &'static str, value: B) -> Self { |
26 | Flag { name, value } |
27 | } |
28 | |
29 | /** |
30 | Get the name of this flag. |
31 | |
32 | If the flag is unnamed then the returned string will be empty. |
33 | */ |
34 | pub const fn name(&self) -> &'static str { |
35 | self.name |
36 | } |
37 | |
38 | /** |
39 | Get the flags value of this flag. |
40 | */ |
41 | pub const fn value(&self) -> &B { |
42 | &self.value |
43 | } |
44 | |
45 | /** |
46 | Whether the flag is named. |
47 | |
48 | If [`Flag::name`] returns a non-empty string then this method will return `true`. |
49 | */ |
50 | pub const fn is_named(&self) -> bool { |
51 | !self.name.is_empty() |
52 | } |
53 | |
54 | /** |
55 | Whether the flag is unnamed. |
56 | |
57 | If [`Flag::name`] returns a non-empty string then this method will return `false`. |
58 | */ |
59 | pub const fn is_unnamed(&self) -> bool { |
60 | self.name.is_empty() |
61 | } |
62 | } |
63 | |
64 | /** |
65 | A set of defined flags using a bits type as storage. |
66 | |
67 | ## Implementing `Flags` |
68 | |
69 | This trait is implemented by the [`bitflags`](macro.bitflags.html) macro: |
70 | |
71 | ``` |
72 | use bitflags::bitflags; |
73 | |
74 | bitflags! { |
75 | struct MyFlags: u8 { |
76 | const A = 1; |
77 | const B = 1 << 1; |
78 | } |
79 | } |
80 | ``` |
81 | |
82 | It can also be implemented manually: |
83 | |
84 | ``` |
85 | use bitflags::{Flag, Flags}; |
86 | |
87 | struct MyFlags(u8); |
88 | |
89 | impl Flags for MyFlags { |
90 | const FLAGS: &'static [Flag<Self>] = &[ |
91 | Flag::new("A" , MyFlags(1)), |
92 | Flag::new("B" , MyFlags(1 << 1)), |
93 | ]; |
94 | |
95 | type Bits = u8; |
96 | |
97 | fn from_bits_retain(bits: Self::Bits) -> Self { |
98 | MyFlags(bits) |
99 | } |
100 | |
101 | fn bits(&self) -> Self::Bits { |
102 | self.0 |
103 | } |
104 | } |
105 | ``` |
106 | |
107 | ## Using `Flags` |
108 | |
109 | The `Flags` trait can be used generically to work with any flags types. In this example, |
110 | we can count the number of defined named flags: |
111 | |
112 | ``` |
113 | # use bitflags::{bitflags, Flags}; |
114 | fn defined_flags<F: Flags>() -> usize { |
115 | F::FLAGS.iter().filter(|f| f.is_named()).count() |
116 | } |
117 | |
118 | bitflags! { |
119 | struct MyFlags: u8 { |
120 | const A = 1; |
121 | const B = 1 << 1; |
122 | const C = 1 << 2; |
123 | |
124 | const _ = !0; |
125 | } |
126 | } |
127 | |
128 | assert_eq!(3, defined_flags::<MyFlags>()); |
129 | ``` |
130 | */ |
131 | pub trait Flags: Sized + 'static { |
132 | /// The set of defined flags. |
133 | const FLAGS: &'static [Flag<Self>]; |
134 | |
135 | /// The underlying bits type. |
136 | type Bits: Bits; |
137 | |
138 | /// Get a flags value with all bits unset. |
139 | fn empty() -> Self { |
140 | Self::from_bits_retain(Self::Bits::EMPTY) |
141 | } |
142 | |
143 | /// Get a flags value with all known bits set. |
144 | fn all() -> Self { |
145 | let mut truncated = Self::Bits::EMPTY; |
146 | |
147 | for flag in Self::FLAGS.iter() { |
148 | truncated = truncated | flag.value().bits(); |
149 | } |
150 | |
151 | Self::from_bits_retain(truncated) |
152 | } |
153 | |
154 | /// Get the underlying bits value. |
155 | /// |
156 | /// The returned value is exactly the bits set in this flags value. |
157 | fn bits(&self) -> Self::Bits; |
158 | |
159 | /// Convert from a bits value. |
160 | /// |
161 | /// This method will return `None` if any unknown bits are set. |
162 | fn from_bits(bits: Self::Bits) -> Option<Self> { |
163 | let truncated = Self::from_bits_truncate(bits); |
164 | |
165 | if truncated.bits() == bits { |
166 | Some(truncated) |
167 | } else { |
168 | None |
169 | } |
170 | } |
171 | |
172 | /// Convert from a bits value, unsetting any unknown bits. |
173 | fn from_bits_truncate(bits: Self::Bits) -> Self { |
174 | Self::from_bits_retain(bits & Self::all().bits()) |
175 | } |
176 | |
177 | /// Convert from a bits value exactly. |
178 | fn from_bits_retain(bits: Self::Bits) -> Self; |
179 | |
180 | /// Get a flags value with the bits of a flag with the given name set. |
181 | /// |
182 | /// This method will return `None` if `name` is empty or doesn't |
183 | /// correspond to any named flag. |
184 | fn from_name(name: &str) -> Option<Self> { |
185 | // Don't parse empty names as empty flags |
186 | if name.is_empty() { |
187 | return None; |
188 | } |
189 | |
190 | for flag in Self::FLAGS { |
191 | if flag.name() == name { |
192 | return Some(Self::from_bits_retain(flag.value().bits())); |
193 | } |
194 | } |
195 | |
196 | None |
197 | } |
198 | |
199 | /// Yield a set of contained flags values. |
200 | /// |
201 | /// Each yielded flags value will correspond to a defined named flag. Any unknown bits |
202 | /// will be yielded together as a final flags value. |
203 | fn iter(&self) -> iter::Iter<Self> { |
204 | iter::Iter::new(self) |
205 | } |
206 | |
207 | /// Yield a set of contained named flags values. |
208 | /// |
209 | /// This method is like [`Flags::iter`], except only yields bits in contained named flags. |
210 | /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded. |
211 | fn iter_names(&self) -> iter::IterNames<Self> { |
212 | iter::IterNames::new(self) |
213 | } |
214 | |
215 | /// Whether all bits in this flags value are unset. |
216 | fn is_empty(&self) -> bool { |
217 | self.bits() == Self::Bits::EMPTY |
218 | } |
219 | |
220 | /// Whether all known bits in this flags value are set. |
221 | fn is_all(&self) -> bool { |
222 | // NOTE: We check against `Self::all` here, not `Self::Bits::ALL` |
223 | // because the set of all flags may not use all bits |
224 | Self::all().bits() | self.bits() == self.bits() |
225 | } |
226 | |
227 | /// Whether any set bits in a source flags value are also set in a target flags value. |
228 | fn intersects(&self, other: Self) -> bool |
229 | where |
230 | Self: Sized, |
231 | { |
232 | self.bits() & other.bits() != Self::Bits::EMPTY |
233 | } |
234 | |
235 | /// Whether all set bits in a source flags value are also set in a target flags value. |
236 | fn contains(&self, other: Self) -> bool |
237 | where |
238 | Self: Sized, |
239 | { |
240 | self.bits() & other.bits() == other.bits() |
241 | } |
242 | |
243 | /// The bitwise or (`|`) of the bits in two flags values. |
244 | fn insert(&mut self, other: Self) |
245 | where |
246 | Self: Sized, |
247 | { |
248 | *self = Self::from_bits_retain(self.bits()).union(other); |
249 | } |
250 | |
251 | /// The intersection of a source flags value with the complement of a target flags value (`&!`). |
252 | /// |
253 | /// This method is not equivalent to `self & !other` when `other` has unknown bits set. |
254 | /// `remove` won't truncate `other`, but the `!` operator will. |
255 | fn remove(&mut self, other: Self) |
256 | where |
257 | Self: Sized, |
258 | { |
259 | *self = Self::from_bits_retain(self.bits()).difference(other); |
260 | } |
261 | |
262 | /// The bitwise exclusive-or (`^`) of the bits in two flags values. |
263 | fn toggle(&mut self, other: Self) |
264 | where |
265 | Self: Sized, |
266 | { |
267 | *self = Self::from_bits_retain(self.bits()).symmetric_difference(other); |
268 | } |
269 | |
270 | /// Call [`Flags::insert`] when `value` is `true` or [`Flags::remove`] when `value` is `false`. |
271 | fn set(&mut self, other: Self, value: bool) |
272 | where |
273 | Self: Sized, |
274 | { |
275 | if value { |
276 | self.insert(other); |
277 | } else { |
278 | self.remove(other); |
279 | } |
280 | } |
281 | |
282 | /// The bitwise and (`&`) of the bits in two flags values. |
283 | #[must_use ] |
284 | fn intersection(self, other: Self) -> Self { |
285 | Self::from_bits_retain(self.bits() & other.bits()) |
286 | } |
287 | |
288 | /// The bitwise or (`|`) of the bits in two flags values. |
289 | #[must_use ] |
290 | fn union(self, other: Self) -> Self { |
291 | Self::from_bits_retain(self.bits() | other.bits()) |
292 | } |
293 | |
294 | /// The intersection of a source flags value with the complement of a target flags value (`&!`). |
295 | /// |
296 | /// This method is not equivalent to `self & !other` when `other` has unknown bits set. |
297 | /// `difference` won't truncate `other`, but the `!` operator will. |
298 | #[must_use ] |
299 | fn difference(self, other: Self) -> Self { |
300 | Self::from_bits_retain(self.bits() & !other.bits()) |
301 | } |
302 | |
303 | /// The bitwise exclusive-or (`^`) of the bits in two flags values. |
304 | #[must_use ] |
305 | fn symmetric_difference(self, other: Self) -> Self { |
306 | Self::from_bits_retain(self.bits() ^ other.bits()) |
307 | } |
308 | |
309 | /// The bitwise negation (`!`) of the bits in a flags value, truncating the result. |
310 | #[must_use ] |
311 | fn complement(self) -> Self { |
312 | Self::from_bits_truncate(!self.bits()) |
313 | } |
314 | } |
315 | |
316 | /** |
317 | A bits type that can be used as storage for a flags type. |
318 | */ |
319 | pub trait Bits: |
320 | Clone |
321 | + Copy |
322 | + PartialEq |
323 | + BitAnd<Output = Self> |
324 | + BitOr<Output = Self> |
325 | + BitXor<Output = Self> |
326 | + Not<Output = Self> |
327 | + Sized |
328 | + 'static |
329 | { |
330 | /// A value with all bits unset. |
331 | const EMPTY: Self; |
332 | |
333 | /// A value with all bits set. |
334 | const ALL: Self; |
335 | } |
336 | |
337 | // Not re-exported: prevent custom `Bits` impls being used in the `bitflags!` macro, |
338 | // or they may fail to compile based on crate features |
339 | pub trait Primitive {} |
340 | |
341 | macro_rules! impl_bits { |
342 | ($($u:ty, $i:ty,)*) => { |
343 | $( |
344 | impl Bits for $u { |
345 | const EMPTY: $u = 0; |
346 | const ALL: $u = <$u>::MAX; |
347 | } |
348 | |
349 | impl Bits for $i { |
350 | const EMPTY: $i = 0; |
351 | const ALL: $i = <$u>::MAX as $i; |
352 | } |
353 | |
354 | impl ParseHex for $u { |
355 | fn parse_hex(input: &str) -> Result<Self, ParseError> { |
356 | <$u>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input)) |
357 | } |
358 | } |
359 | |
360 | impl ParseHex for $i { |
361 | fn parse_hex(input: &str) -> Result<Self, ParseError> { |
362 | <$i>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input)) |
363 | } |
364 | } |
365 | |
366 | impl WriteHex for $u { |
367 | fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result { |
368 | write!(writer, "{:x}" , self) |
369 | } |
370 | } |
371 | |
372 | impl WriteHex for $i { |
373 | fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result { |
374 | write!(writer, "{:x}" , self) |
375 | } |
376 | } |
377 | |
378 | impl Primitive for $i {} |
379 | impl Primitive for $u {} |
380 | )* |
381 | } |
382 | } |
383 | |
384 | impl_bits! { |
385 | u8, i8, |
386 | u16, i16, |
387 | u32, i32, |
388 | u64, i64, |
389 | u128, i128, |
390 | usize, isize, |
391 | } |
392 | |
393 | /// A trait for referencing the `bitflags`-owned internal type |
394 | /// without exposing it publicly. |
395 | pub trait PublicFlags { |
396 | /// The type of the underlying storage. |
397 | type Primitive: Primitive; |
398 | |
399 | /// The type of the internal field on the generated flags type. |
400 | type Internal; |
401 | } |
402 | |
403 | #[doc (hidden)] |
404 | #[deprecated (note = "use the `Flags` trait instead" )] |
405 | pub trait BitFlags: ImplementedByBitFlagsMacro + Flags { |
406 | /// An iterator over enabled flags in an instance of the type. |
407 | type Iter: Iterator<Item = Self>; |
408 | |
409 | /// An iterator over the raw names and bits for enabled flags in an instance of the type. |
410 | type IterNames: Iterator<Item = (&'static str, Self)>; |
411 | } |
412 | |
413 | #[allow (deprecated)] |
414 | impl<B: Flags> BitFlags for B { |
415 | type Iter = iter::Iter<Self>; |
416 | type IterNames = iter::IterNames<Self>; |
417 | } |
418 | |
419 | impl<B: Flags> ImplementedByBitFlagsMacro for B {} |
420 | |
421 | /// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro. |
422 | /// |
423 | /// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their |
424 | /// manual implementations won't break between non-breaking releases. |
425 | #[doc (hidden)] |
426 | pub trait ImplementedByBitFlagsMacro {} |
427 | |
428 | pub(crate) mod __private { |
429 | pub use super::{ImplementedByBitFlagsMacro, PublicFlags}; |
430 | } |
431 | |