tiny_bit_flags/
lib.rs

1//! Generate bit-flags struct and methods.
2//!
3//! It's very simple and easy to use. See the example below for details.
4//!
5//! # Usage
6//!
7//! Import this crate and `paste` to your `Cargo.toml`:
8//!
9//! ```toml
10//! [dependencies]
11//! tiny-bit-flags = "0.1"
12//! paste = "1.0"
13//! ```
14//!
15//! Invoke the `tiny_bit_flags!` macro to define flags:
16//!
17//! ```rust
18//! tiny_bit_flags::tiny_bit_flags! {
19//!     struct PrimFlags: u32 { // FORMAT: struct <StructName>: <InnerType>
20//!         // list flags below
21//!         const WRITABLE   = 0b00000001;
22//!         const EXECUTABLE = 0b00000010;
23//!     }
24//! }
25//! ```
26//!
27//! This actually generates the following code:
28//!
29//! ```rust,ignore
30//! // struct
31//! struct PrimFlags(u32);
32//!
33//! impl PrimFlags {
34//!     // constant values
35//!     const WRITABLE: u32   = 0b00000001;
36//!     const EXECUTABLE: u32 = 0b00000010;
37//!     // checking methods
38//!     const fn is_writable(&self) -> bool { ... }
39//!     const fn is_executable(&self) -> bool { ... }
40//!     // setting methods
41//!     const fn set_writable(&mut self) { ... }
42//!     const fn set_executable(&mut self) { ... }
43//!     // clearing methods
44//!     const fn clear_writable(&mut self) { ... }
45//!     const fn clear_executable(&mut self) { ... }
46//! }
47//! ```
48//!
49//! Then you can use them in your program:
50//!
51//! ```rust,ignore
52//! let mut f = PrimFlags(PrimFlags::WRITABLE); // initialize
53//! assert!(f.is_writable()); // check flag
54//! assert!(!f.is_executable());
55//!
56//! f.clear_writable(); // clear flag
57//! assert!(!f.is_writable());
58//!
59//! f.set_executable(); // set flag
60//! assert!(f.is_executable());
61//! ```
62//!
63//! You can use `pub` before `struct` to make all above to be public:
64//!
65//! ```diff
66//!  tiny_bit_flags! {
67//! +    pub struct PrimFlags: u32 {
68//! -    struct PrimFlags: u32 {
69//! ```
70//!
71//! You can also derive some traits on the struct:
72//!
73//! ```diff
74//!  tiny_bit_flags! {
75//! +    #[derive(Copy, Clone, Debug, Default)]
76//!      struct PrimFlags: u32 {
77//! ```
78
79/// Generate bit-flags struct and methods.
80///
81/// See module-level document for details.
82///
83/// Example:
84///
85/// ```rust
86/// tiny_bit_flags::tiny_bit_flags! {
87///     struct PrimFlags: u32 {
88///         const WRITABLE   = 0b00000001;
89///         const EXECUTABLE = 0b00000010;
90///     }
91/// }
92///
93/// let mut f = PrimFlags(PrimFlags::WRITABLE); // initialize
94/// assert!(f.is_writable()); // check flag
95/// assert!(!f.is_executable());
96///
97/// f.clear_writable(); // clear flag
98/// assert!(!f.is_writable());
99///
100/// f.set_executable(); // set flag
101/// assert!(f.is_executable());
102/// ```
103///
104#[macro_export]
105macro_rules! tiny_bit_flags {
106    (
107        $(#[$outer:meta])*
108        $vis:vis struct $BitFlags:ident: $T:ty {
109            $(
110                $(#[$inner:ident $($args:tt)*])*
111                const $Flag:tt = $value:expr;
112            )*
113        }
114    ) => {
115        // struct
116        $(#[$outer])*
117        $vis struct $BitFlags($vis $T);
118
119        impl $BitFlags {
120            $(
121                // constant values
122                $(#[$inner $($args)*])*
123                $vis const $Flag: $T = $value;
124
125                // methods
126                paste::paste! {
127                    $vis const fn [<is_ $Flag:lower>](&self) -> bool {
128                        self.0 & $value != 0
129                    }
130                    $vis const fn [<set_ $Flag:lower>](&mut self) {
131                        self.0 |= $value
132                    }
133                    $vis const fn [<clear_ $Flag:lower>](&mut self) {
134                        self.0 &= !$value
135                    }
136                }
137            )*
138        }
139    };
140}