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 /*! 12 Generate types for C-style flags with ergonomic APIs. 13 14 # Getting started 15 16 Add `bitflags` to your `Cargo.toml`: 17 18 ```toml 19 [dependencies.bitflags] 20 version = "2.9.0" 21 ``` 22 23 ## Generating flags types 24 25 Use the [`bitflags`] macro to generate flags types: 26 27 ```rust 28 use bitflags::bitflags; 29 30 bitflags! { 31 pub struct Flags: u32 { 32 const A = 0b00000001; 33 const B = 0b00000010; 34 const C = 0b00000100; 35 } 36 } 37 ``` 38 39 See the docs for the `bitflags` macro for the full syntax. 40 41 Also see the [`example_generated`](./example_generated/index.html) module for an example of what the `bitflags` macro generates for a flags type. 42 43 ### Externally defined flags 44 45 If you're generating flags types for an external source, such as a C API, you can define 46 an extra unnamed flag as a mask of all bits the external source may ever set. Usually this would be all bits (`!0`): 47 48 ```rust 49 # use bitflags::bitflags; 50 bitflags! { 51 pub struct Flags: u32 { 52 const A = 0b00000001; 53 const B = 0b00000010; 54 const C = 0b00000100; 55 56 // The source may set any bits 57 const _ = !0; 58 } 59 } 60 ``` 61 62 Why should you do this? Generated methods like `all` and truncating operators like `!` only consider 63 bits in defined flags. Adding an unnamed flag makes those methods consider additional bits, 64 without generating additional constants for them. It helps compatibility when the external source 65 may start setting additional bits at any time. The [known and unknown bits](#known-and-unknown-bits) 66 section has more details on this behavior. 67 68 ### Custom derives 69 70 You can derive some traits on generated flags types if you enable Cargo features. The following 71 libraries are currently supported: 72 73 - `serde`: Support `#[derive(Serialize, Deserialize)]`, using text for human-readable formats, 74 and a raw number for binary formats. 75 - `arbitrary`: Support `#[derive(Arbitrary)]`, only generating flags values with known bits. 76 - `bytemuck`: Support `#[derive(Pod, Zeroable)]`, for casting between flags values and their 77 underlying bits values. 78 79 You can also define your own flags type outside of the [`bitflags`] macro and then use it to generate methods. 80 This can be useful if you need a custom `#[derive]` attribute for a library that `bitflags` doesn't 81 natively support: 82 83 ```rust 84 # use std::fmt::Debug as SomeTrait; 85 # use bitflags::bitflags; 86 #[derive(SomeTrait)] 87 pub struct Flags(u32); 88 89 bitflags! { 90 impl Flags: u32 { 91 const A = 0b00000001; 92 const B = 0b00000010; 93 const C = 0b00000100; 94 } 95 } 96 ``` 97 98 ### Adding custom methods 99 100 The [`bitflags`] macro supports attributes on generated flags types within the macro itself, while 101 `impl` blocks can be added outside of it: 102 103 ```rust 104 # use bitflags::bitflags; 105 bitflags! { 106 // Attributes can be applied to flags types 107 #[repr(transparent)] 108 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 109 pub struct Flags: u32 { 110 const A = 0b00000001; 111 const B = 0b00000010; 112 const C = 0b00000100; 113 } 114 } 115 116 // Impl blocks can be added to flags types 117 impl Flags { 118 pub fn as_u64(&self) -> u64 { 119 self.bits() as u64 120 } 121 } 122 ``` 123 124 ## Working with flags values 125 126 Use generated constants and standard bitwise operators to interact with flags values: 127 128 ```rust 129 # use bitflags::bitflags; 130 # bitflags! { 131 # #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 132 # pub struct Flags: u32 { 133 # const A = 0b00000001; 134 # const B = 0b00000010; 135 # const C = 0b00000100; 136 # } 137 # } 138 // union 139 let ab = Flags::A | Flags::B; 140 141 // intersection 142 let a = ab & Flags::A; 143 144 // difference 145 let b = ab - Flags::A; 146 147 // complement 148 let c = !ab; 149 ``` 150 151 See the docs for the [`Flags`] trait for more details on operators and how they behave. 152 153 # Formatting and parsing 154 155 `bitflags` defines a text format that can be used to convert any flags value to and from strings. 156 157 See the [`parser`] module for more details. 158 159 # Specification 160 161 The terminology and behavior of generated flags types is 162 [specified in the source repository](https://github.com/bitflags/bitflags/blob/main/spec.md). 163 Details are repeated in these docs where appropriate, but is exhaustively listed in the spec. Some 164 things are worth calling out explicitly here. 165 166 ## Flags types, flags values, flags 167 168 The spec and these docs use consistent terminology to refer to things in the bitflags domain: 169 170 - **Bits type**: A type that defines a fixed number of bits at specific locations. 171 - **Flag**: A set of bits in a bits type that may have a unique name. 172 - **Flags type**: A set of defined flags over a specific bits type. 173 - **Flags value**: An instance of a flags type using its specific bits value for storage. 174 175 ``` 176 # use bitflags::bitflags; 177 bitflags! { 178 struct FlagsType: u8 { 179 // -- Bits type 180 // --------- Flags type 181 const A = 1; 182 // ----- Flag 183 } 184 } 185 186 let flag = FlagsType::A; 187 // ---- Flags value 188 ``` 189 190 ## Known and unknown bits 191 192 Any bits in a flag you define are called _known bits_. Any other bits are _unknown bits_. 193 In the following flags type: 194 195 ``` 196 # use bitflags::bitflags; 197 bitflags! { 198 struct Flags: u8 { 199 const A = 1; 200 const B = 1 << 1; 201 const C = 1 << 2; 202 } 203 } 204 ``` 205 206 The known bits are `0b0000_0111` and the unknown bits are `0b1111_1000`. 207 208 `bitflags` doesn't guarantee that a flags value will only ever have known bits set, but some operators 209 will unset any unknown bits they encounter. In a future version of `bitflags`, all operators will 210 unset unknown bits. 211 212 If you're using `bitflags` for flags types defined externally, such as from C, you probably want all 213 bits to be considered known, in case that external source changes. You can do this using an unnamed 214 flag, as described in [externally defined flags](#externally-defined-flags). 215 216 ## Zero-bit flags 217 218 Flags with no bits set should be avoided because they interact strangely with [`Flags::contains`] 219 and [`Flags::intersects`]. A zero-bit flag is always contained, but is never intersected. The 220 names of zero-bit flags can be parsed, but are never formatted. 221 222 ## Multi-bit flags 223 224 Flags that set multiple bits should be avoided unless each bit is also in a single-bit flag. 225 Take the following flags type as an example: 226 227 ``` 228 # use bitflags::bitflags; 229 bitflags! { 230 struct Flags: u8 { 231 const A = 1; 232 const B = 1 | 1 << 1; 233 } 234 } 235 ``` 236 237 The result of `Flags::A ^ Flags::B` is `0b0000_0010`, which doesn't correspond to either 238 `Flags::A` or `Flags::B` even though it's still a known bit. 239 */ 240 241 #![cfg_attr(not(any(feature = "std", test)), no_std)] 242 #![cfg_attr(not(test), forbid(unsafe_code))] 243 #![cfg_attr(test, allow(mixed_script_confusables))] 244 245 #[doc(inline)] 246 pub use traits::{Bits, Flag, Flags}; 247 248 pub mod iter; 249 pub mod parser; 250 251 mod traits; 252 253 #[doc(hidden)] 254 pub mod __private { 255 #[allow(unused_imports)] 256 // Easier than conditionally checking any optional external dependencies 257 pub use crate::{external::__private::*, traits::__private::*}; 258 259 pub use core; 260 } 261 262 #[allow(unused_imports)] 263 pub use external::*; 264 265 #[allow(deprecated)] 266 pub use traits::BitFlags; 267 268 /* 269 How does the bitflags crate work? 270 271 This library generates a `struct` in the end-user's crate with a bunch of constants on it that represent flags. 272 The difference between `bitflags` and a lot of other libraries is that we don't actually control the generated `struct` in the end. 273 It's part of the end-user's crate, so it belongs to them. That makes it difficult to extend `bitflags` with new functionality 274 because we could end up breaking valid code that was already written. 275 276 Our solution is to split the type we generate into two: the public struct owned by the end-user, and an internal struct owned by `bitflags` (us). 277 To give you an example, let's say we had a crate that called `bitflags!`: 278 279 ```rust 280 bitflags! { 281 pub struct MyFlags: u32 { 282 const A = 1; 283 const B = 2; 284 } 285 } 286 ``` 287 288 What they'd end up with looks something like this: 289 290 ```rust 291 pub struct MyFlags(<MyFlags as PublicFlags>::InternalBitFlags); 292 293 const _: () = { 294 #[repr(transparent)] 295 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 296 pub struct MyInternalBitFlags { 297 bits: u32, 298 } 299 300 impl PublicFlags for MyFlags { 301 type Internal = InternalBitFlags; 302 } 303 }; 304 ``` 305 306 If we want to expose something like a new trait impl for generated flags types, we add it to our generated `MyInternalBitFlags`, 307 and let `#[derive]` on `MyFlags` pick up that implementation, if an end-user chooses to add one. 308 309 The public API is generated in the `__impl_public_flags!` macro, and the internal API is generated in 310 the `__impl_internal_flags!` macro. 311 312 The macros are split into 3 modules: 313 314 - `public`: where the user-facing flags types are generated. 315 - `internal`: where the `bitflags`-facing flags types are generated. 316 - `external`: where external library traits are implemented conditionally. 317 */ 318 319 /** 320 Generate a flags type. 321 322 # `struct` mode 323 324 A declaration that begins with `$vis struct` will generate a `struct` for a flags type, along with 325 methods and trait implementations for it. The body of the declaration defines flags as constants, 326 where each constant is a flags value of the generated flags type. 327 328 ## Examples 329 330 Generate a flags type using `u8` as the bits type: 331 332 ``` 333 # use bitflags::bitflags; 334 bitflags! { 335 struct Flags: u8 { 336 const A = 1; 337 const B = 1 << 1; 338 const C = 0b0000_0100; 339 } 340 } 341 ``` 342 343 Flags types are private by default and accept standard visibility modifiers. Flags themselves 344 are always public: 345 346 ``` 347 # use bitflags::bitflags; 348 bitflags! { 349 pub struct Flags: u8 { 350 // Constants are always `pub` 351 const A = 1; 352 } 353 } 354 ``` 355 356 Flags may refer to other flags using their [`Flags::bits`] value: 357 358 ``` 359 # use bitflags::bitflags; 360 bitflags! { 361 struct Flags: u8 { 362 const A = 1; 363 const B = 1 << 1; 364 const AB = Flags::A.bits() | Flags::B.bits(); 365 } 366 } 367 ``` 368 369 A single `bitflags` invocation may include zero or more flags type declarations: 370 371 ``` 372 # use bitflags::bitflags; 373 bitflags! {} 374 375 bitflags! { 376 struct Flags1: u8 { 377 const A = 1; 378 } 379 380 struct Flags2: u8 { 381 const A = 1; 382 } 383 } 384 ``` 385 386 # `impl` mode 387 388 A declaration that begins with `impl` will only generate methods and trait implementations for the 389 `struct` defined outside of the `bitflags` macro. 390 391 The struct itself must be a newtype using the bits type as its field. 392 393 The syntax for `impl` mode is identical to `struct` mode besides the starting token. 394 395 ## Examples 396 397 Implement flags methods and traits for a custom flags type using `u8` as its underlying bits type: 398 399 ``` 400 # use bitflags::bitflags; 401 struct Flags(u8); 402 403 bitflags! { 404 impl Flags: u8 { 405 const A = 1; 406 const B = 1 << 1; 407 const C = 0b0000_0100; 408 } 409 } 410 ``` 411 412 # Named and unnamed flags 413 414 Constants in the body of a declaration are flags. The identifier of the constant is the name of 415 the flag. If the identifier is `_`, then the flag is unnamed. Unnamed flags don't appear in the 416 generated API, but affect how bits are truncated. 417 418 ## Examples 419 420 Adding an unnamed flag that makes all bits known: 421 422 ``` 423 # use bitflags::bitflags; 424 bitflags! { 425 struct Flags: u8 { 426 const A = 1; 427 const B = 1 << 1; 428 429 const _ = !0; 430 } 431 } 432 ``` 433 434 Flags types may define multiple unnamed flags: 435 436 ``` 437 # use bitflags::bitflags; 438 bitflags! { 439 struct Flags: u8 { 440 const _ = 1; 441 const _ = 1 << 1; 442 } 443 } 444 ``` 445 */ 446 #[macro_export] 447 macro_rules! bitflags { 448 ( 449 $(#[$outer:meta])* 450 $vis:vis struct $BitFlags:ident: $T:ty { 451 $( 452 $(#[$inner:ident $($args:tt)*])* 453 const $Flag:tt = $value:expr; 454 )* 455 } 456 457 $($t:tt)* 458 ) => { 459 // Declared in the scope of the `bitflags!` call 460 // This type appears in the end-user's API 461 $crate::__declare_public_bitflags! { 462 $(#[$outer])* 463 $vis struct $BitFlags 464 } 465 466 // Workaround for: https://github.com/bitflags/bitflags/issues/320 467 $crate::__impl_public_bitflags_consts! { 468 $BitFlags: $T { 469 $( 470 $(#[$inner $($args)*])* 471 const $Flag = $value; 472 )* 473 } 474 } 475 476 #[allow( 477 dead_code, 478 deprecated, 479 unused_doc_comments, 480 unused_attributes, 481 unused_mut, 482 unused_imports, 483 non_upper_case_globals, 484 clippy::assign_op_pattern, 485 clippy::indexing_slicing, 486 clippy::same_name_method, 487 clippy::iter_without_into_iter, 488 )] 489 const _: () = { 490 // Declared in a "hidden" scope that can't be reached directly 491 // These types don't appear in the end-user's API 492 $crate::__declare_internal_bitflags! { 493 $vis struct InternalBitFlags: $T 494 } 495 496 $crate::__impl_internal_bitflags! { 497 InternalBitFlags: $T, $BitFlags { 498 $( 499 $(#[$inner $($args)*])* 500 const $Flag = $value; 501 )* 502 } 503 } 504 505 // This is where new library trait implementations can be added 506 $crate::__impl_external_bitflags! { 507 InternalBitFlags: $T, $BitFlags { 508 $( 509 $(#[$inner $($args)*])* 510 const $Flag; 511 )* 512 } 513 } 514 515 $crate::__impl_public_bitflags_forward! { 516 $BitFlags: $T, InternalBitFlags 517 } 518 519 $crate::__impl_public_bitflags_ops! { 520 $BitFlags 521 } 522 523 $crate::__impl_public_bitflags_iter! { 524 $BitFlags: $T, $BitFlags 525 } 526 }; 527 528 $crate::bitflags! { 529 $($t)* 530 } 531 }; 532 ( 533 $(#[$outer:meta])* 534 impl $BitFlags:ident: $T:ty { 535 $( 536 $(#[$inner:ident $($args:tt)*])* 537 const $Flag:tt = $value:expr; 538 )* 539 } 540 541 $($t:tt)* 542 ) => { 543 $crate::__impl_public_bitflags_consts! { 544 $BitFlags: $T { 545 $( 546 $(#[$inner $($args)*])* 547 const $Flag = $value; 548 )* 549 } 550 } 551 552 #[allow( 553 dead_code, 554 deprecated, 555 unused_doc_comments, 556 unused_attributes, 557 unused_mut, 558 unused_imports, 559 non_upper_case_globals, 560 clippy::assign_op_pattern, 561 clippy::iter_without_into_iter, 562 )] 563 const _: () = { 564 $crate::__impl_public_bitflags! { 565 $(#[$outer])* 566 $BitFlags: $T, $BitFlags { 567 $( 568 $(#[$inner $($args)*])* 569 const $Flag = $value; 570 )* 571 } 572 } 573 574 $crate::__impl_public_bitflags_ops! { 575 $BitFlags 576 } 577 578 $crate::__impl_public_bitflags_iter! { 579 $BitFlags: $T, $BitFlags 580 } 581 }; 582 583 $crate::bitflags! { 584 $($t)* 585 } 586 }; 587 () => {}; 588 } 589 590 /// Implement functions on bitflags types. 591 /// 592 /// We need to be careful about adding new methods and trait implementations here because they 593 /// could conflict with items added by the end-user. 594 #[macro_export] 595 #[doc(hidden)] 596 macro_rules! __impl_bitflags { 597 ( 598 $(#[$outer:meta])* 599 $PublicBitFlags:ident: $T:ty { 600 fn empty() $empty:block 601 fn all() $all:block 602 fn bits($bits0:ident) $bits:block 603 fn from_bits($from_bits0:ident) $from_bits:block 604 fn from_bits_truncate($from_bits_truncate0:ident) $from_bits_truncate:block 605 fn from_bits_retain($from_bits_retain0:ident) $from_bits_retain:block 606 fn from_name($from_name0:ident) $from_name:block 607 fn is_empty($is_empty0:ident) $is_empty:block 608 fn is_all($is_all0:ident) $is_all:block 609 fn intersects($intersects0:ident, $intersects1:ident) $intersects:block 610 fn contains($contains0:ident, $contains1:ident) $contains:block 611 fn insert($insert0:ident, $insert1:ident) $insert:block 612 fn remove($remove0:ident, $remove1:ident) $remove:block 613 fn toggle($toggle0:ident, $toggle1:ident) $toggle:block 614 fn set($set0:ident, $set1:ident, $set2:ident) $set:block 615 fn intersection($intersection0:ident, $intersection1:ident) $intersection:block 616 fn union($union0:ident, $union1:ident) $union:block 617 fn difference($difference0:ident, $difference1:ident) $difference:block 618 fn symmetric_difference($symmetric_difference0:ident, $symmetric_difference1:ident) $symmetric_difference:block 619 fn complement($complement0:ident) $complement:block 620 } 621 ) => { 622 #[allow(dead_code, deprecated, unused_attributes)] 623 $(#[$outer])* 624 impl $PublicBitFlags { 625 /// Get a flags value with all bits unset. 626 #[inline] 627 pub const fn empty() -> Self { 628 $empty 629 } 630 631 /// Get a flags value with all known bits set. 632 #[inline] 633 pub const fn all() -> Self { 634 $all 635 } 636 637 /// Get the underlying bits value. 638 /// 639 /// The returned value is exactly the bits set in this flags value. 640 #[inline] 641 pub const fn bits(&self) -> $T { 642 let $bits0 = self; 643 $bits 644 } 645 646 /// Convert from a bits value. 647 /// 648 /// This method will return `None` if any unknown bits are set. 649 #[inline] 650 pub const fn from_bits(bits: $T) -> $crate::__private::core::option::Option<Self> { 651 let $from_bits0 = bits; 652 $from_bits 653 } 654 655 /// Convert from a bits value, unsetting any unknown bits. 656 #[inline] 657 pub const fn from_bits_truncate(bits: $T) -> Self { 658 let $from_bits_truncate0 = bits; 659 $from_bits_truncate 660 } 661 662 /// Convert from a bits value exactly. 663 #[inline] 664 pub const fn from_bits_retain(bits: $T) -> Self { 665 let $from_bits_retain0 = bits; 666 $from_bits_retain 667 } 668 669 /// Get a flags value with the bits of a flag with the given name set. 670 /// 671 /// This method will return `None` if `name` is empty or doesn't 672 /// correspond to any named flag. 673 #[inline] 674 pub fn from_name(name: &str) -> $crate::__private::core::option::Option<Self> { 675 let $from_name0 = name; 676 $from_name 677 } 678 679 /// Whether all bits in this flags value are unset. 680 #[inline] 681 pub const fn is_empty(&self) -> bool { 682 let $is_empty0 = self; 683 $is_empty 684 } 685 686 /// Whether all known bits in this flags value are set. 687 #[inline] 688 pub const fn is_all(&self) -> bool { 689 let $is_all0 = self; 690 $is_all 691 } 692 693 /// Whether any set bits in a source flags value are also set in a target flags value. 694 #[inline] 695 pub const fn intersects(&self, other: Self) -> bool { 696 let $intersects0 = self; 697 let $intersects1 = other; 698 $intersects 699 } 700 701 /// Whether all set bits in a source flags value are also set in a target flags value. 702 #[inline] 703 pub const fn contains(&self, other: Self) -> bool { 704 let $contains0 = self; 705 let $contains1 = other; 706 $contains 707 } 708 709 /// The bitwise or (`|`) of the bits in two flags values. 710 #[inline] 711 pub fn insert(&mut self, other: Self) { 712 let $insert0 = self; 713 let $insert1 = other; 714 $insert 715 } 716 717 /// The intersection of a source flags value with the complement of a target flags value (`&!`). 718 /// 719 /// This method is not equivalent to `self & !other` when `other` has unknown bits set. 720 /// `remove` won't truncate `other`, but the `!` operator will. 721 #[inline] 722 pub fn remove(&mut self, other: Self) { 723 let $remove0 = self; 724 let $remove1 = other; 725 $remove 726 } 727 728 /// The bitwise exclusive-or (`^`) of the bits in two flags values. 729 #[inline] 730 pub fn toggle(&mut self, other: Self) { 731 let $toggle0 = self; 732 let $toggle1 = other; 733 $toggle 734 } 735 736 /// Call `insert` when `value` is `true` or `remove` when `value` is `false`. 737 #[inline] 738 pub fn set(&mut self, other: Self, value: bool) { 739 let $set0 = self; 740 let $set1 = other; 741 let $set2 = value; 742 $set 743 } 744 745 /// The bitwise and (`&`) of the bits in two flags values. 746 #[inline] 747 #[must_use] 748 pub const fn intersection(self, other: Self) -> Self { 749 let $intersection0 = self; 750 let $intersection1 = other; 751 $intersection 752 } 753 754 /// The bitwise or (`|`) of the bits in two flags values. 755 #[inline] 756 #[must_use] 757 pub const fn union(self, other: Self) -> Self { 758 let $union0 = self; 759 let $union1 = other; 760 $union 761 } 762 763 /// The intersection of a source flags value with the complement of a target flags value (`&!`). 764 /// 765 /// This method is not equivalent to `self & !other` when `other` has unknown bits set. 766 /// `difference` won't truncate `other`, but the `!` operator will. 767 #[inline] 768 #[must_use] 769 pub const fn difference(self, other: Self) -> Self { 770 let $difference0 = self; 771 let $difference1 = other; 772 $difference 773 } 774 775 /// The bitwise exclusive-or (`^`) of the bits in two flags values. 776 #[inline] 777 #[must_use] 778 pub const fn symmetric_difference(self, other: Self) -> Self { 779 let $symmetric_difference0 = self; 780 let $symmetric_difference1 = other; 781 $symmetric_difference 782 } 783 784 /// The bitwise negation (`!`) of the bits in a flags value, truncating the result. 785 #[inline] 786 #[must_use] 787 pub const fn complement(self) -> Self { 788 let $complement0 = self; 789 $complement 790 } 791 } 792 }; 793 } 794 795 /// A macro that matches flags values, similar to Rust's `match` statement. 796 /// 797 /// In a regular `match` statement, the syntax `Flag::A | Flag::B` is interpreted as an or-pattern, 798 /// instead of the bitwise-or of `Flag::A` and `Flag::B`. This can be surprising when combined with flags types 799 /// because `Flag::A | Flag::B` won't match the pattern `Flag::A | Flag::B`. This macro is an alternative to 800 /// `match` for flags values that doesn't have this issue. 801 /// 802 /// # Syntax 803 /// 804 /// ```ignore 805 /// bitflags_match!(expression, { 806 /// pattern1 => result1, 807 /// pattern2 => result2, 808 /// .. 809 /// _ => default_result, 810 /// }) 811 /// ``` 812 /// 813 /// The final `_ => default_result` arm is required, otherwise the macro will fail to compile. 814 /// 815 /// # Examples 816 /// 817 /// ```rust 818 /// use bitflags::{bitflags, bitflags_match}; 819 /// 820 /// bitflags! { 821 /// #[derive(PartialEq)] 822 /// struct Flags: u8 { 823 /// const A = 1 << 0; 824 /// const B = 1 << 1; 825 /// const C = 1 << 2; 826 /// } 827 /// } 828 /// 829 /// let flags = Flags::A | Flags::B; 830 /// 831 /// bitflags_match!(flags, { 832 /// Flags::A | Flags::B => println!("A and/or B are set"), 833 /// _ => println!("neither A nor B are set"), 834 /// }) 835 /// ``` 836 /// 837 /// # How it works 838 /// 839 /// The macro expands to a series of `if` statements, checking equality between the input expression 840 /// and each pattern. This allows for correct matching of bitflag combinations, which is not possible 841 /// with a regular match expression due to the way bitflags are implemented. 842 /// 843 /// Patterns are evaluated in order. 844 #[macro_export] 845 macro_rules! bitflags_match { 846 ($operation:expr, { 847 $($t:tt)* 848 }) => { 849 // Expand to a closure so we can use `return` 850 // This makes it possible to apply attributes to the "match arms" 851 (|| { 852 $crate::__bitflags_match!($operation, { $($t)* }) 853 })() 854 }; 855 } 856 857 /// Expand the `bitflags_match` macro 858 #[macro_export] 859 #[doc(hidden)] 860 macro_rules! __bitflags_match { 861 // Eat an optional `,` following a block match arm 862 ($operation:expr, { $pattern:expr => { $($body:tt)* } , $($t:tt)+ }) => { 863 $crate::__bitflags_match!($operation, { $pattern => { $($body)* } $($t)+ }) 864 }; 865 // Expand a block match arm `A => { .. }` 866 ($operation:expr, { $pattern:expr => { $($body:tt)* } $($t:tt)+ }) => { 867 { 868 if $operation == $pattern { 869 return { 870 $($body)* 871 }; 872 } 873 874 $crate::__bitflags_match!($operation, { $($t)+ }) 875 } 876 }; 877 // Expand an expression match arm `A => x,` 878 ($operation:expr, { $pattern:expr => $body:expr , $($t:tt)+ }) => { 879 { 880 if $operation == $pattern { 881 return $body; 882 } 883 884 $crate::__bitflags_match!($operation, { $($t)+ }) 885 } 886 }; 887 // Expand the default case 888 ($operation:expr, { _ => $default:expr $(,)? }) => { 889 $default 890 } 891 } 892 893 /// A macro that processed the input to `bitflags!` and shuffles attributes around 894 /// based on whether or not they're "expression-safe". 895 /// 896 /// This macro is a token-tree muncher that works on 2 levels: 897 /// 898 /// For each attribute, we explicitly match on its identifier, like `cfg` to determine 899 /// whether or not it should be considered expression-safe. 900 /// 901 /// If you find yourself with an attribute that should be considered expression-safe 902 /// and isn't, it can be added here. 903 #[macro_export] 904 #[doc(hidden)] 905 macro_rules! __bitflags_expr_safe_attrs { 906 // Entrypoint: Move all flags and all attributes into `unprocessed` lists 907 // where they'll be munched one-at-a-time 908 ( 909 $(#[$inner:ident $($args:tt)*])* 910 { $e:expr } 911 ) => { 912 $crate::__bitflags_expr_safe_attrs! { 913 expr: { $e }, 914 attrs: { 915 // All attributes start here 916 unprocessed: [$(#[$inner $($args)*])*], 917 // Attributes that are safe on expressions go here 918 processed: [], 919 }, 920 } 921 }; 922 // Process the next attribute on the current flag 923 // `cfg`: The next flag should be propagated to expressions 924 // NOTE: You can copy this rules block and replace `cfg` with 925 // your attribute name that should be considered expression-safe 926 ( 927 expr: { $e:expr }, 928 attrs: { 929 unprocessed: [ 930 // cfg matched here 931 #[cfg $($args:tt)*] 932 $($attrs_rest:tt)* 933 ], 934 processed: [$($expr:tt)*], 935 }, 936 ) => { 937 $crate::__bitflags_expr_safe_attrs! { 938 expr: { $e }, 939 attrs: { 940 unprocessed: [ 941 $($attrs_rest)* 942 ], 943 processed: [ 944 $($expr)* 945 // cfg added here 946 #[cfg $($args)*] 947 ], 948 }, 949 } 950 }; 951 // Process the next attribute on the current flag 952 // `$other`: The next flag should not be propagated to expressions 953 ( 954 expr: { $e:expr }, 955 attrs: { 956 unprocessed: [ 957 // $other matched here 958 #[$other:ident $($args:tt)*] 959 $($attrs_rest:tt)* 960 ], 961 processed: [$($expr:tt)*], 962 }, 963 ) => { 964 $crate::__bitflags_expr_safe_attrs! { 965 expr: { $e }, 966 attrs: { 967 unprocessed: [ 968 $($attrs_rest)* 969 ], 970 processed: [ 971 // $other not added here 972 $($expr)* 973 ], 974 }, 975 } 976 }; 977 // Once all attributes on all flags are processed, generate the actual code 978 ( 979 expr: { $e:expr }, 980 attrs: { 981 unprocessed: [], 982 processed: [$(#[$expr:ident $($exprargs:tt)*])*], 983 }, 984 ) => { 985 $(#[$expr $($exprargs)*])* 986 { $e } 987 } 988 } 989 990 /// Implement a flag, which may be a wildcard `_`. 991 #[macro_export] 992 #[doc(hidden)] 993 macro_rules! __bitflags_flag { 994 ( 995 { 996 name: _, 997 named: { $($named:tt)* }, 998 unnamed: { $($unnamed:tt)* }, 999 } 1000 ) => { 1001 $($unnamed)* 1002 }; 1003 ( 1004 { 1005 name: $Flag:ident, 1006 named: { $($named:tt)* }, 1007 unnamed: { $($unnamed:tt)* }, 1008 } 1009 ) => { 1010 $($named)* 1011 }; 1012 } 1013 1014 #[macro_use] 1015 mod public; 1016 #[macro_use] 1017 mod internal; 1018 #[macro_use] 1019 mod external; 1020 1021 #[cfg(feature = "example_generated")] 1022 pub mod example_generated; 1023 1024 #[cfg(test)] 1025 mod tests; 1026