1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. |
4 | // |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
8 | // option. This file may not be copied, modified, or distributed |
9 | // except according to those terms. |
10 | |
11 | //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. |
12 | //! It can be used for creating typesafe wrappers around C APIs. |
13 | //! |
14 | //! The `bitflags!` macro generates `struct`s that manage a set of flags. The |
15 | //! flags should only be defined for integer types, otherwise unexpected type |
16 | //! errors may occur at compile time. |
17 | //! |
18 | //! # Example |
19 | //! |
20 | //! ``` |
21 | //! use bitflags::bitflags; |
22 | //! |
23 | //! bitflags! { |
24 | //! struct Flags: u32 { |
25 | //! const A = 0b00000001; |
26 | //! const B = 0b00000010; |
27 | //! const C = 0b00000100; |
28 | //! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
29 | //! } |
30 | //! } |
31 | //! |
32 | //! fn main() { |
33 | //! let e1 = Flags::A | Flags::C; |
34 | //! let e2 = Flags::B | Flags::C; |
35 | //! assert_eq!((e1 | e2), Flags::ABC); // union |
36 | //! assert_eq!((e1 & e2), Flags::C); // intersection |
37 | //! assert_eq!((e1 - e2), Flags::A); // set difference |
38 | //! assert_eq!(!e2, Flags::A); // set complement |
39 | //! } |
40 | //! ``` |
41 | //! |
42 | //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code |
43 | //! generated by the above `bitflags!` expansion. |
44 | //! |
45 | //! The generated `struct`s can also be extended with type and trait |
46 | //! implementations: |
47 | //! |
48 | //! ``` |
49 | //! use std::fmt; |
50 | //! |
51 | //! use bitflags::bitflags; |
52 | //! |
53 | //! bitflags! { |
54 | //! struct Flags: u32 { |
55 | //! const A = 0b00000001; |
56 | //! const B = 0b00000010; |
57 | //! } |
58 | //! } |
59 | //! |
60 | //! impl Flags { |
61 | //! pub fn clear(&mut self) { |
62 | //! self.bits = 0; // The `bits` field can be accessed from within the |
63 | //! // same module where the `bitflags!` macro was invoked. |
64 | //! } |
65 | //! } |
66 | //! |
67 | //! impl fmt::Display for Flags { |
68 | //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
69 | //! write!(f, "hi!" ) |
70 | //! } |
71 | //! } |
72 | //! |
73 | //! fn main() { |
74 | //! let mut flags = Flags::A | Flags::B; |
75 | //! flags.clear(); |
76 | //! assert!(flags.is_empty()); |
77 | //! assert_eq!(format!("{}" , flags), "hi!" ); |
78 | //! assert_eq!(format!("{:?}" , Flags::A | Flags::B), "A | B" ); |
79 | //! assert_eq!(format!("{:?}" , Flags::B), "B" ); |
80 | //! } |
81 | //! ``` |
82 | //! |
83 | //! # Visibility |
84 | //! |
85 | //! The generated structs and their associated flag constants are not exported |
86 | //! out of the current module by default. A definition can be exported out of |
87 | //! the current module by adding `pub` before `struct`: |
88 | //! |
89 | //! ``` |
90 | //! mod example { |
91 | //! use bitflags::bitflags; |
92 | //! |
93 | //! bitflags! { |
94 | //! pub struct Flags1: u32 { |
95 | //! const A = 0b00000001; |
96 | //! } |
97 | //! |
98 | //! # pub |
99 | //! struct Flags2: u32 { |
100 | //! const B = 0b00000010; |
101 | //! } |
102 | //! } |
103 | //! } |
104 | //! |
105 | //! fn main() { |
106 | //! let flag1 = example::Flags1::A; |
107 | //! let flag2 = example::Flags2::B; // error: const `B` is private |
108 | //! } |
109 | //! ``` |
110 | //! |
111 | //! # Attributes |
112 | //! |
113 | //! Attributes can be attached to the generated `struct`s by placing them |
114 | //! before the `struct` keyword. |
115 | //! |
116 | //! ## Representations |
117 | //! |
118 | //! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type |
119 | //! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype. |
120 | //! |
121 | //! ``` |
122 | //! use bitflags::bitflags; |
123 | //! |
124 | //! bitflags! { |
125 | //! #[repr(transparent)] |
126 | //! struct Flags: u32 { |
127 | //! const A = 0b00000001; |
128 | //! const B = 0b00000010; |
129 | //! const C = 0b00000100; |
130 | //! } |
131 | //! } |
132 | //! ``` |
133 | //! |
134 | //! # Trait implementations |
135 | //! |
136 | //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` |
137 | //! traits are automatically derived for the `struct`s using the `derive` attribute. |
138 | //! Additional traits can be derived by providing an explicit `derive` |
139 | //! attribute on `struct`. |
140 | //! |
141 | //! The `Extend` and `FromIterator` traits are implemented for the `struct`s, |
142 | //! too: `Extend` adds the union of the instances of the `struct` iterated over, |
143 | //! while `FromIterator` calculates the union. |
144 | //! |
145 | //! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also |
146 | //! implemented by displaying the bits value of the internal struct. |
147 | //! |
148 | //! ## Operators |
149 | //! |
150 | //! The following operator traits are implemented for the generated `struct`s: |
151 | //! |
152 | //! - `BitOr` and `BitOrAssign`: union |
153 | //! - `BitAnd` and `BitAndAssign`: intersection |
154 | //! - `BitXor` and `BitXorAssign`: toggle |
155 | //! - `Sub` and `SubAssign`: set difference |
156 | //! - `Not`: set complement |
157 | //! |
158 | //! # Methods |
159 | //! |
160 | //! The following methods are defined for the generated `struct`s: |
161 | //! |
162 | //! - `empty`: an empty set of flags |
163 | //! - `all`: the set of all defined flags |
164 | //! - `bits`: the raw value of the flags currently stored |
165 | //! - `from_bits`: convert from underlying bit representation, unless that |
166 | //! representation contains bits that do not correspond to a |
167 | //! defined flag |
168 | //! - `from_bits_truncate`: convert from underlying bit representation, dropping |
169 | //! any bits that do not correspond to defined flags |
170 | //! - `from_bits_unchecked`: convert from underlying bit representation, keeping |
171 | //! all bits (even those not corresponding to defined |
172 | //! flags) |
173 | //! - `is_empty`: `true` if no flags are currently stored |
174 | //! - `is_all`: `true` if currently set flags exactly equal all defined flags |
175 | //! - `intersects`: `true` if there are flags common to both `self` and `other` |
176 | //! - `contains`: `true` if all of the flags in `other` are contained within `self` |
177 | //! - `insert`: inserts the specified flags in-place |
178 | //! - `remove`: removes the specified flags in-place |
179 | //! - `toggle`: the specified flags will be inserted if not present, and removed |
180 | //! if they are. |
181 | //! - `set`: inserts or removes the specified flags depending on the passed value |
182 | //! - `intersection`: returns a new set of flags, containing only the flags present |
183 | //! in both `self` and `other` (the argument to the function). |
184 | //! - `union`: returns a new set of flags, containing any flags present in |
185 | //! either `self` or `other` (the argument to the function). |
186 | //! - `difference`: returns a new set of flags, containing all flags present in |
187 | //! `self` without any of the flags present in `other` (the |
188 | //! argument to the function). |
189 | //! - `symmetric_difference`: returns a new set of flags, containing all flags |
190 | //! present in either `self` or `other` (the argument |
191 | //! to the function), but not both. |
192 | //! - `complement`: returns a new set of flags, containing all flags which are |
193 | //! not set in `self`, but which are allowed for this type. |
194 | //! |
195 | //! ## Default |
196 | //! |
197 | //! The `Default` trait is not automatically implemented for the generated structs. |
198 | //! |
199 | //! If your default value is equal to `0` (which is the same value as calling `empty()` |
200 | //! on the generated struct), you can simply derive `Default`: |
201 | //! |
202 | //! ``` |
203 | //! use bitflags::bitflags; |
204 | //! |
205 | //! bitflags! { |
206 | //! // Results in default value with bits: 0 |
207 | //! #[derive(Default)] |
208 | //! struct Flags: u32 { |
209 | //! const A = 0b00000001; |
210 | //! const B = 0b00000010; |
211 | //! const C = 0b00000100; |
212 | //! } |
213 | //! } |
214 | //! |
215 | //! fn main() { |
216 | //! let derived_default: Flags = Default::default(); |
217 | //! assert_eq!(derived_default.bits(), 0); |
218 | //! } |
219 | //! ``` |
220 | //! |
221 | //! If your default value is not equal to `0` you need to implement `Default` yourself: |
222 | //! |
223 | //! ``` |
224 | //! use bitflags::bitflags; |
225 | //! |
226 | //! bitflags! { |
227 | //! struct Flags: u32 { |
228 | //! const A = 0b00000001; |
229 | //! const B = 0b00000010; |
230 | //! const C = 0b00000100; |
231 | //! } |
232 | //! } |
233 | //! |
234 | //! // explicit `Default` implementation |
235 | //! impl Default for Flags { |
236 | //! fn default() -> Flags { |
237 | //! Flags::A | Flags::C |
238 | //! } |
239 | //! } |
240 | //! |
241 | //! fn main() { |
242 | //! let implemented_default: Flags = Default::default(); |
243 | //! assert_eq!(implemented_default, (Flags::A | Flags::C)); |
244 | //! } |
245 | //! ``` |
246 | //! |
247 | //! # Zero Flags |
248 | //! |
249 | //! Flags with a value equal to zero will have some strange behavior that one should be aware of. |
250 | //! |
251 | //! ``` |
252 | //! use bitflags::bitflags; |
253 | //! |
254 | //! bitflags! { |
255 | //! struct Flags: u32 { |
256 | //! const NONE = 0b00000000; |
257 | //! const SOME = 0b00000001; |
258 | //! } |
259 | //! } |
260 | //! |
261 | //! fn main() { |
262 | //! let empty = Flags::empty(); |
263 | //! let none = Flags::NONE; |
264 | //! let some = Flags::SOME; |
265 | //! |
266 | //! // Zero flags are treated as always present |
267 | //! assert!(empty.contains(Flags::NONE)); |
268 | //! assert!(none.contains(Flags::NONE)); |
269 | //! assert!(some.contains(Flags::NONE)); |
270 | //! |
271 | //! // Zero flags will be ignored when testing for emptiness |
272 | //! assert!(none.is_empty()); |
273 | //! } |
274 | //! ``` |
275 | //! |
276 | //! Users should generally avoid defining a flag with a value of zero. |
277 | |
278 | #![cfg_attr (not(test), no_std)] |
279 | #![doc (html_root_url = "https://docs.rs/bitflags/1.3.2" )] |
280 | |
281 | #[doc (hidden)] |
282 | pub extern crate core as _core; |
283 | |
284 | /// The macro used to generate the flag structures. |
285 | /// |
286 | /// See the [crate level docs](../bitflags/index.html) for complete documentation. |
287 | /// |
288 | /// # Example |
289 | /// |
290 | /// ``` |
291 | /// use bitflags::bitflags; |
292 | /// |
293 | /// bitflags! { |
294 | /// struct Flags: u32 { |
295 | /// const A = 0b00000001; |
296 | /// const B = 0b00000010; |
297 | /// const C = 0b00000100; |
298 | /// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
299 | /// } |
300 | /// } |
301 | /// |
302 | /// fn main() { |
303 | /// let e1 = Flags::A | Flags::C; |
304 | /// let e2 = Flags::B | Flags::C; |
305 | /// assert_eq!((e1 | e2), Flags::ABC); // union |
306 | /// assert_eq!((e1 & e2), Flags::C); // intersection |
307 | /// assert_eq!((e1 - e2), Flags::A); // set difference |
308 | /// assert_eq!(!e2, Flags::A); // set complement |
309 | /// } |
310 | /// ``` |
311 | /// |
312 | /// The generated `struct`s can also be extended with type and trait |
313 | /// implementations: |
314 | /// |
315 | /// ``` |
316 | /// use std::fmt; |
317 | /// |
318 | /// use bitflags::bitflags; |
319 | /// |
320 | /// bitflags! { |
321 | /// struct Flags: u32 { |
322 | /// const A = 0b00000001; |
323 | /// const B = 0b00000010; |
324 | /// } |
325 | /// } |
326 | /// |
327 | /// impl Flags { |
328 | /// pub fn clear(&mut self) { |
329 | /// self.bits = 0; // The `bits` field can be accessed from within the |
330 | /// // same module where the `bitflags!` macro was invoked. |
331 | /// } |
332 | /// } |
333 | /// |
334 | /// impl fmt::Display for Flags { |
335 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
336 | /// write!(f, "hi!" ) |
337 | /// } |
338 | /// } |
339 | /// |
340 | /// fn main() { |
341 | /// let mut flags = Flags::A | Flags::B; |
342 | /// flags.clear(); |
343 | /// assert!(flags.is_empty()); |
344 | /// assert_eq!(format!("{}" , flags), "hi!" ); |
345 | /// assert_eq!(format!("{:?}" , Flags::A | Flags::B), "A | B" ); |
346 | /// assert_eq!(format!("{:?}" , Flags::B), "B" ); |
347 | /// } |
348 | /// ``` |
349 | #[macro_export (local_inner_macros)] |
350 | macro_rules! bitflags { |
351 | ( |
352 | $(#[$outer:meta])* |
353 | $vis:vis struct $BitFlags:ident: $T:ty { |
354 | $( |
355 | $(#[$inner:ident $($args:tt)*])* |
356 | const $Flag:ident = $value:expr; |
357 | )* |
358 | } |
359 | |
360 | $($t:tt)* |
361 | ) => { |
362 | $(#[$outer])* |
363 | #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] |
364 | $vis struct $BitFlags { |
365 | bits: $T, |
366 | } |
367 | |
368 | __impl_bitflags! { |
369 | $BitFlags: $T { |
370 | $( |
371 | $(#[$inner $($args)*])* |
372 | $Flag = $value; |
373 | )* |
374 | } |
375 | } |
376 | |
377 | bitflags! { |
378 | $($t)* |
379 | } |
380 | }; |
381 | () => {}; |
382 | } |
383 | |
384 | // A helper macro to implement the `all` function. |
385 | #[macro_export (local_inner_macros)] |
386 | #[doc (hidden)] |
387 | macro_rules! __impl_all_bitflags { |
388 | ( |
389 | $BitFlags:ident: $T:ty { |
390 | $( |
391 | $(#[$attr:ident $($args:tt)*])* |
392 | $Flag:ident = $value:expr; |
393 | )+ |
394 | } |
395 | ) => { |
396 | // See `Debug::fmt` for why this approach is taken. |
397 | #[allow(non_snake_case)] |
398 | trait __BitFlags { |
399 | $( |
400 | const $Flag: $T = 0; |
401 | )+ |
402 | } |
403 | #[allow(non_snake_case)] |
404 | impl __BitFlags for $BitFlags { |
405 | $( |
406 | __impl_bitflags! { |
407 | #[allow(deprecated)] |
408 | $(? #[$attr $($args)*])* |
409 | const $Flag: $T = Self::$Flag.bits; |
410 | } |
411 | )+ |
412 | } |
413 | Self { bits: $(<Self as __BitFlags>::$Flag)|+ } |
414 | }; |
415 | ( |
416 | $BitFlags:ident: $T:ty { } |
417 | ) => { |
418 | Self { bits: 0 } |
419 | }; |
420 | } |
421 | |
422 | #[macro_export (local_inner_macros)] |
423 | #[doc (hidden)] |
424 | macro_rules! __impl_bitflags { |
425 | ( |
426 | $BitFlags:ident: $T:ty { |
427 | $( |
428 | $(#[$attr:ident $($args:tt)*])* |
429 | $Flag:ident = $value:expr; |
430 | )* |
431 | } |
432 | ) => { |
433 | impl $crate::_core::fmt::Debug for $BitFlags { |
434 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
435 | // This convoluted approach is to handle #[cfg]-based flag |
436 | // omission correctly. For example it needs to support: |
437 | // |
438 | // #[cfg(unix)] const A: Flag = /* ... */; |
439 | // #[cfg(windows)] const B: Flag = /* ... */; |
440 | |
441 | // Unconditionally define a check for every flag, even disabled |
442 | // ones. |
443 | #[allow(non_snake_case)] |
444 | trait __BitFlags { |
445 | $( |
446 | #[inline] |
447 | fn $Flag(&self) -> bool { false } |
448 | )* |
449 | } |
450 | |
451 | // Conditionally override the check for just those flags that |
452 | // are not #[cfg]ed away. |
453 | #[allow(non_snake_case)] |
454 | impl __BitFlags for $BitFlags { |
455 | $( |
456 | __impl_bitflags! { |
457 | #[allow(deprecated)] |
458 | #[inline] |
459 | $(? #[$attr $($args)*])* |
460 | fn $Flag(&self) -> bool { |
461 | if Self::$Flag.bits == 0 && self.bits != 0 { |
462 | false |
463 | } else { |
464 | self.bits & Self::$Flag.bits == Self::$Flag.bits |
465 | } |
466 | } |
467 | } |
468 | )* |
469 | } |
470 | |
471 | let mut first = true; |
472 | $( |
473 | if <Self as __BitFlags>::$Flag(self) { |
474 | if !first { |
475 | f.write_str(" | " )?; |
476 | } |
477 | first = false; |
478 | f.write_str($crate::_core::stringify!($Flag))?; |
479 | } |
480 | )* |
481 | let extra_bits = self.bits & !Self::all().bits(); |
482 | if extra_bits != 0 { |
483 | if !first { |
484 | f.write_str(" | " )?; |
485 | } |
486 | first = false; |
487 | f.write_str("0x" )?; |
488 | $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?; |
489 | } |
490 | if first { |
491 | f.write_str("(empty)" )?; |
492 | } |
493 | Ok(()) |
494 | } |
495 | } |
496 | impl $crate::_core::fmt::Binary for $BitFlags { |
497 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
498 | $crate::_core::fmt::Binary::fmt(&self.bits, f) |
499 | } |
500 | } |
501 | impl $crate::_core::fmt::Octal for $BitFlags { |
502 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
503 | $crate::_core::fmt::Octal::fmt(&self.bits, f) |
504 | } |
505 | } |
506 | impl $crate::_core::fmt::LowerHex for $BitFlags { |
507 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
508 | $crate::_core::fmt::LowerHex::fmt(&self.bits, f) |
509 | } |
510 | } |
511 | impl $crate::_core::fmt::UpperHex for $BitFlags { |
512 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
513 | $crate::_core::fmt::UpperHex::fmt(&self.bits, f) |
514 | } |
515 | } |
516 | |
517 | #[allow(dead_code)] |
518 | impl $BitFlags { |
519 | $( |
520 | $(#[$attr $($args)*])* |
521 | pub const $Flag: Self = Self { bits: $value }; |
522 | )* |
523 | |
524 | /// Returns an empty set of flags. |
525 | #[inline] |
526 | pub const fn empty() -> Self { |
527 | Self { bits: 0 } |
528 | } |
529 | |
530 | /// Returns the set containing all flags. |
531 | #[inline] |
532 | pub const fn all() -> Self { |
533 | __impl_all_bitflags! { |
534 | $BitFlags: $T { |
535 | $( |
536 | $(#[$attr $($args)*])* |
537 | $Flag = $value; |
538 | )* |
539 | } |
540 | } |
541 | } |
542 | |
543 | /// Returns the raw value of the flags currently stored. |
544 | #[inline] |
545 | pub const fn bits(&self) -> $T { |
546 | self.bits |
547 | } |
548 | |
549 | /// Convert from underlying bit representation, unless that |
550 | /// representation contains bits that do not correspond to a flag. |
551 | #[inline] |
552 | pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> { |
553 | if (bits & !Self::all().bits()) == 0 { |
554 | $crate::_core::option::Option::Some(Self { bits }) |
555 | } else { |
556 | $crate::_core::option::Option::None |
557 | } |
558 | } |
559 | |
560 | /// Convert from underlying bit representation, dropping any bits |
561 | /// that do not correspond to flags. |
562 | #[inline] |
563 | pub const fn from_bits_truncate(bits: $T) -> Self { |
564 | Self { bits: bits & Self::all().bits } |
565 | } |
566 | |
567 | /// Convert from underlying bit representation, preserving all |
568 | /// bits (even those not corresponding to a defined flag). |
569 | /// |
570 | /// # Safety |
571 | /// |
572 | /// The caller of the `bitflags!` macro can chose to allow or |
573 | /// disallow extra bits for their bitflags type. |
574 | /// |
575 | /// The caller of `from_bits_unchecked()` has to ensure that |
576 | /// all bits correspond to a defined flag or that extra bits |
577 | /// are valid for this bitflags type. |
578 | #[inline] |
579 | pub const unsafe fn from_bits_unchecked(bits: $T) -> Self { |
580 | Self { bits } |
581 | } |
582 | |
583 | /// Returns `true` if no flags are currently stored. |
584 | #[inline] |
585 | pub const fn is_empty(&self) -> bool { |
586 | self.bits() == Self::empty().bits() |
587 | } |
588 | |
589 | /// Returns `true` if all flags are currently set. |
590 | #[inline] |
591 | pub const fn is_all(&self) -> bool { |
592 | Self::all().bits | self.bits == self.bits |
593 | } |
594 | |
595 | /// Returns `true` if there are flags common to both `self` and `other`. |
596 | #[inline] |
597 | pub const fn intersects(&self, other: Self) -> bool { |
598 | !(Self { bits: self.bits & other.bits}).is_empty() |
599 | } |
600 | |
601 | /// Returns `true` if all of the flags in `other` are contained within `self`. |
602 | #[inline] |
603 | pub const fn contains(&self, other: Self) -> bool { |
604 | (self.bits & other.bits) == other.bits |
605 | } |
606 | |
607 | /// Inserts the specified flags in-place. |
608 | #[inline] |
609 | pub fn insert(&mut self, other: Self) { |
610 | self.bits |= other.bits; |
611 | } |
612 | |
613 | /// Removes the specified flags in-place. |
614 | #[inline] |
615 | pub fn remove(&mut self, other: Self) { |
616 | self.bits &= !other.bits; |
617 | } |
618 | |
619 | /// Toggles the specified flags in-place. |
620 | #[inline] |
621 | pub fn toggle(&mut self, other: Self) { |
622 | self.bits ^= other.bits; |
623 | } |
624 | |
625 | /// Inserts or removes the specified flags depending on the passed value. |
626 | #[inline] |
627 | pub fn set(&mut self, other: Self, value: bool) { |
628 | if value { |
629 | self.insert(other); |
630 | } else { |
631 | self.remove(other); |
632 | } |
633 | } |
634 | |
635 | /// Returns the intersection between the flags in `self` and |
636 | /// `other`. |
637 | /// |
638 | /// Specifically, the returned set contains only the flags which are |
639 | /// present in *both* `self` *and* `other`. |
640 | /// |
641 | /// This is equivalent to using the `&` operator (e.g. |
642 | /// [`ops::BitAnd`]), as in `flags & other`. |
643 | /// |
644 | /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html |
645 | #[inline] |
646 | #[must_use] |
647 | pub const fn intersection(self, other: Self) -> Self { |
648 | Self { bits: self.bits & other.bits } |
649 | } |
650 | |
651 | /// Returns the union of between the flags in `self` and `other`. |
652 | /// |
653 | /// Specifically, the returned set contains all flags which are |
654 | /// present in *either* `self` *or* `other`, including any which are |
655 | /// present in both (see [`Self::symmetric_difference`] if that |
656 | /// is undesirable). |
657 | /// |
658 | /// This is equivalent to using the `|` operator (e.g. |
659 | /// [`ops::BitOr`]), as in `flags | other`. |
660 | /// |
661 | /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html |
662 | #[inline] |
663 | #[must_use] |
664 | pub const fn union(self, other: Self) -> Self { |
665 | Self { bits: self.bits | other.bits } |
666 | } |
667 | |
668 | /// Returns the difference between the flags in `self` and `other`. |
669 | /// |
670 | /// Specifically, the returned set contains all flags present in |
671 | /// `self`, except for the ones present in `other`. |
672 | /// |
673 | /// It is also conceptually equivalent to the "bit-clear" operation: |
674 | /// `flags & !other` (and this syntax is also supported). |
675 | /// |
676 | /// This is equivalent to using the `-` operator (e.g. |
677 | /// [`ops::Sub`]), as in `flags - other`. |
678 | /// |
679 | /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html |
680 | #[inline] |
681 | #[must_use] |
682 | pub const fn difference(self, other: Self) -> Self { |
683 | Self { bits: self.bits & !other.bits } |
684 | } |
685 | |
686 | /// Returns the [symmetric difference][sym-diff] between the flags |
687 | /// in `self` and `other`. |
688 | /// |
689 | /// Specifically, the returned set contains the flags present which |
690 | /// are present in `self` or `other`, but that are not present in |
691 | /// both. Equivalently, it contains the flags present in *exactly |
692 | /// one* of the sets `self` and `other`. |
693 | /// |
694 | /// This is equivalent to using the `^` operator (e.g. |
695 | /// [`ops::BitXor`]), as in `flags ^ other`. |
696 | /// |
697 | /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference |
698 | /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html |
699 | #[inline] |
700 | #[must_use] |
701 | pub const fn symmetric_difference(self, other: Self) -> Self { |
702 | Self { bits: self.bits ^ other.bits } |
703 | } |
704 | |
705 | /// Returns the complement of this set of flags. |
706 | /// |
707 | /// Specifically, the returned set contains all the flags which are |
708 | /// not set in `self`, but which are allowed for this type. |
709 | /// |
710 | /// Alternatively, it can be thought of as the set difference |
711 | /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`) |
712 | /// |
713 | /// This is equivalent to using the `!` operator (e.g. |
714 | /// [`ops::Not`]), as in `!flags`. |
715 | /// |
716 | /// [`Self::all()`]: Self::all |
717 | /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html |
718 | #[inline] |
719 | #[must_use] |
720 | pub const fn complement(self) -> Self { |
721 | Self::from_bits_truncate(!self.bits) |
722 | } |
723 | |
724 | } |
725 | |
726 | impl $crate::_core::ops::BitOr for $BitFlags { |
727 | type Output = Self; |
728 | |
729 | /// Returns the union of the two sets of flags. |
730 | #[inline] |
731 | fn bitor(self, other: $BitFlags) -> Self { |
732 | Self { bits: self.bits | other.bits } |
733 | } |
734 | } |
735 | |
736 | impl $crate::_core::ops::BitOrAssign for $BitFlags { |
737 | /// Adds the set of flags. |
738 | #[inline] |
739 | fn bitor_assign(&mut self, other: Self) { |
740 | self.bits |= other.bits; |
741 | } |
742 | } |
743 | |
744 | impl $crate::_core::ops::BitXor for $BitFlags { |
745 | type Output = Self; |
746 | |
747 | /// Returns the left flags, but with all the right flags toggled. |
748 | #[inline] |
749 | fn bitxor(self, other: Self) -> Self { |
750 | Self { bits: self.bits ^ other.bits } |
751 | } |
752 | } |
753 | |
754 | impl $crate::_core::ops::BitXorAssign for $BitFlags { |
755 | /// Toggles the set of flags. |
756 | #[inline] |
757 | fn bitxor_assign(&mut self, other: Self) { |
758 | self.bits ^= other.bits; |
759 | } |
760 | } |
761 | |
762 | impl $crate::_core::ops::BitAnd for $BitFlags { |
763 | type Output = Self; |
764 | |
765 | /// Returns the intersection between the two sets of flags. |
766 | #[inline] |
767 | fn bitand(self, other: Self) -> Self { |
768 | Self { bits: self.bits & other.bits } |
769 | } |
770 | } |
771 | |
772 | impl $crate::_core::ops::BitAndAssign for $BitFlags { |
773 | /// Disables all flags disabled in the set. |
774 | #[inline] |
775 | fn bitand_assign(&mut self, other: Self) { |
776 | self.bits &= other.bits; |
777 | } |
778 | } |
779 | |
780 | impl $crate::_core::ops::Sub for $BitFlags { |
781 | type Output = Self; |
782 | |
783 | /// Returns the set difference of the two sets of flags. |
784 | #[inline] |
785 | fn sub(self, other: Self) -> Self { |
786 | Self { bits: self.bits & !other.bits } |
787 | } |
788 | } |
789 | |
790 | impl $crate::_core::ops::SubAssign for $BitFlags { |
791 | /// Disables all flags enabled in the set. |
792 | #[inline] |
793 | fn sub_assign(&mut self, other: Self) { |
794 | self.bits &= !other.bits; |
795 | } |
796 | } |
797 | |
798 | impl $crate::_core::ops::Not for $BitFlags { |
799 | type Output = Self; |
800 | |
801 | /// Returns the complement of this set of flags. |
802 | #[inline] |
803 | fn not(self) -> Self { |
804 | Self { bits: !self.bits } & Self::all() |
805 | } |
806 | } |
807 | |
808 | impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { |
809 | fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) { |
810 | for item in iterator { |
811 | self.insert(item) |
812 | } |
813 | } |
814 | } |
815 | |
816 | impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { |
817 | fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self { |
818 | let mut result = Self::empty(); |
819 | result.extend(iterator); |
820 | result |
821 | } |
822 | } |
823 | }; |
824 | |
825 | // Every attribute that the user writes on a const is applied to the |
826 | // corresponding const that we generate, but within the implementation of |
827 | // Debug and all() we want to ignore everything but #[cfg] attributes. In |
828 | // particular, including a #[deprecated] attribute on those items would fail |
829 | // to compile. |
830 | // https://github.com/bitflags/bitflags/issues/109 |
831 | // |
832 | // Input: |
833 | // |
834 | // ? #[cfg(feature = "advanced")] |
835 | // ? #[deprecated(note = "Use something else.")] |
836 | // ? #[doc = r"High quality documentation."] |
837 | // fn f() -> i32 { /* ... */ } |
838 | // |
839 | // Output: |
840 | // |
841 | // #[cfg(feature = "advanced")] |
842 | // fn f() -> i32 { /* ... */ } |
843 | ( |
844 | $(#[$filtered:meta])* |
845 | ? #[cfg $($cfgargs:tt)*] |
846 | $(? #[$rest:ident $($restargs:tt)*])* |
847 | fn $($item:tt)* |
848 | ) => { |
849 | __impl_bitflags! { |
850 | $(#[$filtered])* |
851 | #[cfg $($cfgargs)*] |
852 | $(? #[$rest $($restargs)*])* |
853 | fn $($item)* |
854 | } |
855 | }; |
856 | ( |
857 | $(#[$filtered:meta])* |
858 | // $next != `cfg` |
859 | ? #[$next:ident $($nextargs:tt)*] |
860 | $(? #[$rest:ident $($restargs:tt)*])* |
861 | fn $($item:tt)* |
862 | ) => { |
863 | __impl_bitflags! { |
864 | $(#[$filtered])* |
865 | // $next filtered out |
866 | $(? #[$rest $($restargs)*])* |
867 | fn $($item)* |
868 | } |
869 | }; |
870 | ( |
871 | $(#[$filtered:meta])* |
872 | fn $($item:tt)* |
873 | ) => { |
874 | $(#[$filtered])* |
875 | fn $($item)* |
876 | }; |
877 | |
878 | // Every attribute that the user writes on a const is applied to the |
879 | // corresponding const that we generate, but within the implementation of |
880 | // Debug and all() we want to ignore everything but #[cfg] attributes. In |
881 | // particular, including a #[deprecated] attribute on those items would fail |
882 | // to compile. |
883 | // https://github.com/bitflags/bitflags/issues/109 |
884 | // |
885 | // const version |
886 | // |
887 | // Input: |
888 | // |
889 | // ? #[cfg(feature = "advanced")] |
890 | // ? #[deprecated(note = "Use something else.")] |
891 | // ? #[doc = r"High quality documentation."] |
892 | // const f: i32 { /* ... */ } |
893 | // |
894 | // Output: |
895 | // |
896 | // #[cfg(feature = "advanced")] |
897 | // const f: i32 { /* ... */ } |
898 | ( |
899 | $(#[$filtered:meta])* |
900 | ? #[cfg $($cfgargs:tt)*] |
901 | $(? #[$rest:ident $($restargs:tt)*])* |
902 | const $($item:tt)* |
903 | ) => { |
904 | __impl_bitflags! { |
905 | $(#[$filtered])* |
906 | #[cfg $($cfgargs)*] |
907 | $(? #[$rest $($restargs)*])* |
908 | const $($item)* |
909 | } |
910 | }; |
911 | ( |
912 | $(#[$filtered:meta])* |
913 | // $next != `cfg` |
914 | ? #[$next:ident $($nextargs:tt)*] |
915 | $(? #[$rest:ident $($restargs:tt)*])* |
916 | const $($item:tt)* |
917 | ) => { |
918 | __impl_bitflags! { |
919 | $(#[$filtered])* |
920 | // $next filtered out |
921 | $(? #[$rest $($restargs)*])* |
922 | const $($item)* |
923 | } |
924 | }; |
925 | ( |
926 | $(#[$filtered:meta])* |
927 | const $($item:tt)* |
928 | ) => { |
929 | $(#[$filtered])* |
930 | const $($item)* |
931 | }; |
932 | } |
933 | |
934 | #[cfg (feature = "example_generated" )] |
935 | pub mod example_generated; |
936 | |
937 | #[cfg (test)] |
938 | mod tests { |
939 | use std::collections::hash_map::DefaultHasher; |
940 | use std::hash::{Hash, Hasher}; |
941 | |
942 | bitflags! { |
943 | #[doc = "> The first principle is that you must not fool yourself — and" ] |
944 | #[doc = "> you are the easiest person to fool." ] |
945 | #[doc = "> " ] |
946 | #[doc = "> - Richard Feynman" ] |
947 | #[derive (Default)] |
948 | struct Flags: u32 { |
949 | const A = 0b00000001; |
950 | #[doc = "<pcwalton> macros are way better at generating code than trans is" ] |
951 | const B = 0b00000010; |
952 | const C = 0b00000100; |
953 | #[doc = "* cmr bed" ] |
954 | #[doc = "* strcat table" ] |
955 | #[doc = "<strcat> wait what?" ] |
956 | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
957 | } |
958 | |
959 | struct _CfgFlags: u32 { |
960 | #[cfg(unix)] |
961 | const _CFG_A = 0b01; |
962 | #[cfg(windows)] |
963 | const _CFG_B = 0b01; |
964 | #[cfg(unix)] |
965 | const _CFG_C = Self::_CFG_A.bits | 0b10; |
966 | } |
967 | |
968 | struct AnotherSetOfFlags: i8 { |
969 | const ANOTHER_FLAG = -1_i8; |
970 | } |
971 | |
972 | struct LongFlags: u32 { |
973 | const LONG_A = 0b1111111111111111; |
974 | } |
975 | } |
976 | |
977 | bitflags! { |
978 | struct EmptyFlags: u32 { |
979 | } |
980 | } |
981 | |
982 | #[test ] |
983 | fn test_bits() { |
984 | assert_eq!(Flags::empty().bits(), 0b00000000); |
985 | assert_eq!(Flags::A.bits(), 0b00000001); |
986 | assert_eq!(Flags::ABC.bits(), 0b00000111); |
987 | |
988 | assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); |
989 | assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8); |
990 | |
991 | assert_eq!(EmptyFlags::empty().bits(), 0b00000000); |
992 | } |
993 | |
994 | #[test ] |
995 | fn test_from_bits() { |
996 | assert_eq!(Flags::from_bits(0), Some(Flags::empty())); |
997 | assert_eq!(Flags::from_bits(0b1), Some(Flags::A)); |
998 | assert_eq!(Flags::from_bits(0b10), Some(Flags::B)); |
999 | assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B)); |
1000 | assert_eq!(Flags::from_bits(0b1000), None); |
1001 | |
1002 | assert_eq!( |
1003 | AnotherSetOfFlags::from_bits(!0_i8), |
1004 | Some(AnotherSetOfFlags::ANOTHER_FLAG) |
1005 | ); |
1006 | |
1007 | assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty())); |
1008 | assert_eq!(EmptyFlags::from_bits(0b1), None); |
1009 | } |
1010 | |
1011 | #[test ] |
1012 | fn test_from_bits_truncate() { |
1013 | assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); |
1014 | assert_eq!(Flags::from_bits_truncate(0b1), Flags::A); |
1015 | assert_eq!(Flags::from_bits_truncate(0b10), Flags::B); |
1016 | assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B)); |
1017 | assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); |
1018 | assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A); |
1019 | |
1020 | assert_eq!( |
1021 | AnotherSetOfFlags::from_bits_truncate(0_i8), |
1022 | AnotherSetOfFlags::empty() |
1023 | ); |
1024 | |
1025 | assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty()); |
1026 | assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty()); |
1027 | } |
1028 | |
1029 | #[test ] |
1030 | fn test_from_bits_unchecked() { |
1031 | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1032 | assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty()); |
1033 | assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A); |
1034 | assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B); |
1035 | |
1036 | assert_eq!( |
1037 | unsafe { Flags::from_bits_unchecked(0b11) }, |
1038 | (Flags::A | Flags::B) |
1039 | ); |
1040 | assert_eq!( |
1041 | unsafe { Flags::from_bits_unchecked(0b1000) }, |
1042 | (extra | Flags::empty()) |
1043 | ); |
1044 | assert_eq!( |
1045 | unsafe { Flags::from_bits_unchecked(0b1001) }, |
1046 | (extra | Flags::A) |
1047 | ); |
1048 | |
1049 | let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) }; |
1050 | assert_eq!( |
1051 | unsafe { EmptyFlags::from_bits_unchecked(0b1000) }, |
1052 | (extra | EmptyFlags::empty()) |
1053 | ); |
1054 | } |
1055 | |
1056 | #[test ] |
1057 | fn test_is_empty() { |
1058 | assert!(Flags::empty().is_empty()); |
1059 | assert!(!Flags::A.is_empty()); |
1060 | assert!(!Flags::ABC.is_empty()); |
1061 | |
1062 | assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty()); |
1063 | |
1064 | assert!(EmptyFlags::empty().is_empty()); |
1065 | assert!(EmptyFlags::all().is_empty()); |
1066 | } |
1067 | |
1068 | #[test ] |
1069 | fn test_is_all() { |
1070 | assert!(Flags::all().is_all()); |
1071 | assert!(!Flags::A.is_all()); |
1072 | assert!(Flags::ABC.is_all()); |
1073 | |
1074 | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1075 | assert!(!extra.is_all()); |
1076 | assert!(!(Flags::A | extra).is_all()); |
1077 | assert!((Flags::ABC | extra).is_all()); |
1078 | |
1079 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all()); |
1080 | |
1081 | assert!(EmptyFlags::all().is_all()); |
1082 | assert!(EmptyFlags::empty().is_all()); |
1083 | } |
1084 | |
1085 | #[test ] |
1086 | fn test_two_empties_do_not_intersect() { |
1087 | let e1 = Flags::empty(); |
1088 | let e2 = Flags::empty(); |
1089 | assert!(!e1.intersects(e2)); |
1090 | |
1091 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG)); |
1092 | } |
1093 | |
1094 | #[test ] |
1095 | fn test_empty_does_not_intersect_with_full() { |
1096 | let e1 = Flags::empty(); |
1097 | let e2 = Flags::ABC; |
1098 | assert!(!e1.intersects(e2)); |
1099 | } |
1100 | |
1101 | #[test ] |
1102 | fn test_disjoint_intersects() { |
1103 | let e1 = Flags::A; |
1104 | let e2 = Flags::B; |
1105 | assert!(!e1.intersects(e2)); |
1106 | } |
1107 | |
1108 | #[test ] |
1109 | fn test_overlapping_intersects() { |
1110 | let e1 = Flags::A; |
1111 | let e2 = Flags::A | Flags::B; |
1112 | assert!(e1.intersects(e2)); |
1113 | } |
1114 | |
1115 | #[test ] |
1116 | fn test_contains() { |
1117 | let e1 = Flags::A; |
1118 | let e2 = Flags::A | Flags::B; |
1119 | assert!(!e1.contains(e2)); |
1120 | assert!(e2.contains(e1)); |
1121 | assert!(Flags::ABC.contains(e2)); |
1122 | |
1123 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG)); |
1124 | |
1125 | assert!(EmptyFlags::empty().contains(EmptyFlags::empty())); |
1126 | } |
1127 | |
1128 | #[test ] |
1129 | fn test_insert() { |
1130 | let mut e1 = Flags::A; |
1131 | let e2 = Flags::A | Flags::B; |
1132 | e1.insert(e2); |
1133 | assert_eq!(e1, e2); |
1134 | |
1135 | let mut e3 = AnotherSetOfFlags::empty(); |
1136 | e3.insert(AnotherSetOfFlags::ANOTHER_FLAG); |
1137 | assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG); |
1138 | } |
1139 | |
1140 | #[test ] |
1141 | fn test_remove() { |
1142 | let mut e1 = Flags::A | Flags::B; |
1143 | let e2 = Flags::A | Flags::C; |
1144 | e1.remove(e2); |
1145 | assert_eq!(e1, Flags::B); |
1146 | |
1147 | let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG; |
1148 | e3.remove(AnotherSetOfFlags::ANOTHER_FLAG); |
1149 | assert_eq!(e3, AnotherSetOfFlags::empty()); |
1150 | } |
1151 | |
1152 | #[test ] |
1153 | fn test_operators() { |
1154 | let e1 = Flags::A | Flags::C; |
1155 | let e2 = Flags::B | Flags::C; |
1156 | assert_eq!((e1 | e2), Flags::ABC); // union |
1157 | assert_eq!((e1 & e2), Flags::C); // intersection |
1158 | assert_eq!((e1 - e2), Flags::A); // set difference |
1159 | assert_eq!(!e2, Flags::A); // set complement |
1160 | assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle |
1161 | let mut e3 = e1; |
1162 | e3.toggle(e2); |
1163 | assert_eq!(e3, Flags::A | Flags::B); |
1164 | |
1165 | let mut m4 = AnotherSetOfFlags::empty(); |
1166 | m4.toggle(AnotherSetOfFlags::empty()); |
1167 | assert_eq!(m4, AnotherSetOfFlags::empty()); |
1168 | } |
1169 | |
1170 | #[test ] |
1171 | fn test_operators_unchecked() { |
1172 | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1173 | let e1 = Flags::A | Flags::C | extra; |
1174 | let e2 = Flags::B | Flags::C; |
1175 | assert_eq!((e1 | e2), (Flags::ABC | extra)); // union |
1176 | assert_eq!((e1 & e2), Flags::C); // intersection |
1177 | assert_eq!((e1 - e2), (Flags::A | extra)); // set difference |
1178 | assert_eq!(!e2, Flags::A); // set complement |
1179 | assert_eq!(!e1, Flags::B); // set complement |
1180 | assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle |
1181 | let mut e3 = e1; |
1182 | e3.toggle(e2); |
1183 | assert_eq!(e3, Flags::A | Flags::B | extra); |
1184 | } |
1185 | |
1186 | #[test ] |
1187 | fn test_set_ops_basic() { |
1188 | let ab = Flags::A.union(Flags::B); |
1189 | let ac = Flags::A.union(Flags::C); |
1190 | let bc = Flags::B.union(Flags::C); |
1191 | assert_eq!(ab.bits, 0b011); |
1192 | assert_eq!(bc.bits, 0b110); |
1193 | assert_eq!(ac.bits, 0b101); |
1194 | |
1195 | assert_eq!(ab, Flags::B.union(Flags::A)); |
1196 | assert_eq!(ac, Flags::C.union(Flags::A)); |
1197 | assert_eq!(bc, Flags::C.union(Flags::B)); |
1198 | |
1199 | assert_eq!(ac, Flags::A | Flags::C); |
1200 | assert_eq!(bc, Flags::B | Flags::C); |
1201 | assert_eq!(ab.union(bc), Flags::ABC); |
1202 | |
1203 | assert_eq!(ac, Flags::A | Flags::C); |
1204 | assert_eq!(bc, Flags::B | Flags::C); |
1205 | |
1206 | assert_eq!(ac.union(bc), ac | bc); |
1207 | assert_eq!(ac.union(bc), Flags::ABC); |
1208 | assert_eq!(bc.union(ac), Flags::ABC); |
1209 | |
1210 | assert_eq!(ac.intersection(bc), ac & bc); |
1211 | assert_eq!(ac.intersection(bc), Flags::C); |
1212 | assert_eq!(bc.intersection(ac), Flags::C); |
1213 | |
1214 | assert_eq!(ac.difference(bc), ac - bc); |
1215 | assert_eq!(bc.difference(ac), bc - ac); |
1216 | assert_eq!(ac.difference(bc), Flags::A); |
1217 | assert_eq!(bc.difference(ac), Flags::B); |
1218 | |
1219 | assert_eq!(bc.complement(), !bc); |
1220 | assert_eq!(bc.complement(), Flags::A); |
1221 | assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B)); |
1222 | assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B)); |
1223 | } |
1224 | |
1225 | #[test ] |
1226 | fn test_set_ops_const() { |
1227 | // These just test that these compile and don't cause use-site panics |
1228 | // (would be possible if we had some sort of UB) |
1229 | const INTERSECT: Flags = Flags::all().intersection(Flags::C); |
1230 | const UNION: Flags = Flags::A.union(Flags::C); |
1231 | const DIFFERENCE: Flags = Flags::all().difference(Flags::A); |
1232 | const COMPLEMENT: Flags = Flags::C.complement(); |
1233 | const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE); |
1234 | assert_eq!(INTERSECT, Flags::C); |
1235 | assert_eq!(UNION, Flags::A | Flags::C); |
1236 | assert_eq!(DIFFERENCE, Flags::all() - Flags::A); |
1237 | assert_eq!(COMPLEMENT, !Flags::C); |
1238 | assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A)); |
1239 | } |
1240 | |
1241 | #[test ] |
1242 | fn test_set_ops_unchecked() { |
1243 | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1244 | let e1 = Flags::A.union(Flags::C).union(extra); |
1245 | let e2 = Flags::B.union(Flags::C); |
1246 | assert_eq!(e1.bits, 0b1101); |
1247 | assert_eq!(e1.union(e2), (Flags::ABC | extra)); |
1248 | assert_eq!(e1.intersection(e2), Flags::C); |
1249 | assert_eq!(e1.difference(e2), Flags::A | extra); |
1250 | assert_eq!(e2.difference(e1), Flags::B); |
1251 | assert_eq!(e2.complement(), Flags::A); |
1252 | assert_eq!(e1.complement(), Flags::B); |
1253 | assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle |
1254 | } |
1255 | |
1256 | #[test ] |
1257 | fn test_set_ops_exhaustive() { |
1258 | // Define a flag that contains gaps to help exercise edge-cases, |
1259 | // especially around "unknown" flags (e.g. ones outside of `all()` |
1260 | // `from_bits_unchecked`). |
1261 | // - when lhs and rhs both have different sets of unknown flags. |
1262 | // - unknown flags at both ends, and in the middle |
1263 | // - cases with "gaps". |
1264 | bitflags! { |
1265 | struct Test: u16 { |
1266 | // Intentionally no `A` |
1267 | const B = 0b000000010; |
1268 | // Intentionally no `C` |
1269 | const D = 0b000001000; |
1270 | const E = 0b000010000; |
1271 | const F = 0b000100000; |
1272 | const G = 0b001000000; |
1273 | // Intentionally no `H` |
1274 | const I = 0b100000000; |
1275 | } |
1276 | } |
1277 | let iter_test_flags = |
1278 | || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) }); |
1279 | |
1280 | for a in iter_test_flags() { |
1281 | assert_eq!( |
1282 | a.complement(), |
1283 | Test::from_bits_truncate(!a.bits), |
1284 | "wrong result: !( {:?})" , |
1285 | a, |
1286 | ); |
1287 | assert_eq!(a.complement(), !a, "named != op: !( {:?})" , a); |
1288 | for b in iter_test_flags() { |
1289 | // Check that the named operations produce the expected bitwise |
1290 | // values. |
1291 | assert_eq!( |
1292 | a.union(b).bits, |
1293 | a.bits | b.bits, |
1294 | "wrong result: ` {:?}` | ` {:?}`" , |
1295 | a, |
1296 | b, |
1297 | ); |
1298 | assert_eq!( |
1299 | a.intersection(b).bits, |
1300 | a.bits & b.bits, |
1301 | "wrong result: ` {:?}` & ` {:?}`" , |
1302 | a, |
1303 | b, |
1304 | ); |
1305 | assert_eq!( |
1306 | a.symmetric_difference(b).bits, |
1307 | a.bits ^ b.bits, |
1308 | "wrong result: ` {:?}` ^ ` {:?}`" , |
1309 | a, |
1310 | b, |
1311 | ); |
1312 | assert_eq!( |
1313 | a.difference(b).bits, |
1314 | a.bits & !b.bits, |
1315 | "wrong result: ` {:?}` - ` {:?}`" , |
1316 | a, |
1317 | b, |
1318 | ); |
1319 | // Note: Difference is checked as both `a - b` and `b - a` |
1320 | assert_eq!( |
1321 | b.difference(a).bits, |
1322 | b.bits & !a.bits, |
1323 | "wrong result: ` {:?}` - ` {:?}`" , |
1324 | b, |
1325 | a, |
1326 | ); |
1327 | // Check that the named set operations are equivalent to the |
1328 | // bitwise equivalents |
1329 | assert_eq!(a.union(b), a | b, "named != op: ` {:?}` | ` {:?}`" , a, b,); |
1330 | assert_eq!( |
1331 | a.intersection(b), |
1332 | a & b, |
1333 | "named != op: ` {:?}` & ` {:?}`" , |
1334 | a, |
1335 | b, |
1336 | ); |
1337 | assert_eq!( |
1338 | a.symmetric_difference(b), |
1339 | a ^ b, |
1340 | "named != op: ` {:?}` ^ ` {:?}`" , |
1341 | a, |
1342 | b, |
1343 | ); |
1344 | assert_eq!(a.difference(b), a - b, "named != op: ` {:?}` - ` {:?}`" , a, b,); |
1345 | // Note: Difference is checked as both `a - b` and `b - a` |
1346 | assert_eq!(b.difference(a), b - a, "named != op: ` {:?}` - ` {:?}`" , b, a,); |
1347 | // Verify that the operations which should be symmetric are |
1348 | // actually symmetric. |
1349 | assert_eq!(a.union(b), b.union(a), "asymmetry: ` {:?}` | ` {:?}`" , a, b,); |
1350 | assert_eq!( |
1351 | a.intersection(b), |
1352 | b.intersection(a), |
1353 | "asymmetry: ` {:?}` & ` {:?}`" , |
1354 | a, |
1355 | b, |
1356 | ); |
1357 | assert_eq!( |
1358 | a.symmetric_difference(b), |
1359 | b.symmetric_difference(a), |
1360 | "asymmetry: ` {:?}` ^ ` {:?}`" , |
1361 | a, |
1362 | b, |
1363 | ); |
1364 | } |
1365 | } |
1366 | } |
1367 | |
1368 | #[test ] |
1369 | fn test_set() { |
1370 | let mut e1 = Flags::A | Flags::C; |
1371 | e1.set(Flags::B, true); |
1372 | e1.set(Flags::C, false); |
1373 | |
1374 | assert_eq!(e1, Flags::A | Flags::B); |
1375 | } |
1376 | |
1377 | #[test ] |
1378 | fn test_assignment_operators() { |
1379 | let mut m1 = Flags::empty(); |
1380 | let e1 = Flags::A | Flags::C; |
1381 | // union |
1382 | m1 |= Flags::A; |
1383 | assert_eq!(m1, Flags::A); |
1384 | // intersection |
1385 | m1 &= e1; |
1386 | assert_eq!(m1, Flags::A); |
1387 | // set difference |
1388 | m1 -= m1; |
1389 | assert_eq!(m1, Flags::empty()); |
1390 | // toggle |
1391 | m1 ^= e1; |
1392 | assert_eq!(m1, e1); |
1393 | } |
1394 | |
1395 | #[test ] |
1396 | fn test_const_fn() { |
1397 | const _M1: Flags = Flags::empty(); |
1398 | |
1399 | const M2: Flags = Flags::A; |
1400 | assert_eq!(M2, Flags::A); |
1401 | |
1402 | const M3: Flags = Flags::C; |
1403 | assert_eq!(M3, Flags::C); |
1404 | } |
1405 | |
1406 | #[test ] |
1407 | fn test_extend() { |
1408 | let mut flags; |
1409 | |
1410 | flags = Flags::empty(); |
1411 | flags.extend([].iter().cloned()); |
1412 | assert_eq!(flags, Flags::empty()); |
1413 | |
1414 | flags = Flags::empty(); |
1415 | flags.extend([Flags::A, Flags::B].iter().cloned()); |
1416 | assert_eq!(flags, Flags::A | Flags::B); |
1417 | |
1418 | flags = Flags::A; |
1419 | flags.extend([Flags::A, Flags::B].iter().cloned()); |
1420 | assert_eq!(flags, Flags::A | Flags::B); |
1421 | |
1422 | flags = Flags::B; |
1423 | flags.extend([Flags::A, Flags::ABC].iter().cloned()); |
1424 | assert_eq!(flags, Flags::ABC); |
1425 | } |
1426 | |
1427 | #[test ] |
1428 | fn test_from_iterator() { |
1429 | assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty()); |
1430 | assert_eq!( |
1431 | [Flags::A, Flags::B].iter().cloned().collect::<Flags>(), |
1432 | Flags::A | Flags::B |
1433 | ); |
1434 | assert_eq!( |
1435 | [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(), |
1436 | Flags::ABC |
1437 | ); |
1438 | } |
1439 | |
1440 | #[test ] |
1441 | fn test_lt() { |
1442 | let mut a = Flags::empty(); |
1443 | let mut b = Flags::empty(); |
1444 | |
1445 | assert!(!(a < b) && !(b < a)); |
1446 | b = Flags::B; |
1447 | assert!(a < b); |
1448 | a = Flags::C; |
1449 | assert!(!(a < b) && b < a); |
1450 | b = Flags::C | Flags::B; |
1451 | assert!(a < b); |
1452 | } |
1453 | |
1454 | #[test ] |
1455 | fn test_ord() { |
1456 | let mut a = Flags::empty(); |
1457 | let mut b = Flags::empty(); |
1458 | |
1459 | assert!(a <= b && a >= b); |
1460 | a = Flags::A; |
1461 | assert!(a > b && a >= b); |
1462 | assert!(b < a && b <= a); |
1463 | b = Flags::B; |
1464 | assert!(b > a && b >= a); |
1465 | assert!(a < b && a <= b); |
1466 | } |
1467 | |
1468 | fn hash<T: Hash>(t: &T) -> u64 { |
1469 | let mut s = DefaultHasher::new(); |
1470 | t.hash(&mut s); |
1471 | s.finish() |
1472 | } |
1473 | |
1474 | #[test ] |
1475 | fn test_hash() { |
1476 | let mut x = Flags::empty(); |
1477 | let mut y = Flags::empty(); |
1478 | assert_eq!(hash(&x), hash(&y)); |
1479 | x = Flags::all(); |
1480 | y = Flags::ABC; |
1481 | assert_eq!(hash(&x), hash(&y)); |
1482 | } |
1483 | |
1484 | #[test ] |
1485 | fn test_default() { |
1486 | assert_eq!(Flags::empty(), Flags::default()); |
1487 | } |
1488 | |
1489 | #[test ] |
1490 | fn test_debug() { |
1491 | assert_eq!(format!("{:?}" , Flags::A | Flags::B), "A | B" ); |
1492 | assert_eq!(format!("{:?}" , Flags::empty()), "(empty)" ); |
1493 | assert_eq!(format!("{:?}" , Flags::ABC), "A | B | C | ABC" ); |
1494 | let extra = unsafe { Flags::from_bits_unchecked(0xb8) }; |
1495 | assert_eq!(format!("{:?}" , extra), "0xb8" ); |
1496 | assert_eq!(format!("{:?}" , Flags::A | extra), "A | 0xb8" ); |
1497 | |
1498 | assert_eq!( |
1499 | format!("{:?}" , Flags::ABC | extra), |
1500 | "A | B | C | ABC | 0xb8" |
1501 | ); |
1502 | |
1503 | assert_eq!(format!("{:?}" , EmptyFlags::empty()), "(empty)" ); |
1504 | } |
1505 | |
1506 | #[test ] |
1507 | fn test_binary() { |
1508 | assert_eq!(format!("{:b}" , Flags::ABC), "111" ); |
1509 | assert_eq!(format!("{:#b}" , Flags::ABC), "0b111" ); |
1510 | let extra = unsafe { Flags::from_bits_unchecked(0b1010000) }; |
1511 | assert_eq!(format!("{:b}" , Flags::ABC | extra), "1010111" ); |
1512 | assert_eq!(format!("{:#b}" , Flags::ABC | extra), "0b1010111" ); |
1513 | } |
1514 | |
1515 | #[test ] |
1516 | fn test_octal() { |
1517 | assert_eq!(format!("{:o}" , LongFlags::LONG_A), "177777" ); |
1518 | assert_eq!(format!("{:#o}" , LongFlags::LONG_A), "0o177777" ); |
1519 | let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) }; |
1520 | assert_eq!(format!("{:o}" , LongFlags::LONG_A | extra), "5177777" ); |
1521 | assert_eq!(format!("{:#o}" , LongFlags::LONG_A | extra), "0o5177777" ); |
1522 | } |
1523 | |
1524 | #[test ] |
1525 | fn test_lowerhex() { |
1526 | assert_eq!(format!("{:x}" , LongFlags::LONG_A), "ffff" ); |
1527 | assert_eq!(format!("{:#x}" , LongFlags::LONG_A), "0xffff" ); |
1528 | let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; |
1529 | assert_eq!(format!("{:x}" , LongFlags::LONG_A | extra), "e0ffff" ); |
1530 | assert_eq!(format!("{:#x}" , LongFlags::LONG_A | extra), "0xe0ffff" ); |
1531 | } |
1532 | |
1533 | #[test ] |
1534 | fn test_upperhex() { |
1535 | assert_eq!(format!("{:X}" , LongFlags::LONG_A), "FFFF" ); |
1536 | assert_eq!(format!("{:#X}" , LongFlags::LONG_A), "0xFFFF" ); |
1537 | let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; |
1538 | assert_eq!(format!("{:X}" , LongFlags::LONG_A | extra), "E0FFFF" ); |
1539 | assert_eq!(format!("{:#X}" , LongFlags::LONG_A | extra), "0xE0FFFF" ); |
1540 | } |
1541 | |
1542 | mod submodule { |
1543 | bitflags! { |
1544 | pub struct PublicFlags: i8 { |
1545 | const X = 0; |
1546 | } |
1547 | |
1548 | struct PrivateFlags: i8 { |
1549 | const Y = 0; |
1550 | } |
1551 | } |
1552 | |
1553 | #[test ] |
1554 | fn test_private() { |
1555 | let _ = PrivateFlags::Y; |
1556 | } |
1557 | } |
1558 | |
1559 | #[test ] |
1560 | fn test_public() { |
1561 | let _ = submodule::PublicFlags::X; |
1562 | } |
1563 | |
1564 | mod t1 { |
1565 | mod foo { |
1566 | pub type Bar = i32; |
1567 | } |
1568 | |
1569 | bitflags! { |
1570 | /// baz |
1571 | struct Flags: foo::Bar { |
1572 | const A = 0b00000001; |
1573 | #[cfg(foo)] |
1574 | const B = 0b00000010; |
1575 | #[cfg(foo)] |
1576 | const C = 0b00000010; |
1577 | } |
1578 | } |
1579 | } |
1580 | |
1581 | #[test ] |
1582 | fn test_in_function() { |
1583 | bitflags! { |
1584 | struct Flags: u8 { |
1585 | const A = 1; |
1586 | #[cfg(any())] // false |
1587 | const B = 2; |
1588 | } |
1589 | } |
1590 | assert_eq!(Flags::all(), Flags::A); |
1591 | assert_eq!(format!("{:?}" , Flags::A), "A" ); |
1592 | } |
1593 | |
1594 | #[test ] |
1595 | fn test_deprecated() { |
1596 | bitflags! { |
1597 | pub struct TestFlags: u32 { |
1598 | #[deprecated(note = "Use something else." )] |
1599 | const ONE = 1; |
1600 | } |
1601 | } |
1602 | } |
1603 | |
1604 | #[test ] |
1605 | fn test_pub_crate() { |
1606 | mod module { |
1607 | bitflags! { |
1608 | pub (crate) struct Test: u8 { |
1609 | const FOO = 1; |
1610 | } |
1611 | } |
1612 | } |
1613 | |
1614 | assert_eq!(module::Test::FOO.bits(), 1); |
1615 | } |
1616 | |
1617 | #[test ] |
1618 | fn test_pub_in_module() { |
1619 | mod module { |
1620 | mod submodule { |
1621 | bitflags! { |
1622 | // `pub (in super)` means only the module `module` will |
1623 | // be able to access this. |
1624 | pub (in super) struct Test: u8 { |
1625 | const FOO = 1; |
1626 | } |
1627 | } |
1628 | } |
1629 | |
1630 | mod test { |
1631 | // Note: due to `pub (in super)`, |
1632 | // this cannot be accessed directly by the testing code. |
1633 | pub(super) fn value() -> u8 { |
1634 | super::submodule::Test::FOO.bits() |
1635 | } |
1636 | } |
1637 | |
1638 | pub fn value() -> u8 { |
1639 | test::value() |
1640 | } |
1641 | } |
1642 | |
1643 | assert_eq!(module::value(), 1) |
1644 | } |
1645 | |
1646 | #[test ] |
1647 | fn test_zero_value_flags() { |
1648 | bitflags! { |
1649 | struct Flags: u32 { |
1650 | const NONE = 0b0; |
1651 | const SOME = 0b1; |
1652 | } |
1653 | } |
1654 | |
1655 | assert!(Flags::empty().contains(Flags::NONE)); |
1656 | assert!(Flags::SOME.contains(Flags::NONE)); |
1657 | assert!(Flags::NONE.is_empty()); |
1658 | |
1659 | assert_eq!(format!("{:?}" , Flags::empty()), "NONE" ); |
1660 | assert_eq!(format!("{:?}" , Flags::SOME), "SOME" ); |
1661 | } |
1662 | |
1663 | #[test ] |
1664 | fn test_empty_bitflags() { |
1665 | bitflags! {} |
1666 | } |
1667 | |
1668 | #[test ] |
1669 | fn test_u128_bitflags() { |
1670 | bitflags! { |
1671 | struct Flags128: u128 { |
1672 | const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; |
1673 | const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; |
1674 | const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; |
1675 | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
1676 | } |
1677 | } |
1678 | |
1679 | assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C); |
1680 | assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); |
1681 | assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); |
1682 | assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); |
1683 | assert_eq!( |
1684 | Flags128::ABC.bits, |
1685 | 0x8000_0000_0000_1000_0000_0000_0000_0001 |
1686 | ); |
1687 | assert_eq!(format!("{:?}" , Flags128::A), "A" ); |
1688 | assert_eq!(format!("{:?}" , Flags128::B), "B" ); |
1689 | assert_eq!(format!("{:?}" , Flags128::C), "C" ); |
1690 | assert_eq!(format!("{:?}" , Flags128::ABC), "A | B | C | ABC" ); |
1691 | } |
1692 | |
1693 | #[test ] |
1694 | fn test_serde_bitflags_serialize() { |
1695 | let flags = SerdeFlags::A | SerdeFlags::B; |
1696 | |
1697 | let serialized = serde_json::to_string(&flags).unwrap(); |
1698 | |
1699 | assert_eq!(serialized, r#"{"bits":3}"# ); |
1700 | } |
1701 | |
1702 | #[test ] |
1703 | fn test_serde_bitflags_deserialize() { |
1704 | let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"# ).unwrap(); |
1705 | |
1706 | let expected = SerdeFlags::C | SerdeFlags::D; |
1707 | |
1708 | assert_eq!(deserialized.bits, expected.bits); |
1709 | } |
1710 | |
1711 | #[test ] |
1712 | fn test_serde_bitflags_roundtrip() { |
1713 | let flags = SerdeFlags::A | SerdeFlags::B; |
1714 | |
1715 | let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap(); |
1716 | |
1717 | assert_eq!(deserialized.bits, flags.bits); |
1718 | } |
1719 | |
1720 | bitflags! { |
1721 | #[derive (serde::Serialize, serde::Deserialize)] |
1722 | struct SerdeFlags: u32 { |
1723 | const A = 1; |
1724 | const B = 2; |
1725 | const C = 4; |
1726 | const D = 8; |
1727 | } |
1728 | } |
1729 | } |
1730 | |