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}