Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple bitflags structs in one macro invocation #235

Merged
merged 2 commits into from May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.rs
Expand Up @@ -2,7 +2,7 @@ use std::env;
use std::process::Command;
use std::str::{self, FromStr};

fn main(){
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
Expand Down Expand Up @@ -41,4 +41,4 @@ fn rustc_minor_version() -> Option<u32> {
};

u32::from_str(next).ok()
}
}
80 changes: 52 additions & 28 deletions src/lib.rs
Expand Up @@ -11,7 +11,7 @@
//! A typesafe bitmask flag generator useful for sets of C-style bitmask flags.
//! It can be used for creating typesafe wrappers around C APIs.
//!
//! The `bitflags!` macro generates a `struct` that manages a set of flags. The
//! The `bitflags!` macro generates `struct`s that manage a set of flags. The
//! flags should only be defined for integer types, otherwise unexpected type
//! errors may occur at compile time.
//!
Expand Down Expand Up @@ -84,9 +84,9 @@
//!
//! # Visibility
//!
//! The generated struct and its associated flag constants are not exported
//! The generated structs and their associated flag constants are not exported
//! out of the current module by default. A definition can be exported out of
//! the current module by adding `pub` before `flags`:
//! the current module by adding `pub` before `struct`:
//!
//! ```
//! #[macro_use]
Expand All @@ -97,8 +97,7 @@
//! pub struct Flags1: u32 {
//! const A = 0b00000001;
//! }
//! }
//! bitflags! {
//!
//! # pub
//! struct Flags2: u32 {
//! const B = 0b00000010;
Expand All @@ -114,26 +113,26 @@
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//! Attributes can be attached to the generated `struct`s by placing them
//! before the `struct` keyword.
//!
//! # Trait implementations
//!
//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
//! traits automatically derived for the `struct` using the `derive` attribute.
//! traits are automatically derived for the `struct`s using the `derive` attribute.
//! Additional traits can be derived by providing an explicit `derive`
//! attribute on `flags`.
//! attribute on `struct`.
//!
//! The `Extend` and `FromIterator` traits are implemented for the `struct`,
//! The `Extend` and `FromIterator` traits are implemented for the `struct`s,
//! too: `Extend` adds the union of the instances of the `struct` iterated over,
//! while `FromIterator` calculates the union.
//!
//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` trait is also
//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also
//! implemented by displaying the bits value of the internal struct.
//!
//! ## Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//! The following operator traits are implemented for the generated `struct`s:
//!
//! - `BitOr` and `BitOrAssign`: union
//! - `BitAnd` and `BitAndAssign`: intersection
Expand All @@ -143,7 +142,7 @@
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//! The following methods are defined for the generated `struct`s:
//!
//! - `empty`: an empty set of flags
//! - `all`: the set of all defined flags
Expand All @@ -168,7 +167,7 @@
//!
//! ## Default
//!
//! The `Default` trait is not automatically implemented for the generated struct.
//! The `Default` trait is not automatically implemented for the generated structs.
//!
//! If your default value is equal to `0` (which is the same value as calling `empty()`
//! on the generated struct), you can simply derive `Default`:
Expand Down Expand Up @@ -262,7 +261,7 @@ extern crate std;
#[doc(hidden)]
pub extern crate core as _core;

/// The macro used to generate the flag structure.
/// The macro used to generate the flag structures.
///
/// See the [crate level docs](../bitflags/index.html) for complete documentation.
///
Expand Down Expand Up @@ -339,6 +338,7 @@ macro_rules! bitflags {
const $Flag:ident = $value:expr;
)+
}
$($t:tt)*
) => {
__bitflags! {
$(#[$outer])*
Expand All @@ -349,6 +349,10 @@ macro_rules! bitflags {
)+
}
}

bitflags! {
$($t)*
}
};
(
$(#[$outer:meta])*
Expand All @@ -358,6 +362,7 @@ macro_rules! bitflags {
const $Flag:ident = $value:expr;
)+
}
$($t:tt)*
) => {
__bitflags! {
$(#[$outer])*
Expand All @@ -368,6 +373,10 @@ macro_rules! bitflags {
)+
}
}

bitflags! {
$($t)*
}
};
(
$(#[$outer:meta])*
Expand All @@ -377,6 +386,7 @@ macro_rules! bitflags {
const $Flag:ident = $value:expr;
)+
}
$($t:tt)*
) => {
__bitflags! {
$(#[$outer])*
Expand All @@ -387,7 +397,12 @@ macro_rules! bitflags {
)+
}
}

bitflags! {
$($t)*
}
};
() => {};
}

#[macro_export(local_inner_macros)]
Expand Down Expand Up @@ -958,9 +973,7 @@ mod tests {
#[doc = "<strcat> wait what?"]
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
}
}

bitflags! {
struct _CfgFlags: u32 {
#[cfg(unix)]
const _CFG_A = 0b01;
Expand All @@ -969,15 +982,11 @@ mod tests {
#[cfg(unix)]
const _CFG_C = Self::_CFG_A.bits | 0b10;
}
}

bitflags! {
struct AnotherSetOfFlags: i8 {
const ANOTHER_FLAG = -1_i8;
}
}

bitflags! {
struct LongFlags: u32 {
const LONG_A = 0b1111111111111111;
}
Expand Down Expand Up @@ -1028,9 +1037,18 @@ mod tests {
assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty());
assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A);
assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B);
assert_eq!(unsafe { Flags::from_bits_unchecked(0b11) }, (Flags::A | Flags::B));
assert_eq!(unsafe { Flags::from_bits_unchecked(0b1000) }, (extra | Flags::empty()));
assert_eq!(unsafe { Flags::from_bits_unchecked(0b1001) }, (extra | Flags::A));
assert_eq!(
unsafe { Flags::from_bits_unchecked(0b11) },
(Flags::A | Flags::B)
);
assert_eq!(
unsafe { Flags::from_bits_unchecked(0b1000) },
(extra | Flags::empty())
);
assert_eq!(
unsafe { Flags::from_bits_unchecked(0b1001) },
(extra | Flags::A)
);
}

#[test]
Expand Down Expand Up @@ -1177,7 +1195,6 @@ mod tests {
assert_eq!(m1, e1);
}


#[cfg(bitflags_const_fn)]
#[test]
fn test_const_fn() {
Expand Down Expand Up @@ -1276,7 +1293,10 @@ mod tests {
let extra = unsafe { Flags::from_bits_unchecked(0xb8) };
assert_eq!(format!("{:?}", extra), "0xb8");
assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8");
assert_eq!(format!("{:?}", Flags::ABC | extra), "A | B | C | ABC | 0xb8");
assert_eq!(
format!("{:?}", Flags::ABC | extra),
"A | B | C | ABC | 0xb8"
);
}

#[test]
Expand Down Expand Up @@ -1320,8 +1340,7 @@ mod tests {
pub struct PublicFlags: i8 {
const X = 0;
}
}
bitflags! {

struct PrivateFlags: i8 {
const Y = 0;
}
Expand Down Expand Up @@ -1436,4 +1455,9 @@ mod tests {
assert_eq!(format!("{:?}", Flags::empty()), "NONE");
assert_eq!(format!("{:?}", Flags::SOME), "SOME");
}

#[test]
fn test_empty_bitflags() {
bitflags! {}
}
}
3 changes: 1 addition & 2 deletions test_suite/tests/compile-fail/private_flags.rs
Expand Up @@ -6,8 +6,7 @@ mod example {
pub struct Flags1: u32 {
const FLAG_A = 0b00000001;
}
}
bitflags! {

struct Flags2: u32 {
const FLAG_B = 0b00000010;
}
Expand Down
18 changes: 10 additions & 8 deletions test_suite/tests/compile-fail/private_flags.stderr
@@ -1,16 +1,18 @@
error[E0603]: struct `Flags2` is private
--> $DIR/private_flags.rs:19:26
--> $DIR/private_flags.rs:18:26
|
19 | let flag2 = example::Flags2::FLAG_B;
18 | let flag2 = example::Flags2::FLAG_B;
| ^^^^^^ private struct
|
note: the struct `Flags2` is defined here
--> $DIR/private_flags.rs:10:5
--> $DIR/private_flags.rs:5:5
|
10 | / bitflags! {
11 | | struct Flags2: u32 {
12 | | const FLAG_B = 0b00000010;
13 | | }
14 | | }
5 | / bitflags! {
6 | | pub struct Flags1: u32 {
7 | | const FLAG_A = 0b00000001;
8 | | }
... |
12 | | }
13 | | }
| |_____^
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)