Code Monkey home page Code Monkey logo

bitflags's Introduction

bitflags

Rust Latest version Documentation License

bitflags generates flags enums with well-defined semantics and ergonomic end-user APIs.

You can use bitflags to:

  • provide more user-friendly bindings to C APIs where flags may or may not be fully known in advance.
  • generate efficient options types with string parsing and formatting support.

You can't use bitflags to:

  • guarantee only bits corresponding to defined flags will ever be set. bitflags allows access to the underlying bits type so arbitrary bits may be set.

  • define bitfields. bitflags only generates types where set bits denote the presence of some combination of flags.

  • Documentation

  • Specification

  • Release notes

Usage

Add this to your Cargo.toml:

[dependencies]
bitflags = "2.5.0"

and this to your source code:

use bitflags::bitflags;

Example

Generate a flags structure:

use bitflags::bitflags;

// The `bitflags!` macro generates `struct`s that manage a set of flags.
bitflags! {
    /// Represents a set of flags.
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    struct Flags: u32 {
        /// The value `A`, at bit position `0`.
        const A = 0b00000001;
        /// The value `B`, at bit position `1`.
        const B = 0b00000010;
        /// The value `C`, at bit position `2`.
        const C = 0b00000100;

        /// The combination of `A`, `B`, and `C`.
        const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
    }
}

fn main() {
    let e1 = Flags::A | Flags::C;
    let e2 = Flags::B | Flags::C;
    assert_eq!((e1 | e2), Flags::ABC);   // union
    assert_eq!((e1 & e2), Flags::C);     // intersection
    assert_eq!((e1 - e2), Flags::A);     // set difference
    assert_eq!(!e2, Flags::A);           // set complement
}

Rust Version Support

The minimum supported Rust version is documented in the Cargo.toml file. This may be bumped in minor releases as necessary.

bitflags's People

Contributors

alexcrichton avatar amanieu avatar arturoc avatar astocko avatar bors[bot] avatar cldfire avatar dextero avatar dimbleby avatar drmikehenry avatar dtolnay avatar dylan-dpc avatar ericson2314 avatar fiveop avatar gabrielmajeri avatar gnomeddev avatar guillaumegomez avatar jake-shadle avatar kodraus avatar koivunej avatar konsumlamm avatar ms2ger avatar niklasf avatar nim65s avatar raoulstrackx avatar rap2hpoutre avatar ratijas avatar tamird avatar topecongiro avatar varkor avatar wy193777 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitflags's Issues

Possibly unintended breakage between 0.8 and 0.9 involving use of the `#[deprecated]` attribute

Given the following snippet of code compiled with bitflags 0.8:

#![allow(deprecated)]

#[macro_use]
extern crate bitflags;

bitflags! {
    pub flags TestFlags: u32 {
        #[deprecated(note = "test note")]
        const FLAG_ONE = 1,
    }
}

Everything works fine:

Compiling bitflags_breakage_test v0.1.0 (file:///home/cldfire/programming_projects/bitflags_breakage_test)
    Finished dev [unoptimized + debuginfo] target(s) in 0.10 secs

And everything looks fine in the docs as well:

spectacle h29900

spectacle t29900

However, given the same snippet of code (ignoring syntax changes) compiled with bitflags 0.9:

#![allow(deprecated)]

#[macro_use]
extern crate bitflags;

bitflags! {
    pub struct TestFlags: u32 {
        #[deprecated(note = "test note")]
        const FLAG_ONE = 1;
    }
}

It does not compile:

   Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling bitflags_breakage_test v0.1.0 (file:///home/cldfire/programming_projects/bitflags_breakage_test)
error: This deprecation annotation is useless
  --> src/lib.rs:6:1
   |
6  | / bitflags! {
7  | |     pub struct TestFlags: u32 {
8  | |         #[deprecated(note = "test note")]
9  | |         const FLAG_ONE = 1;
10 | |     }
11 | | }
   | |_^
   |
   = note: this error originates in a macro outside of the current crate

error: This deprecation annotation is useless
  --> src/lib.rs:6:1
   |
6  | / bitflags! {
7  | |     pub struct TestFlags: u32 {
8  | |         #[deprecated(note = "test note")]
9  | |         const FLAG_ONE = 1;
10 | |     }
11 | | }
   | |_^
   |
   = note: this error originates in a macro outside of the current crate

error: aborting due to 2 previous errors

error: Could not compile `bitflags_breakage_test`.

To learn more, run the command again with --verbose.

I am not sure if this behavior is intended or not, or if use of attributes such as #[deprecated] was supported in the first place. If this is correct behavior it would be nice to mention it in the release notes (I encountered this issue while bumping bitflags from 0.8 -> 0.9 in my own crate).

Warnings about deprecated SipHasher

cargo test prints the following warnings:

warning: use of deprecated item: use `std::collections::hash_map::DefaultHasher` instead
   --> src/lib.rs:519:21
    |
519 |     use std::hash::{SipHasher, Hash, Hasher};
    |                     ^^^^^^^^^
    |
    = note: #[warn(deprecated)] on by default

warning: use of deprecated item: use `std::collections::hash_map::DefaultHasher` instead
   --> src/lib.rs:775:21
    |
775 |         let mut s = SipHasher::new_with_keys(0, 0);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(deprecated)] on by default

warning: use of deprecated item: use `std::collections::hash_map::DefaultHasher` instead
   --> src/lib.rs:775:21
    |
775 |         let mut s = SipHasher::new_with_keys(0, 0);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(deprecated)] on by default

Dead code warnings

https://gist.github.com/Ms2ger/5dd2268cb37176076856 causes

$ cargo build
   Compiling bitflags v0.1.0 (file:///tmp/bitflags)
<bitflags macros>:30:15: 30:60 warning: method is never used: `bits`, #[warn(dead_code)] on by default
<bitflags macros>:30  # [ inline ] pub fn bits ( & self ) -> $ T { self . bits }
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:33:15: 37:67 warning: method is never used: `from_bits`, #[warn(dead_code)] on by default
<bitflags macros>:33  # [ inline ] pub fn from_bits ( bits : $ T ) -> :: std:: option:: Option < $
<bitflags macros>:34 BitFlags > {
<bitflags macros>:35 if ( bits & ! $ BitFlags:: all (  ) . bits (  ) ) != 0 {
<bitflags macros>:36 :: std:: option:: Option:: None } else {
<bitflags macros>:37 :: std:: option:: Option:: Some ( $ BitFlags { bits : bits } ) } }
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:40:15: 41:53 warning: method is never used: `from_bits_truncate`, #[warn(dead_code)] on by default
<bitflags macros>:40  # [ inline ] pub fn from_bits_truncate ( bits : $ T ) -> $ BitFlags {
<bitflags macros>:41 $ BitFlags { bits : bits } & $ BitFlags:: all (  ) }
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:43:15: 44:36 warning: method is never used: `is_empty`, #[warn(dead_code)] on by default
<bitflags macros>:43  # [ inline ] pub fn is_empty ( & self ) -> bool {
<bitflags macros>:44 * self == $ BitFlags:: empty (  ) }
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:46:15: 47:34 warning: method is never used: `is_all`, #[warn(dead_code)] on by default
<bitflags macros>:46  # [ inline ] pub fn is_all ( & self ) -> bool {
<bitflags macros>:47 * self == $ BitFlags:: all (  ) }
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:49:15: 50:39 warning: method is never used: `intersects`, #[warn(dead_code)] on by default
<bitflags macros>:49  # [ inline ] pub fn intersects ( & self , other : $ BitFlags ) -> bool {
<bitflags macros>:50 ! ( * self & other ) . is_empty (  ) }
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:56:15: 57:34 warning: method is never used: `remove`, #[warn(dead_code)] on by default
<bitflags macros>:56  # [ inline ] pub fn remove ( & mut self , other : $ BitFlags ) {
<bitflags macros>:57 self . bits &= ! other . bits ; } /// Toggles the specified flags in-place.
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
<bitflags macros>:58:15: 59:32 warning: method is never used: `toggle`, #[warn(dead_code)] on by default
<bitflags macros>:58  # [ inline ] pub fn toggle ( & mut self , other : $ BitFlags ) {
<bitflags macros>:59 self . bits ^= other . bits ; } } impl :: std:: ops:: BitOr for $ BitFlags {
<bitflags macros>:90:1: 92:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:5:1: 10:2 note: in this expansion of bitflags! (defined in <bitflags macros>)

Publishing a new version

0.8.2 contains #[allow(private_in_public)] for a flavor of private-in-public error that is really going to become an error (public reexport of a private extern crate).
I turned it into an error in rustc and during bootstrapping I discovered that bitflags 0.8.2 used by rustc are still using it.

Create a test suite crate

#61 adds an unstable_testing feature that is only considered by tests. It seems unfortunate to leak this into the public API.

Having a separate crate for tests (like in Serde) would avoid this.

Library evaluation tracking issue

Version 0.2.1 breaks glfw

glfw v0.0.8 has a dependancy on bitflags. Version 0.1.1 of bitflags is fine, 0.2.1 gives this error in the build:

Compiling glfw v0.0.8
:8:24: 15:4 error: conflicting implementations for trait core::fmt::Debug [E0119]
:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
:9 fn fmt ( & self , f : & mut :: std:: fmt:: Formatter ) -> :: std:: fmt::
:10 Result {
:11 let mut first = true ; $ (
:12 if self . contains ( $ Flag ) {
:13 if ! first { try ! ( f . write_str ( " | " ) ) ; } first = false ; try ! (
...
:1:1: 79:67 note: in expansion of bitflags!
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1041:1: 1049:2 note: expansion site
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1051:1: 1063:2 note: note conflicting implementation here
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1051 impl fmt::Debug for Modifiers {
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1052 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1053 for (i, x) in [Shift, Control, Alt, Super].iter().filter(|x| self.contains(**x)).enumerate() {
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1054 if i != 0 { try!(write!(f, ", ")) };
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1055 if *x == Shift { try!(write!(f, "Shift" )) }
/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/glfw-0.0.8/src/lib.rs:1056 else if *x == Control { try!(write!(f, "Control" )) }
...
error: aborting due to previous error

Compiling anything with glfw should produce this error. Pulling up the previous version with

cargo update -p bitflags --precise 0.1.1

has everything running again. This conflict with bitflags only occurs in an OSX build, not Linux.

#![feature(hash)] warning

The latest nightly yields warnings:

note: in expansion of #[derive]
<bitflags macros>:5:1: 5:73 note: expansion site
<bitflags macros>:1:1: 72:67 note: in expansion of bitflags!
<bitflags macros>:70:1: 72:63 note: expansion site
<bitflags macros>:1:1: 72:67 note: in expansion of bitflags!
src/lib.rs:39:1: 52:2 note: expansion site
<bitflags macros>:5:65: 5:69 help: add #![feature(hash)] to the crate attributes to silence this warning
<bitflags macros>:5 # [ derive ( Copy , PartialEq , Eq , Clone , PartialOrd , Ord , Hash ) ] $ (

Automatically fill in bit pattern

The Go equivalent using iota looks like:

const (
    flagA = 1 << iota
    flagB
    flagC
    flagD
)

Is this something you would consider supporting in a better way in bitflags?

Resolve clippy lints

When using this lib as a dep, and running clippy across the project, this dependency fails a few trivial lints, this prevents things like causing clippy to fail a CI build. The lints in question are:

I haven't looked at the source for this project at all, but if it's just a trivial change, and doesn't affect the underlying methodology I'd be happy to submit a PR fixing these.

Thanks for this lib too!

serde support

Are there any plans to support Serialize and Deserialize for generated types? I'm writing the impls manually in my code, but this falls apart once there's a ton of bitflags generated types. If others are interested in such a feature, maybe I can find the time to implement it myself and submit a pull request :)

associated constants

This crate really wants to use associated constants (see rust-lang/rust#24921) but the tricks introduced in #14 are incompatible with associated constants (because associated constants can't be used to shadow locally scoped constants).

What do?

Fails to build in travis occasionally

Looks very strange, sometimes it works, sometimes it doesn't:

Used to be:

Could not document `bitflags`.
Caused by:
  Process didn't exit successfully: `rustdoc /home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/bitflags-0.2.1/src/lib.rs --crate-name bitflags -o /home/travis/build/gfx-rs/gfx/target/doc -L dependency=/home/travis/build/gfx-rs/gfx/target/debug/deps -L dependency=/home/travis/build/gfx-rs/gfx/target/debug/deps` (exit code: 101)

But has changed into this in the most recent build:

<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/state.rs:289:1: 299:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:43:1: 54:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
<bitflags macros>:75:1: 77:63 note: expansion site
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:56:1: 62:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
<bitflags macros>:7:27: 8:19 error: missing documentation for a constant
<bitflags macros>:7 $ ( # [ $ Flag_attr ] ) * pub const $ Flag : $ BitFlags = $ BitFlags {
<bitflags macros>:8 bits : $ value } ; ) + impl :: std:: fmt:: Debug for $ BitFlags {
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
<bitflags macros>:75:1: 77:63 note: expansion site
<bitflags macros>:1:1: 77:67 note: in expansion of bitflags!
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/target.rs:56:1: 62:3 note: expansion site
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17:9: 17:21 note: lint level defined here
/home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs:17 #![deny(missing_docs, missing_copy_implementations)]
                                                                                                    ^~~~~~~~~~~~
error: aborting due to 15 previous errors
Build failed, waiting for other jobs to finish...
Could not compile `draw_state`.
Caused by:
  Process didn't exit successfully: `rustc /home/travis/.cargo/registry/src/github.com-0a35038f75765ae4/draw_state-0.1.1/src/lib.rs --crate-name draw_state --crate-type lib -g -C metadata=db41f6c0c53c3a65 -C extra-filename=-db41f6c0c53c3a65 --out-dir /home/travis/build/gfx-rs/gfx/target/debug/deps --emit=dep-info,link -L dependency=/home/travis/build/gfx-rs/gfx/target/debug/deps -L dependency=/home/travis/build/gfx-rs/gfx/target/debug/deps --extern bitflags=/home/travis/build/gfx-rs/gfx/target/debug/deps/libbitflags-425420435a0b4460.rlib -Awarnings` (exit code: 101)

Add ability to iterate through flags

Iterating over each each possible flag value would be a cool feature. I'm currently making an array with each constant value and then iterating over that.

Allow namespaced flags

It would be nice to have FlagType::FlagName be the pattern rather than dumping the flag values into the top-level namespace. Is this possible?

Function-local bitflags

Is there any hope of supporting usage like this? The error here is inconsistent with being able to declare structs and other types of items local to a function.

#[macro_use]
extern crate bitflags;

fn main() {
    bitflags! {
        flags Flags: u8 {
            const A = 1,
            const B = 2,
        }
    }
    println!("{:?}", A);
}
error[E0425]: cannot find value `A` in module `super::super`
  --> src/main.rs:5:5
   |
5  |       bitflags! {
   |  _____^ starting here...
6  | |         flags Flags: u8 {
7  | |             const A = 1,
8  | |             const B = 2,
9  | |         }
10 | |     }
   | |_____^ ...ending here: not found in `super::super`
   |
   = note: this error originates in a macro outside of the current crate

Support for nightly 128-bit integers

What do you think about adding feature gated 128-bit based bitflags? While trying u128 in nightly, I noticed that bitflags silently degrades to u64.

I can work on a PR if interested.

Explicit dependency on std

I notice that some freestanding folk are borrowing this code, doing a quick s#::std#::core# and going on their merry way.

core isn't stable, so I can't suggest you do that, but… I wonder if there's a solution on the horizon for this explicit module dependency problem. I imagine it's going to pop up more and more often as people do fun things with Rust.

Thoughts?

Move docs to the crate level

This crate presently has no crate level docs, and that is the most important place for docs to be.

Let's move the current content of the bitflags! rustdocs up to the crate level, leaving behind copies of the examples, and a hyperlink to the crate level.

Error building libucl-sys

bitflags 0.3 builds fine but 0.5 gives me this error when building libucl-sys (latest: https://github.com/hauleth/libucl-sys). Not sure where the problem is..

<bitflags macros>:17:24: 19:63 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:89:1: 99:2 note: in this expansion of bitflags! (defined in <bitflags macros>)
lib.rs:91:31: 91:36 help: run `rustc --explain E0412` to see a detailed explanation
lib.rs:91:31: 91:36 help: you can import several candidates into scope (`use ...;`):
lib.rs:91:31: 91:36 help:   `bitflags::__core::os::raw::c_int`
lib.rs:91:31: 91:36 help:   `libc::c_int`
lib.rs:91:31: 91:36 help:   `std::os::raw::c_int`
lib.rs:91:31: 91:36 error: type name `c_int` is undefined or not in scope [E0412]
lib.rs:91     flags ucl_object_flags_t: c_int {

Documentation for specific flags aren't scoped

In nix we use the bitflags! macro for grouping the various libc constants into datatypes for our functions. This provides some nice type safety, but unfortunately the generated documentation is not ideal. There are two problems with how bitflags! results in generated documentation:

  1. The constants are all listed, ungrouped, in the module documentation (see here).
  2. The generated datatypes don't list their specific constants within their documentation. (see here).

I'm not certain if this is fixable by bitflags without changes to rustdoc, but I'd prefer if the documentation for the generated datatypes more closely matched Enum types, which doesn't have either of the above problems.

Also relevant: nix-rust/nix#593

flags.contains(0) == true

The contains API is implemented as follows:

pub fn contains(&self, other: $BitFlags) -> bool {
    (*self & other) == other
}

This means that doing flags.contains(SomeFlag::empty()) is true, which is counterintuitive.

Bitflags should be private by default

Bitflags should match the semantics of structs, which are private by default unless explicitly exported using pub.

Since this is a compat-breaking change, it would make sense to do it at the same time as the switch to associated constants and namespaced flags (#24).

Example:

bitflags! {
    pub flags Flags: u32 {
        const FLAG_A   = 0b00000001,
        const FLAG_B   = 0b00000010,
    }
}

Allow for masking using a different datatype

I work with data that often has a set of bitflags and then also has various masks defined over those bitflags. Unfortunately those masks are not often a valid value for the actual datatype. For example, when working with the termios API on POSIX systems, you have the constants:

bitflags! {
    pub flags ControlFlags: tcflag_t {
        ...,
        CS5,
        CS6,
        CS7,
        CS8,
        ...,
    }
}

This is part of a larger bitfield that contains many other values, so the following flags are defined:

bitflags! {
    pub flags ControlFlagsMask: tcflag_t {
        ...,
        CSIZE,
        ...,
    }
}

But if I do this, there's no way to actually do set operations between these two without combining these flags, which creates the problem of a user actually being able to generate an invalid bitfield by using CSIZE directly and passing it into a function.

It'd be great if there was a way to tag certain values as a mask such that you could use it to select values from an existing bitflags type but couldn't use it directly within that type.

Add an example of what the macro-expanded API looks like

This crate has a documentation problem in that it generates a bunch of methods, and they are hard to document. I believe the way we want to address this is by creating another module, containing a hand-coded API that looks like the bitflags produced API, and treat that entire module as documentation, sort of like error-chain does.

Will take some experimentation.

New Debug impl fails to compile when the bitflags are conditional

The following code cause a compilation error when compiled not compiled with feature "C".

bitflags! {
    flags Flags: u32 {
        const FLAG_A = 0b00000001,
        const FLAG_B  = 0b00000010,
        #[cfg(feature = "C")] const FLAG_C = 0b00000100,
    }
}

:12:22: 12:28 error: unresolved name FLAG_C
:12 if self . contains ( $ Flag ) {
^~~~~~
:1:1: 79:67 note: in expansion of bitflags!
:77:1: 79:63 note: expansion site
:1:1: 79:67 note: in expansion of bitflags!

Using bitflags with libc types broke in 0.5.

351a632 seems to have broken code which uses libc::c_int as the type of the flags. I'm not sure if libc::c_int is supported or not, since it is an integer type, though it is in some sense, user defined...

#[macro_use]
extern crate bitflags;

extern crate libc;

use libc::c_int;

bitflags! {
    /// baz
    flags Flags: c_int {
        const A       = 0b00000001,
        #[doc = "bar"]
        const B       = 0b00000010,
        const C       = 0b00000100,
        #[doc = "foo"]
        const ABC     = A.bits | B.bits | C.bits,
    }
}

#[test]
fn smoke() {
    assert_eq!(ABC, A | B | C);
}

This worked before this commit, but fails after.

"flags" is meaningless

This threw me off when reading the bitflags documentation for the first time.

bitflags! {
    flags Flags: u32 {
        /* ... */
    }
}

I know it is not a keyword because my IDE does not highlight it like one. The casing suggests that it is a variable name or module name. Nope, it is a nugatory token required by the macro.

I think the important relevant thing to communicate to readers is that a type with the given name is being declared by the macro. Either of the following would be far more valuable I think.

bitflags! {
    type Flags: u32 {
        /* ... */
    }
}
bitflags! {
    struct Flags: u32 {
        /* ... */
    }
}

Macro error when the flag value isn't used directly

The latest macro implementation causes the following error:

:26:5: 26:74 error: constant item is never used: `WNOHANG`, #[deny(dead_code)] on by default :26 $ ( const $ Flag : super:: $ BitFlags = super:: $ BitFlags { bits : 0 } ; ) + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :1:1: 92:67 note: in expansion of bitflags! :90:1: 92:63 note: expansion site :1:1: 92:67 note: in expansion of bitflags! src/sys/wait.rs:13:1: 17:3 note: expansion site

When the bitflags aren't used by name (the following is an example from nix-rust where I noticed the error):

bitflags!(
    flags WaitPidFlag: c_int {
        const WNOHANG = 0x00000001,
    }
);

pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
    use self::WaitStatus::*;

    let mut status: i32 = 0;

    let option_bits = match options {
        Some(bits) => bits.bits(),
        None => 0
    };

    let res = unsafe { ffi::waitpid(pid as pid_t, &mut status as *mut c_int, option_bits) };

    if res < 0 {
        Err(Error::Sys(Errno::last()))
    } else if res == 0 {
        Ok(StillAlive)
    } else {
        Ok(Exited(res))
    }
}

Semicolons

It may be too late for such a change to make sense but typically "const" items are followed by a semicolon, not comma.

Semicolon would be more consistent with lazy_static as well.

bitflags! {
    flags Flags: u32 {
        const A = 0b00000001;
        const B = 0b00000010;
    }
}

const C: u32 = 0b00000100;
const D: u32 = 0b00001000;

lazy_static! {
    static ref E: u32 = 0b00010000;
    static ref F: u32 = 0b00100000;
}

Namespaced bitflag constants?

Would there be any objection to putting all generated consts in a module named after the type? This way, they could behave more like how enums do with variants globbing. It would also prevent documentation clutter in rustdoc, where all the constants are currently listed indiscriminately in the parent module.

Should we allow non-caps in constants so that they're stylistically closer to enums?

The syntax seems to work: http://is.gd/hGgTe7

Empty bitflags has unhelpful Debug representation

The Debug representation is the empty string. This is not very debuggable. I think "(empty)" would be more helpful.

#[macro_use]
extern crate bitflags;

bitflags! {
    pub flags Flags: u8 {
        const A = 0,
    }
}

fn main() {
    println!("{:?}", Flags::empty());
}

Usage?

Are structs created using the bitflags macro recommended to be used in raw FFI bindings, i.e. within function signatures (this involves giving the attribute repr(C) to the struct, but seems to work) – or only using them in higher-level bindings?

Mention Default trait in the docs

It makes sense to me why Default is not derived for bitflags - you may want a default value that is different from the empty value. Since Default is such a common trait, it would be helpful to mention explicitly in the "Trait implementations" section of the rustdoc and show an example using #[derive(Default)].

Allow using imported types

In short, the following should be possible:

extern crate libc;
use libc::c_uint;
mod constants;

bitflags! {
    pub flags EnvFlags: c_uint {
        const EnvNoSync = constants::MDB_NOSYNC,
       // ...
    }
}

As of #38, the above example will not compile. As a workaround, one can reference the imported types/modules within the bitflags definition using absolute paths, e.g. using ::libc::c_uint instead of c_uint or ::constants::MDB_NOSYNC instead of constants::MDB_NOSYNC. This is, at least, surprising.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.