@@ -587,121 +587,6 @@ macro_rules! bitflags {
587587 ( ) => { } ;
588588}
589589
590- /// bitflags match patterns similar to Rust's match expression
591- ///
592- /// This macro allows for matching bitflag combinations in a way that resembles
593- /// Rust's native match expression, but works correctly with bitflag operations.
594- ///
595- /// # Requirements
596- ///
597- /// - The struct used with this macro must implement `PartialEq`.
598- /// - It's recommended to use this macro with structs created by the `bitflags!` macro.
599- ///
600- /// # Syntax
601- ///
602- /// ```ignore
603- /// bitflags_match!(expression, {
604- /// pattern1 => result1,
605- /// pattern2 => result2,
606- /// ...
607- /// _ => default_result
608- /// })
609- /// ```
610- ///
611- /// The final `_ => default_result` arm is required, otherwise the macro will fail to compile.
612- ///
613- /// # Examples
614- ///
615- /// ```rust
616- /// use bitflags::{bitflags, bitflags_match};
617- ///
618- /// bitflags! {
619- /// #[derive(PartialEq)]
620- /// struct Flags: u8 {
621- /// const A = 1 << 0;
622- /// const B = 1 << 1;
623- /// const C = 1 << 2;
624- /// }
625- /// }
626- ///
627- /// let flags = Flags::A | Flags::B;
628- ///
629- /// bitflags_match!(flags, {
630- /// Flags::A => println!("A"),
631- /// Flags::B => { println!("B"); }
632- /// Flags::C => println!("C"),
633- /// Flags::A | Flags::B => {
634- /// print!("A");
635- /// print!(" | ");
636- /// print!("B");
637- /// },
638- /// Flags::A | Flags::C => { println!("A | C") },
639- /// Flags::B | Flags::C => println!("B | C"),
640- /// Flags::A | Flags::B | Flags::C => println!("A | B | C"),
641- /// _ => println!("other")
642- /// })
643- /// ```
644- ///
645- /// # How it works
646- ///
647- /// The macro expands to a series of if(pattern){ return result; } statements,
648- /// checking equality between the input expression and each pattern. This allows for
649- /// correct matching of bitflag combinations, which is not possible with a regular
650- /// match expression due to the way bitflags are implemented.
651- ///
652- /// # Note
653- ///
654- /// The order of patterns matters. The first matching pattern will be executed,
655- /// so more specific patterns should come before more general ones.
656- #[ macro_export]
657- macro_rules! bitflags_match {
658- ( $operation: expr, {
659- $( $t: tt) *
660- } ) => {
661- // Expand to a closure so we can use `return`
662- // This makes it possible to apply attributes to the "match arms"
663- ( || {
664- $crate:: __bitflags_match!( $operation, { $( $t) * } )
665- } ) ( )
666- } ;
667- }
668-
669- /// Expand the `bitflags_match` macro
670- #[ macro_export]
671- #[ doc( hidden) ]
672- macro_rules! __bitflags_match {
673- // Eat an optional `,` following a block match arm
674- ( $operation: expr, { $pattern: expr => { $( $body: tt) * } , $( $t: tt) + } ) => {
675- $crate:: __bitflags_match!( $operation, { $pattern => { $( $body) * } $( $t) + } )
676- } ;
677- // Expand a block match arm `A => { .. }`
678- ( $operation: expr, { $pattern: expr => { $( $body: tt) * } $( $t: tt) + } ) => {
679- {
680- if $operation == $pattern {
681- return {
682- $( $body) *
683- } ;
684- }
685-
686- $crate:: __bitflags_match!( $operation, { $( $t) + } )
687- }
688- } ;
689- // Expand an expression match arm `A => x,`
690- ( $operation: expr, { $pattern: expr => $body: expr , $( $t: tt) + } ) => {
691- {
692- if $operation == $pattern {
693- return $body;
694- }
695-
696- $crate:: __bitflags_match!( $operation, { $( $t) + } )
697- }
698- } ;
699- // Expand the default case
700- ( $operation: expr, { _ => $default: expr $( , ) ? } ) => {
701- $default
702- }
703- }
704-
705590/// Implement functions on bitflags types.
706591///
707592/// We need to be careful about adding new methods and trait implementations here because they
@@ -907,6 +792,104 @@ macro_rules! __impl_bitflags {
907792 } ;
908793}
909794
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+
910893/// A macro that processed the input to `bitflags!` and shuffles attributes around
911894/// based on whether or not they're "expression-safe".
912895///
0 commit comments