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