From 6bbbaabdbebf796566c1740148312ee50159dcba Mon Sep 17 00:00:00 2001 From: konsumlamm Date: Sun, 27 Dec 2020 14:02:31 +0100 Subject: [PATCH 1/2] Allow multiple bitflags structs in one macro invocation Change mentions of the `flags` keyword (used before 0.9) to `struct` --- build.rs | 4 +-- src/lib.rs | 75 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/build.rs b/build.rs index 985757a6..67abc09d 100644 --- a/build.rs +++ b/build.rs @@ -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, @@ -41,4 +41,4 @@ fn rustc_minor_version() -> Option { }; u32::from_str(next).ok() -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 55daa5ea..7234e8f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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. //! @@ -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] @@ -97,8 +97,7 @@ //! pub struct Flags1: u32 { //! const A = 0b00000001; //! } -//! } -//! bitflags! { +//! //! # pub //! struct Flags2: u32 { //! const B = 0b00000010; @@ -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 @@ -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 @@ -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`: @@ -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. /// @@ -339,6 +338,7 @@ macro_rules! bitflags { const $Flag:ident = $value:expr; )+ } + $($t:tt)* ) => { __bitflags! { $(#[$outer])* @@ -349,6 +349,10 @@ macro_rules! bitflags { )+ } } + + bitflags! { + $($t)* + } }; ( $(#[$outer:meta])* @@ -358,6 +362,7 @@ macro_rules! bitflags { const $Flag:ident = $value:expr; )+ } + $($t:tt)* ) => { __bitflags! { $(#[$outer])* @@ -368,6 +373,10 @@ macro_rules! bitflags { )+ } } + + bitflags! { + $($t)* + } }; ( $(#[$outer:meta])* @@ -377,6 +386,7 @@ macro_rules! bitflags { const $Flag:ident = $value:expr; )+ } + $($t:tt)* ) => { __bitflags! { $(#[$outer])* @@ -387,7 +397,12 @@ macro_rules! bitflags { )+ } } + + bitflags! { + $($t)* + } }; + () => {}; } #[macro_export(local_inner_macros)] @@ -958,9 +973,7 @@ mod tests { #[doc = " wait what?"] const ABC = Self::A.bits | Self::B.bits | Self::C.bits; } - } - bitflags! { struct _CfgFlags: u32 { #[cfg(unix)] const _CFG_A = 0b01; @@ -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; } @@ -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] @@ -1177,7 +1195,6 @@ mod tests { assert_eq!(m1, e1); } - #[cfg(bitflags_const_fn)] #[test] fn test_const_fn() { @@ -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] @@ -1320,8 +1340,7 @@ mod tests { pub struct PublicFlags: i8 { const X = 0; } - } - bitflags! { + struct PrivateFlags: i8 { const Y = 0; } From 380d3c075020e57dbac08afc5d3f9247acdf5ab9 Mon Sep 17 00:00:00 2001 From: konsumlamm Date: Thu, 11 Feb 2021 18:07:37 +0100 Subject: [PATCH 2/2] Add test for `bitflags! {}` --- src/lib.rs | 5 +++++ test_suite/tests/compile-fail/private_flags.rs | 3 +-- .../tests/compile-fail/private_flags.stderr | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7234e8f0..906ec986 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1455,4 +1455,9 @@ mod tests { assert_eq!(format!("{:?}", Flags::empty()), "NONE"); assert_eq!(format!("{:?}", Flags::SOME), "SOME"); } + + #[test] + fn test_empty_bitflags() { + bitflags! {} + } } diff --git a/test_suite/tests/compile-fail/private_flags.rs b/test_suite/tests/compile-fail/private_flags.rs index 35089bc0..0532246a 100644 --- a/test_suite/tests/compile-fail/private_flags.rs +++ b/test_suite/tests/compile-fail/private_flags.rs @@ -6,8 +6,7 @@ mod example { pub struct Flags1: u32 { const FLAG_A = 0b00000001; } - } - bitflags! { + struct Flags2: u32 { const FLAG_B = 0b00000010; } diff --git a/test_suite/tests/compile-fail/private_flags.stderr b/test_suite/tests/compile-fail/private_flags.stderr index c72b6ff6..2bdf1acb 100644 --- a/test_suite/tests/compile-fail/private_flags.stderr +++ b/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)