Skip to main content

bitflags_lite/
macros.rs

1/// Defines a flag set from a compact declaration.
2///
3/// The macro generates a [`BitFlagsSpec`] implementation for a tag type,
4/// along with named constants for individual bits and combined masks.
5///
6/// This is a convenience wrapper around the manual [`BitFlagsSpec`]
7/// implementation.
8/// The expansion is small and inspectable.
9/// Running `cargo expand` shows code that matches what you would write by hand.
10///
11/// The macro does not generate a type alias for the flag set. Type aliases
12/// are trivial to write in ordinary Rust, and generating one would create a
13/// naming asymmetry: the flag set would have a name but the individual flag
14/// would not. Write the aliases you need next to the macro invocation:
15///
16/// ```
17/// use bitflags_lite::{BitFlag, BitFlags};
18/// bitflags_lite::bitflags! {
19///     #![storage(u32)]
20///     pub struct PermissionsTag;
21///     // ...
22/// }
23/// pub type Permissions = BitFlags<u32, PermissionsTag>;
24/// pub type Permission = BitFlag<u32, PermissionsTag>;
25/// ```
26///
27/// # Syntax
28///
29/// ```text
30/// bitflags! {
31///     // Storage type. Required.
32///     #![storage( STORAGE )]
33///
34///     // Optional default name matcher.
35///     $( #![name_matcher( EXPR )] )?
36///
37///     // Tag declaration. The `VIS struct` prefix is optional.
38///     $( $( #[$ATTR] )* VIS struct )? TAG;
39///
40///     // Bit declarations. The name and the name slice are optional.
41///     $( #[$ATTR] )* VIS bit NAME = INDEX, &[NAMES];
42///     $( #[$ATTR] )* VIS bit NAME = INDEX;
43///     $( #[$ATTR] )* VIS bit      = INDEX;
44///
45///     // Mask declarations. The display name is optional.
46///     $( #[$ATTR] )* VIS mask NAME = [ A, B, C ], "NAME";
47///     $( #[$ATTR] )* VIS mask NAME = EXPR, "NAME";
48/// }
49/// ```
50///
51/// where:
52///
53/// - `STORAGE` is a primitive integer type such as `u32`. It is required.
54/// - `VIS` is an optional visibility modifier such as `pub` or `pub(crate)`.
55/// - `TAG` is the tag type name. Writing `VIS struct TAG;` generates the tag
56///   with standard derives. Writing just `TAG;` reuses an existing one.
57/// - `INDEX` is the zero-based bit index.
58/// - `&[NAMES]` is a slice of one or more names for the bit. The first is used
59///   by [`Display`](core::fmt::Display). All are accepted when parsing.
60/// - `bit NAME = INDEX;` declares a bit that has a named constant but no
61///   display name.
62/// - `bit = INDEX;` declares a valid bit with no constant and no name. It
63///   contributes to [`VALID_BITS_MASK`] but not to [`FLAG_NAMES`].
64/// - `[ A, B, C ]` computes a union of named bit constants into a multi-bit
65///   value. The special syntax is required because the macro runs in const
66///   context, where `BitFlag` does not implement `BitOr` in a way that can be
67///   folded into a raw integer.
68/// - `EXPR` is a bit-mask expression, for example `0` or
69///   `FIRST.mask_or_default() | SECOND.mask_or_default()`.
70/// - `#![name_matcher(...)]` sets [`BitFlagsSpec::DEFAULT_NAME_MATCHER`] and
71///   defaults to [`NameMatcher::Exact`].
72/// - `ATTR` is any outer attribute, including doc comments. Attributes are
73///   copied to the generated item.
74///
75/// Indices that are not declared are invalid. They are excluded from
76/// [`VALID_BITS_MASK`] and cleared by truncating operations.
77///
78/// # Tag declaration
79///
80/// The tag line may be written in two ways:
81///
82/// ```rust,ignore
83/// // Reuse an existing tag type.
84/// bitflags! {
85///     #![storage(u32)]
86///     SomeTag;
87///     // ...
88/// }
89///
90/// // Generate the tag type.
91/// bitflags! {
92///     #![storage(u32)]
93///     pub struct SomeTag;
94///     // ...
95/// }
96/// ```
97///
98/// Attributes on the tag declaration are copied to the generated struct.
99///
100/// # Generated items
101///
102/// The macro emits `impl BitFlagsSpec<STORAGE> for TAG`, plus one `const` per
103/// named `bit` or `mask`.
104/// The tag struct is emitted only when requested.
105/// Attributes written on a declaration are copied to the corresponding
106/// generated item.
107///
108/// The generated code is approximately equivalent to the following pattern:
109///
110/// ```rust,ignore
111/// // Tag struct, if requested.
112/// #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, Debug)]
113/// pub struct TAG;
114///
115/// // Spec implementation for the tag.
116/// impl BitFlagsSpec<STORAGE> for TAG {
117///     const VALID_BITS_MASK: STORAGE = ...;
118///     const FLAG_NAMES: &[&[&str]] = ...;
119///     const COMBINED_NAMES: &[(STORAGE, &str)] = ...;
120///     const DEFAULT_NAME_MATCHER: NameMatcher = ...;
121/// }
122///
123/// // Bit constant, one per named `bit`.
124/// pub const NAME: BitFlag<STORAGE, TAG> =
125///     BitFlag::<STORAGE, TAG>::from_bit_retain(INDEX);
126///
127/// // Mask constant, one per named `mask`.
128/// pub const NAME: BitFlags<STORAGE, TAG> =
129///     BitFlags::<STORAGE, TAG>::from_bits_retain(VALUE);
130/// ```
131///
132/// `FLAG_NAMES` is sized to the highest declared bit index.
133/// Gaps are filled with empty slices, so unnamed and undeclared indices
134/// coexist.
135///
136/// # Examples
137///
138/// Simple example with three consequent bits in bit flags.
139///
140/// ```rust
141/// use bitflags_lite::{BitFlagsSpec, NameMatcher};
142///
143/// bitflags_lite::bitflags! {
144///     #![storage(u32)]
145///
146///     pub struct PermissionsTag;
147///
148///     pub bit READ  = 0, &["read"];
149///     pub bit WRITE = 1, &["write"];
150///     pub bit EXEC  = 2, &["exec", "execute"];
151///
152///     pub mask RWX  = [ READ, WRITE, EXEC ], "all";
153///     pub mask NONE = 0, "none";
154/// }
155///
156/// assert_eq!(PermissionsTag::VALID_BITS_MASK, 0b111);
157/// assert_eq!(
158///     PermissionsTag::FLAG_NAMES,
159///     &[&["read"][..], &["write"], &["exec", "execute"]]
160/// );
161/// assert_eq!(
162///     PermissionsTag::COMBINED_NAMES,
163///     &[(0b111, "all"), (0, "none")]
164/// );
165/// assert_eq!(PermissionsTag::DEFAULT_NAME_MATCHER, NameMatcher::Exact);
166///
167/// assert_eq!(READ.bit(), 0);
168/// assert_eq!(WRITE.bit(), 1);
169/// assert_eq!(EXEC.bit(), 2);
170/// assert_eq!(RWX.bits(), 0b111);
171/// assert_eq!(NONE.bits(), 0);
172/// ```
173///
174/// <details>
175/// <summary>Macro expansion (click to show)</summary>
176///
177/// ```rust
178/// use bitflags_lite::{BitFlagsSpec, NameMatcher};
179///
180/// #[derive(
181///     ::core::marker::Copy,
182///     ::core::clone::Clone,
183///     ::core::cmp::Eq,
184///     ::core::cmp::PartialEq,
185///     ::core::cmp::Ord,
186///     ::core::cmp::PartialOrd,
187///     ::core::hash::Hash,
188///     ::core::default::Default,
189///     ::core::fmt::Debug,
190/// )]
191/// pub struct PermissionsTag;
192///
193/// impl bitflags_lite::BitFlagsSpec<u32> for PermissionsTag {
194///     const VALID_BITS_MASK: u32 =
195///         const { (0 as u32) | (1 as u32) << 0 | (1 as u32) << 1 | (1 as u32) << 2 };
196///     const FLAG_NAMES: &[&[&str]] = const {
197///         const MAX: usize = bitflags_lite::util::__const_max(&[0, 1, 2]);
198///         const FLAG_NAMES: [&'static [&'static str]; MAX + 1] = const {
199///             let mut flag_names: [&'static [&'static str]; MAX + 1] = [&[]; MAX + 1];
200///             flag_names[0] = (&["read"]);
201///             flag_names[1] = (&["write"]);
202///             flag_names[2] = (&["exec", "execute"]);
203///             flag_names
204///         };
205///         &FLAG_NAMES
206///     };
207///     const COMBINED_NAMES: &[(u32, &str)] = &[
208///         (
209///             (0 | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&READ)
210///                 | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&WRITE)
211///                 | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&EXEC)),
212///             "all",
213///         ),
214///         (0, "none"),
215///     ];
216///     const DEFAULT_NAME_MATCHER: bitflags_lite::NameMatcher =
217///         (bitflags_lite::NameMatcher::Exact);
218/// }
219///
220/// pub const READ: bitflags_lite::BitFlag<u32, PermissionsTag> =
221///     bitflags_lite::BitFlag::<u32, PermissionsTag>::from_bit_retain(0);
222///
223/// pub const WRITE: bitflags_lite::BitFlag<u32, PermissionsTag> =
224///     bitflags_lite::BitFlag::<u32, PermissionsTag>::from_bit_retain(1);
225///
226/// pub const EXEC: bitflags_lite::BitFlag<u32, PermissionsTag> =
227///     bitflags_lite::BitFlag::<u32, PermissionsTag>::from_bit_retain(2);
228///
229/// pub const RWX: bitflags_lite::BitFlags<u32, PermissionsTag> =
230///     bitflags_lite::BitFlags::<u32, PermissionsTag>::from_bits_retain(
231///         (0 | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&READ)
232///             | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&WRITE)
233///             | bitflags_lite::BitFlag::<u32, PermissionsTag>::mask_or_default(&EXEC)),
234///     );
235///
236/// pub const NONE: bitflags_lite::BitFlags<u32, PermissionsTag> =
237///     bitflags_lite::BitFlags::<u32, PermissionsTag>::from_bits_retain(0);
238/// ```
239///
240/// </details>
241///
242/// Example with invalid and unnamed but valid bits.
243///
244/// ```rust
245/// use bitflags_lite::{BitFlagsSpec, NameMatcher};
246///
247/// bitflags_lite::bitflags! {
248///     #![storage(u32)]
249///     #![name_matcher(NameMatcher::AsciiCaseInsensitive)]
250///
251///     /// Flags tag doc-comment.
252///     pub struct FlagsTag;
253///
254///     /// `FIRST` `BitFlag` doc-comment.
255///     pub bit FIRST = 0, &["first", "1st"];
256///
257///     /// `THIRD` `BitFlag` doc-comment.
258///     pub bit THIRD = 2, &["third", "3rd"];
259///
260///     pub bit       = 3;
261///
262///     /// `TENTH` `BitFlag` doc-comment.
263///     pub bit TENTH = 9, &["tenth", "10th"];
264///
265///     /// `ALL` `BitFlags` doc-comment.
266///     pub mask ALL     = [ FIRST, THIRD, TENTH ], "all";
267///
268///     /// `ALL_ALT` `BitFlags` doc-comment.
269///     pub mask ALL_ALT = FIRST.mask_or_default()
270///                      | THIRD.mask_or_default()
271///                      | TENTH.mask_or_default();
272///
273///     /// `NONE` `BitFlags` doc-comment.
274///     pub mask NONE    = 0, "none";
275/// }
276///
277/// assert_eq!(FlagsTag::VALID_BITS_MASK, 0b10_0000_1101);
278/// assert_eq!(
279///     FlagsTag::FLAG_NAMES,
280///     &[
281///         &["first", "1st"][..],
282///         &[],
283///         &["third", "3rd"],
284///         &[],
285///         &[],
286///         &[],
287///         &[],
288///         &[],
289///         &[],
290///         &["tenth", "10th"]
291///     ]
292/// );
293/// assert_eq!(
294///     FlagsTag::COMBINED_NAMES,
295///     &[(0b10_0000_0101, "all"), (0, "none")]
296/// );
297/// assert_eq!(
298///     FlagsTag::DEFAULT_NAME_MATCHER,
299///     NameMatcher::AsciiCaseInsensitive
300/// );
301///
302/// assert_eq!(FIRST.bit(), 0);
303/// assert_eq!(THIRD.bit(), 2);
304/// assert_eq!(TENTH.bit(), 9);
305/// assert_eq!(ALL.bits(), 0b10_0000_0101);
306/// assert_eq!(NONE.bits(), 0);
307/// ```
308///
309/// <details>
310/// <summary>Macro expansion (click to show)</summary>
311///
312/// ```rust
313/// use bitflags_lite::{BitFlagsSpec, NameMatcher};
314///
315/// #[doc = r" Flags tag doc-comment."]
316/// #[derive(
317///     ::core::marker::Copy,
318///     ::core::clone::Clone,
319///     ::core::cmp::Eq,
320///     ::core::cmp::PartialEq,
321///     ::core::cmp::Ord,
322///     ::core::cmp::PartialOrd,
323///     ::core::hash::Hash,
324///     ::core::default::Default,
325///     ::core::fmt::Debug,
326/// )]
327/// pub struct FlagsTag;
328///
329/// impl bitflags_lite::BitFlagsSpec<u32> for FlagsTag {
330///     const VALID_BITS_MASK: u32 = const {
331///         (0 as u32) | (1 as u32) << 0 | (1 as u32) << 2 | (1 as u32) << 3 | (1 as u32) << 9
332///     };
333///     const FLAG_NAMES: &[&[&str]] = const {
334///         const MAX: usize = bitflags_lite::util::__const_max(&[0, 2, 3, 9]);
335///         const FLAG_NAMES: [&'static [&'static str]; MAX + 1] = const {
336///             let mut flag_names: [&'static [&'static str]; MAX + 1] = [&[]; MAX + 1];
337///             flag_names[0] = (&["first", "1st"]);
338///             flag_names[2] = (&["third", "3rd"]);
339///             flag_names[9] = (&["tenth", "10th"]);
340///             flag_names
341///         };
342///         &FLAG_NAMES
343///     };
344///     const COMBINED_NAMES: &[(u32, &str)] = &[
345///         (
346///             (0 | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&FIRST)
347///                 | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&THIRD)
348///                 | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&TENTH)),
349///             "all",
350///         ),
351///         (0, "none"),
352///     ];
353///     const DEFAULT_NAME_MATCHER: bitflags_lite::NameMatcher =
354///         (NameMatcher::AsciiCaseInsensitive);
355/// }
356///
357/// #[doc = r" `FIRST` `BitFlag` doc-comment."]
358/// pub const FIRST: bitflags_lite::BitFlag<u32, FlagsTag> =
359///     bitflags_lite::BitFlag::<u32, FlagsTag>::from_bit_retain(0);
360///
361/// #[doc = r" `THIRD` `BitFlag` doc-comment."]
362/// pub const THIRD: bitflags_lite::BitFlag<u32, FlagsTag> =
363///     bitflags_lite::BitFlag::<u32, FlagsTag>::from_bit_retain(2);
364///
365/// #[doc = r" `TENTH` `BitFlag` doc-comment."]
366/// pub const TENTH: bitflags_lite::BitFlag<u32, FlagsTag> =
367///     bitflags_lite::BitFlag::<u32, FlagsTag>::from_bit_retain(9);
368///
369/// #[doc = r" `ALL` `BitFlags` doc-comment."]
370/// pub const ALL: bitflags_lite::BitFlags<u32, FlagsTag> =
371///     bitflags_lite::BitFlags::<u32, FlagsTag>::from_bits_retain(
372///         (0 | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&FIRST)
373///             | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&THIRD)
374///             | bitflags_lite::BitFlag::<u32, FlagsTag>::mask_or_default(&TENTH)),
375///     );
376///
377/// #[doc = r" `ALL_ALT` `BitFlags` doc-comment."]
378/// pub const ALL_ALT: bitflags_lite::BitFlags<u32, FlagsTag> =
379///     bitflags_lite::BitFlags::<u32, FlagsTag>::from_bits_retain(
380///         (FIRST.mask_or_default() | THIRD.mask_or_default() | TENTH.mask_or_default()),
381///     );
382///
383/// #[doc = r" `NONE` `BitFlags` doc-comment."]
384/// pub const NONE: bitflags_lite::BitFlags<u32, FlagsTag> =
385///     bitflags_lite::BitFlags::<u32, FlagsTag>::from_bits_retain(0);
386/// ```
387///
388/// </details>
389///
390/// [`BitFlagsSpec`]: trait.BitFlagsSpec.html
391/// [`BitFlagsSpec::VALID_BITS_MASK`]: trait.BitFlagsSpec.html#associatedconstant.VALID_BITS_MASK
392/// [`BitFlagsSpec::FLAG_NAMES`]: trait.BitFlagsSpec.html#associatedconstant.FLAG_NAMES
393/// [`BitFlagsSpec::DEFAULT_NAME_MATCHER`]: trait.BitFlagsSpec.html#associatedconstant.DEFAULT_NAME_MATCHER
394/// [`VALID_BITS_MASK`]: trait.BitFlagsSpec.html#associatedconstant.VALID_BITS_MASK
395/// [`FLAG_NAMES`]: trait.BitFlagsSpec.html#associatedconstant.FLAG_NAMES
396/// [`NameMatcher::Exact`]: enum.NameMatcher.html#variant.Exact
397#[macro_export]
398macro_rules! bitflags {
399    (
400        $( #![ $($bitflags_meta:tt)* ] )*
401        $tag_name:ident;
402        $( $tt:tt )*
403    ) => {
404        $crate::__bitflags_impl! {
405            [ $( $tt )* ] [ $( #![ $( $bitflags_meta )* ] )* ]
406            [] [] [] [] [ $tag_name ] [] []
407        }
408    };
409    (
410        $( #![ $($bitflags_meta:tt)* ] )*
411        $( #[ $($tag_meta:tt)* ] )*
412        $tag_vis:vis struct $tag_name:ident;
413        $( $tt:tt )*
414    ) => {
415        $( #[ $($tag_meta)* ] )*
416        #[derive(
417            ::core::marker::Copy,
418            ::core::clone::Clone,
419            ::core::cmp::Eq,
420            ::core::cmp::PartialEq,
421            ::core::cmp::Ord,
422            ::core::cmp::PartialOrd,
423            ::core::hash::Hash,
424            ::core::default::Default,
425            ::core::fmt::Debug,
426        )]
427        $tag_vis struct $tag_name;
428
429        $crate::__bitflags_impl! {
430            [ $( $tt )* ] [ $( #![ $( $bitflags_meta )* ] )* ]
431            [] [] [] [] [ $tag_name ] [] []
432        }
433    };
434}
435
436/// # Syntax
437///
438/// ```rust,ignore
439/// __bitflags_impl {
440///     // Unparsed meta.
441///     [ $( #![name_matcher( $name_matcher:expr )] )? ]
442///
443///     // Unparsed bits and masks.
444///     [ $( $vis:vis $name:ident: $kind:tt = $value:expr $(, $display:expr )?; )* ]
445///
446///     // Parsed bits.
447///     [ $( $value:expr $(, $display:expr )?; )* ]
448///
449///     // Parsed named bits.
450///     [ $( $vis:vis $name:ident = $value:expr $(, $display:expr )?; )* ]
451///
452///     // Parsed masks.
453///     [ $( $value:expr $(, $display:expr )?; )* ]
454///
455///     // Parsed named masks.
456///     [ $( $vis:vis $name:ident = $value:expr $(, $display:expr )?; )* ]
457///
458///     // Storage inner typename.
459///     [ $storage:ty ]
460///
461///     // Tag typename.
462///     [ $tag:ty ]
463///
464///     // Parsed name matcher.
465///     [ $( $name_matcher:expr )? ]
466/// }
467/// ```
468#[doc(hidden)]
469#[macro_export]
470macro_rules! __bitflags_impl {
471    // Choose default name matcher.
472    (
473        [ $( $tt:tt )* ] []
474        [] [] [] [] [ $tag:ty ] [ $storage:ty ] []
475    ) => {
476        $crate::__bitflags_impl! {
477            [ $( $tt )* ] [] [] [] [] []
478            [ $tag ] [ $storage ] [ $crate::NameMatcher::Exact ]
479        }
480    };
481    (
482        [ $( $tt:tt )* ] []
483        [] [] [] [] [ $tag:ty ] [] []
484    ) => {
485        ::core::compile_error!("`#![storage(...)]` attribute is required");
486    };
487
488    // Choose storage.
489    (
490        [ $( $tt:tt )* ]
491        [ #![ storage( $storage:ty ) ] $( #![ $($meta:tt)* ] )* ]
492        [] [] [] [] [ $tag:ty ] [] [ $( $name_matcher:expr )? ]
493    ) => {
494        $crate::__bitflags_impl! {
495            [ $( $tt )* ] [ $( #![ $($meta)* ] )* ]
496            [] [] [] [] [ $tag ] [ $storage ] [ $( $name_matcher )? ]
497        }
498    };
499
500    // Choose name matcher.
501    (
502        [ $( $tt:tt )* ]
503        [ #![ name_matcher( $name_matcher:expr ) ] $( #![ $($meta:tt)* ] )* ]
504        [] [] [] [] [ $tag:ty ] [ $( $storage:ty )? ] []
505    ) => {
506        $crate::__bitflags_impl! {
507            [ $( $tt )* ] [ $( #![ $($meta)* ] )* ]
508            [] [] [] [] [ $tag ] [ $( $storage )? ] [ $name_matcher ]
509        }
510    };
511
512    // Parse unnamed bit item.
513    (
514        [
515            $vis:vis bit = $value:expr $(, $display:expr )?;
516            $( $tt:tt )*
517        ]
518        []
519        [ $( $bits:tt )* ] [ $( $named_bits:tt )* ]
520        [ $( $masks:tt )* ] [ $( $named_masks:tt )* ]
521        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
522    ) => {
523        $crate::__bitflags_impl! {
524            [ $( $tt )* ] []
525            [ $( $bits )* [ [ $value ] [ $( $display )? ] ] ]
526            [ $( $named_bits )* ]
527            [ $( $masks )* ]
528            [ $( $named_masks )* ]
529            [ $tag ] [ $storage ] [ $name_matcher ]
530        }
531    };
532
533    // Parse named bit item.
534    (
535        [
536            $( #[ $($meta:meta)* ] )*
537            $vis:vis bit $name:ident = $value:expr $(, $display:expr )?;
538            $( $tt:tt )*
539        ]
540        []
541        [ $( $bits:tt )* ] [ $( $named_bits:tt )* ]
542        [ $( $masks:tt )* ] [ $( $named_masks:tt )* ]
543        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
544    ) => {
545        $crate::__bitflags_impl! {
546            [ $( $tt )* ] []
547            [ $( $bits )* [ [ $value ] [ $( $display )? ] ] ]
548            [ $( $named_bits )* [
549                [ $( #[ $($meta)* ] )* ] [ $vis ] [ $name ] [ $value ]
550            ] ]
551            [ $( $masks )* ]
552            [ $( $named_masks )* ]
553            [ $tag ] [ $storage ] [ $name_matcher ]
554        }
555    };
556
557    // Parse mask item with union array syntax.
558    (
559        [
560            $( #[ $($meta:meta)* ] )*
561            $vis:vis mask $( $name:ident )? =
562                [ $( $value:ident ),* $(,)? ] $(, $display:expr )?;
563            $( $tt:tt )*
564        ]
565        []
566        [ $( $bits:tt )* ] [ $( $named_bits:tt )* ]
567        [ $( $masks:tt )* ] [ $( $named_masks:tt )* ]
568        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
569    ) => {
570        $crate::__bitflags_impl! {
571            [
572                $( #[ $($meta)* ] )*
573                $vis mask $( $name )? =
574                    0 $( |
575                        $crate::BitFlag::<$storage, $tag>::mask_or_default(&$value)
576                    )*
577                 $(, $display )?;
578                $( $tt )*
579            ]
580            []
581            [ $( $bits )* ] [ $( $named_bits )* ]
582            [ $( $masks )* ] [ $( $named_masks )* ]
583            [ $tag ] [ $storage ] [ $name_matcher ]
584        }
585    };
586
587    // Parse unnamed mask item.
588    (
589        [
590            $( #[ $($meta:meta)* ] )*
591            $vis:vis mask = $value:expr $(, $display:expr )?;
592            $( $tt:tt )*
593        ]
594        []
595        [ $( $bits:tt )* ] [ $( $named_bits:tt )* ]
596        [ $( $masks:tt )* ] [ $( $named_masks:tt )* ]
597        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
598    ) => {
599        $crate::__bitflags_impl! {
600            [ $( $tt )* ] []
601            [ $( $bits )* ]
602            [ $( $named_bits )* ]
603            [ $( $masks )* [ [ $value ] [ $( $display )? ] ] ]
604            [ $( $named_masks )* ]
605            [ $tag ] [ $storage ] [ $name_matcher ]
606        }
607    };
608
609    // Parse named mask item.
610    (
611        [
612            $( #[ $($meta:meta)* ] )*
613            $vis:vis mask $name:ident = $value:expr $(, $display:expr )?;
614            $( $tt:tt )*
615        ]
616        []
617        [ $( $bits:tt )* ] [ $( $named_bits:tt )* ]
618        [ $( $masks:tt )* ] [ $( $named_masks:tt )* ]
619        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
620    ) => {
621        $crate::__bitflags_impl! {
622            [ $( $tt )* ] []
623            [ $( $bits )* ]
624            [ $( $named_bits )* ]
625            [ $( $masks )* [ [ $value ] [ $( $display )? ] ] ]
626            [ $( $named_masks )* [
627                [ $( #[ $($meta)* ] )* ] [ $vis ] [ $name ] [ $value ]
628            ] ]
629            [ $tag ] [ $storage ] [ $name_matcher ]
630        }
631    };
632
633    (
634        [] []
635        [ $( [
636            [ $b_value:expr ] [ $( $b_display:expr )? ]
637        ] )* ]
638        [ $( [
639            [ $( #[ $($nb_meta:meta)* ] )* ]
640            [ $nb_vis:vis ] [ $nb_name:ident ] [ $nb_value:expr ]
641        ] )* ]
642        [ $( [
643            [ $m_value:expr ] [ $( $m_display:expr )? ]
644        ] )* ]
645        [ $( [
646            [ $( #[ $($nm_meta:meta)* ] )* ]
647            [ $nm_vis:vis ] [ $nm_name:ident ] [ $nm_value:expr ]
648        ] )* ]
649        [ $tag:ty ] [ $storage:ty ] [ $name_matcher:expr ]
650    ) => {
651        #[allow(
652            trivial_numeric_casts,
653            unused_mut,
654            clippy::allow_attributes,
655            clippy::as_conversions,
656            reason = "codegen"
657        )]
658        impl $crate::BitFlagsSpec<$storage> for $tag {
659            const VALID_BITS_MASK: $storage = const {
660                (0 as $storage) $( | (1 as $storage) << $b_value )*
661            };
662            const FLAG_NAMES: &[&[&str]] = const {
663                const MAX: usize = $crate::util::__const_max(&[ $( $b_value ),*]);
664                const FLAG_NAMES: [&'static [&'static str]; MAX + 1] = const {
665                    let mut flag_names: [&'static [&'static str]; MAX + 1] = [&[]; MAX + 1];
666                    $( $( flag_names[ $b_value ] = $b_display; )? )*
667                    flag_names
668                };
669                &FLAG_NAMES
670            };
671            const COMBINED_NAMES: &[($storage, &str)] = &[
672                $( $( ( $m_value, $m_display ), )? )*
673            ];
674            const DEFAULT_NAME_MATCHER: $crate::NameMatcher = $name_matcher;
675        }
676
677        $(
678            $( #[ $($nb_meta)* ] )*
679            $nb_vis const $nb_name: $crate::BitFlag<$storage, $tag> =
680                $crate::BitFlag::<$storage, $tag>::from_bit_retain($nb_value);
681        )*
682        $(
683            $( #[ $($nm_meta)* ] )*
684            $nm_vis const $nm_name: $crate::BitFlags<$storage, $tag> =
685                $crate::BitFlags::<$storage, $tag>::from_bits_retain($nm_value);
686        )*
687    };
688
689}