1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The `bitflags!` macro generates a `struct` that holds a set of C-style
12 //! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
14 //! The flags should only be defined for integer types, otherwise unexpected
15 //! type errors may occur at compile time.
21 //! flags Flags: u32 {
22 //! static FlagA = 0x00000001,
23 //! static FlagB = 0x00000010,
24 //! static FlagC = 0x00000100,
25 //! static FlagABC = FlagA.bits
32 //! let e1 = FlagA | FlagC;
33 //! let e2 = FlagB | FlagC;
34 //! assert!((e1 | e2) == FlagABC); // union
35 //! assert!((e1 & e2) == FlagC); // intersection
36 //! assert!((e1 - e2) == FlagA); // set difference
37 //! assert!(!e2 == FlagA); // set complement
41 //! The generated `struct`s can also be extended with type and trait implementations:
47 //! flags Flags: u32 {
48 //! static FlagA = 0x00000001,
49 //! static FlagB = 0x00000010
54 //! pub fn clear(&mut self) {
55 //! self.bits = 0; // The `bits` field can be accessed from within the
56 //! // same module where the `bitflags!` macro was invoked.
60 //! impl fmt::Show for Flags {
61 //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 //! let mut flags = FlagA | FlagB;
69 //! assert!(flags.is_empty());
70 //! assert_eq!(format!("{}", flags).as_slice(), "hi!");
76 //! Attributes can be attached to the generated `struct` by placing them
77 //! before the `flags` keyword.
81 //! The `PartialEq` and `Clone` traits are automatically derived for the `struct` using
82 //! the `deriving` attribute. Additional traits can be derived by providing an
83 //! explicit `deriving` attribute on `flags`.
87 //! The following operator traits are implemented for the generated `struct`:
90 //! - `BitAnd`: intersection
91 //! - `Sub`: set difference
92 //! - `Not`: set complement
96 //! The following methods are defined for the generated `struct`:
98 //! - `empty`: an empty set of flags
99 //! - `all`: the set of all flags
100 //! - `bits`: the raw value of the flags currently stored
101 //! - `is_empty`: `true` if no flags are currently stored
102 //! - `is_all`: `true` if all flags are currently set
103 //! - `intersects`: `true` if there are flags common to both `self` and `other`
104 //! - `contains`: `true` all of the flags in `other` are contained within `self`
105 //! - `insert`: inserts the specified flags in-place
106 //! - `remove`: removes the specified flags in-place
112 macro_rules! bitflags(
113 ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
114 $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
116 #[deriving(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
118 pub struct $BitFlags {
122 $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
125 /// Returns an empty set of flags.
126 pub fn empty() -> $BitFlags {
127 $BitFlags { bits: 0 }
130 /// Returns the set containing all flags.
131 pub fn all() -> $BitFlags {
132 $BitFlags { bits: $($value)|+ }
135 /// Returns the raw value of the flags currently stored.
136 pub fn bits(&self) -> $T {
140 /// Convert from underlying bit representation, unless that
141 /// representation contains bits that do not correspond to a flag.
142 pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
143 if (bits & !$BitFlags::all().bits()) != 0 {
146 ::std::option::Some($BitFlags { bits: bits })
150 /// Convert from underlying bit representation, dropping any bits
151 /// that do not correspond to flags.
152 pub fn from_bits_truncate(bits: $T) -> $BitFlags {
153 $BitFlags { bits: bits } & $BitFlags::all()
156 /// Returns `true` if no flags are currently stored.
157 pub fn is_empty(&self) -> bool {
158 *self == $BitFlags::empty()
161 /// Returns `true` if all flags are currently set.
162 pub fn is_all(&self) -> bool {
163 *self == $BitFlags::all()
166 /// Returns `true` if there are flags common to both `self` and `other`.
167 pub fn intersects(&self, other: $BitFlags) -> bool {
168 !(self & other).is_empty()
171 /// Returns `true` all of the flags in `other` are contained within `self`.
172 pub fn contains(&self, other: $BitFlags) -> bool {
173 (self & other) == other
176 /// Inserts the specified flags in-place.
177 pub fn insert(&mut self, other: $BitFlags) {
178 self.bits |= other.bits;
181 /// Removes the specified flags in-place.
182 pub fn remove(&mut self, other: $BitFlags) {
183 self.bits &= !other.bits;
187 impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
188 /// Returns the union of the two sets of flags.
190 fn bitor(&self, other: &$BitFlags) -> $BitFlags {
191 $BitFlags { bits: self.bits | other.bits }
195 impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
196 /// Returns the intersection between the two sets of flags.
198 fn bitand(&self, other: &$BitFlags) -> $BitFlags {
199 $BitFlags { bits: self.bits & other.bits }
203 impl Sub<$BitFlags, $BitFlags> for $BitFlags {
204 /// Returns the set difference of the two sets of flags.
206 fn sub(&self, other: &$BitFlags) -> $BitFlags {
207 $BitFlags { bits: self.bits & !other.bits }
211 impl Not<$BitFlags> for $BitFlags {
212 /// Returns the complement of this set of flags.
214 fn not(&self) -> $BitFlags {
215 $BitFlags { bits: !self.bits } & $BitFlags::all()
224 use option::{Some, None};
225 use ops::{BitOr, BitAnd, Sub, Not};
229 static FlagA = 0x00000001,
230 static FlagB = 0x00000010,
231 static FlagC = 0x00000100,
232 static FlagABC = FlagA.bits
240 assert_eq!(Flags::empty().bits(), 0x00000000);
241 assert_eq!(FlagA.bits(), 0x00000001);
242 assert_eq!(FlagABC.bits(), 0x00000111);
246 fn test_from_bits() {
247 assert!(Flags::from_bits(0) == Some(Flags::empty()));
248 assert!(Flags::from_bits(0x1) == Some(FlagA));
249 assert!(Flags::from_bits(0x10) == Some(FlagB));
250 assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
251 assert!(Flags::from_bits(0x1000) == None);
255 fn test_from_bits_truncate() {
256 assert!(Flags::from_bits_truncate(0) == Flags::empty());
257 assert!(Flags::from_bits_truncate(0x1) == FlagA);
258 assert!(Flags::from_bits_truncate(0x10) == FlagB);
259 assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
260 assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
261 assert!(Flags::from_bits_truncate(0x1001) == FlagA);
266 assert!(Flags::empty().is_empty());
267 assert!(!FlagA.is_empty());
268 assert!(!FlagABC.is_empty());
273 assert!(Flags::all().is_all());
274 assert!(!FlagA.is_all());
275 assert!(FlagABC.is_all());
279 fn test_two_empties_do_not_intersect() {
280 let e1 = Flags::empty();
281 let e2 = Flags::empty();
282 assert!(!e1.intersects(e2));
286 fn test_empty_does_not_intersect_with_full() {
287 let e1 = Flags::empty();
289 assert!(!e1.intersects(e2));
293 fn test_disjoint_intersects() {
296 assert!(!e1.intersects(e2));
300 fn test_overlapping_intersects() {
302 let e2 = FlagA | FlagB;
303 assert!(e1.intersects(e2));
309 let e2 = FlagA | FlagB;
310 assert!(!e1.contains(e2));
311 assert!(e2.contains(e1));
312 assert!(FlagABC.contains(e2));
318 let e2 = FlagA | FlagB;
325 let mut e1 = FlagA | FlagB;
326 let e2 = FlagA | FlagC;
328 assert!(e1 == FlagB);
332 fn test_operators() {
333 let e1 = FlagA | FlagC;
334 let e2 = FlagB | FlagC;
335 assert!((e1 | e2) == FlagABC); // union
336 assert!((e1 & e2) == FlagC); // intersection
337 assert!((e1 - e2) == FlagA); // set difference
338 assert!(!e2 == FlagA); // set complement
343 let mut a = Flags::empty();
344 let mut b = Flags::empty();
346 assert!(!(a < b) && !(b < a));
350 assert!(!(a < b) && b < a);
357 let mut a = Flags::empty();
358 let mut b = Flags::empty();
360 assert!(a <= b && a >= b);
362 assert!(a > b && a >= b);
363 assert!(b < a && b <= a);
365 assert!(b > a && b >= a);
366 assert!(a < b && a <= b);
371 let mut x = Flags::empty();
372 let mut y = Flags::empty();
373 assert!(hash::hash(&x) == hash::hash(&y));
376 assert!(hash::hash(&x) == hash::hash(&y));