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

Implement set complement and universe for bitflags #14009

Merged
merged 1 commit into from
May 14, 2014
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion src/libstd/bitflags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
//! assert!((e1 | e2) == FlagABC); // union
//! assert!((e1 & e2) == FlagC); // intersection
//! assert!((e1 - e2) == FlagA); // set difference
//! assert!(!e2 == FlagA); // set complement
//! }
//! ~~~
//!
Expand Down Expand Up @@ -88,14 +89,17 @@
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//! - `Not`: set complement
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `all`: the set of all flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `is_all`: `true` if all flags are currently set
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
Expand All @@ -122,6 +126,11 @@ macro_rules! bitflags(
$BitFlags { bits: 0 }
}

/// Returns the set containing all flags.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A common use case would also contain masks. If so, would this be correct? We could add another section to the macro perhaps) eg. flags { ... } masks { ... }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to @alexcrichton, masks are usually subsets of the universal set, so this shouldn't be a problem. I think we should mention though in the macro's comment that the universe is not statically checked (some C bindings are probably weird like that), and in that case it is up to the user to define those outside the macro, eg. static NotInUniverse: Flags = Flags { bits: ??? }.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could auto-generate tests for the validity of the universe and complement functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bjz: Could you give me an example where universe or complement would return an invalid value? How would you test for validity?

pub fn all() -> $BitFlags {
$BitFlags { bits: $($value)|+ }
}

/// Returns the raw value of the flags currently stored.
pub fn bits(&self) -> $T {
self.bits
Expand All @@ -138,6 +147,11 @@ macro_rules! bitflags(
*self == $BitFlags::empty()
}

/// Returns `true` if all flags are currently set.
pub fn is_all(&self) -> bool {
*self == $BitFlags::all()
}

/// Returns `true` if there are flags common to both `self` and `other`.
pub fn intersects(&self, other: $BitFlags) -> bool {
!(self & other).is_empty()
Expand Down Expand Up @@ -182,12 +196,20 @@ macro_rules! bitflags(
$BitFlags { bits: self.bits & !other.bits }
}
}

impl Not<$BitFlags> for $BitFlags {
/// Returns the complement of this set of flags.
#[inline]
fn not(&self) -> $BitFlags {
$BitFlags { bits: !self.bits } & $BitFlags::all()
}
}
)
)

#[cfg(test)]
mod tests {
use ops::{BitOr, BitAnd, Sub};
use ops::{BitOr, BitAnd, Sub, Not};

bitflags!(
flags Flags: u32 {
Expand All @@ -214,6 +236,13 @@ mod tests {
assert!(!FlagABC.is_empty());
}

#[test]
fn test_is_all() {
assert!(Flags::all().is_all());
assert!(!FlagA.is_all());
assert!(FlagABC.is_all());
}

#[test]
fn test_two_empties_do_not_intersect() {
let e1 = Flags::empty();
Expand Down Expand Up @@ -274,5 +303,6 @@ mod tests {
assert!((e1 | e2) == FlagABC); // union
assert!((e1 & e2) == FlagC); // intersection
assert!((e1 - e2) == FlagA); // set difference
assert!(!e2 == FlagA); // set complement
}
}
2 changes: 1 addition & 1 deletion src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ use int;
use iter::Iterator;
use libc;
use mem::transmute;
use ops::{BitOr, BitAnd, Sub};
use ops::{BitOr, BitAnd, Sub, Not};
use option::{Option, Some, None};
use os;
use owned::Box;
Expand Down