(index<- )        ./libstd/bitflags.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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.
   4  //
   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.
  10  
  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.
  13  //!
  14  //! The flags should only be defined for integer types, otherwise unexpected
  15  //! type errors may occur at compile time.
  16  //!
  17  //! # Example
  18  //!
  19  //! ~~~rust
  20  //! bitflags!(
  21  //!     flags Flags: u32 {
  22  //!         static FlagA       = 0x00000001,
  23  //!         static FlagB       = 0x00000010,
  24  //!         static FlagC       = 0x00000100,
  25  //!         static FlagABC     = FlagA.bits
  26  //!                            | FlagB.bits
  27  //!                            | FlagC.bits
  28  //!     }
  29  //! )
  30  //!
  31  //! fn main() {
  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  //! }
  38  //! ~~~
  39  //!
  40  //! The generated `struct`s can also be extended with type and trait implementations:
  41  //!
  42  //! ~~~rust
  43  //! use std::fmt;
  44  //!
  45  //! bitflags!(
  46  //!     flags Flags: u32 {
  47  //!         static FlagA   = 0x00000001,
  48  //!         static FlagB   = 0x00000010
  49  //!     }
  50  //! )
  51  //!
  52  //! impl Flags {
  53  //!     pub fn clear(&mut self) {
  54  //!         self.bits = 0;  // The `bits` field can be accessed from within the
  55  //!                         // same module where the `bitflags!` macro was invoked.
  56  //!     }
  57  //! }
  58  //!
  59  //! impl fmt::Show for Flags {
  60  //!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  61  //!         write!(f.buf, "hi!")
  62  //!     }
  63  //! }
  64  //!
  65  //! fn main() {
  66  //!     let mut flags = FlagA | FlagB;
  67  //!     flags.clear();
  68  //!     assert!(flags.is_empty());
  69  //!     assert_eq!(format!("{}", flags).as_slice(), "hi!");
  70  //! }
  71  //! ~~~
  72  //!
  73  //! # Attributes
  74  //!
  75  //! Attributes can be attached to the generated `struct` by placing them
  76  //! before the `flags` keyword.
  77  //!
  78  //! # Derived traits
  79  //!
  80  //! The `Eq` and `Clone` traits are automatically derived for the `struct` using
  81  //! the `deriving` attribute. Additional traits can be derived by providing an
  82  //! explicit `deriving` attribute on `flags`.
  83  //!
  84  //! # Operators
  85  //!
  86  //! The following operator traits are implemented for the generated `struct`:
  87  //!
  88  //! - `BitOr`: union
  89  //! - `BitAnd`: intersection
  90  //! - `Sub`: set difference
  91  //!
  92  //! # Methods
  93  //!
  94  //! The following methods are defined for the generated `struct`:
  95  //!
  96  //! - `empty`: an empty set of flags
  97  //! - `bits`: the raw value of the flags currently stored
  98  //! - `is_empty`: `true` if no flags are currently stored
  99  //! - `intersects`: `true` if there are flags common to both `self` and `other`
 100  //! - `contains`: `true` all of the flags in `other` are contained within `self`
 101  //! - `insert`: inserts the specified flags in-place
 102  //! - `remove`: removes the specified flags in-place
 103  
 104  #![macro_escape]
 105  
 106  #[macro_export]
 107  macro_rules! bitflags(
 108      ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
 109          $($(#[$Flag_attr:meta])static $Flag:ident = $value:expr),+
 110      }) => (
 111          #[deriving(Eq, TotalEq, Clone)]
 112          $(#[$attr])*
 113          pub struct $BitFlags {
 114              bits: $T,
 115          }
 116  
 117          $($(#[$Flag_attr])pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
 118  
 119          impl $BitFlags {
 120              /// Returns an empty set of flags.
 121              pub fn empty() -> $BitFlags {
 122                  $BitFlags { bits: 0 }
 123              }
 124  
 125              /// Returns the raw value of the flags currently stored.
 126              pub fn bits(&self) -> $T {
 127                  self.bits
 128              }
 129  
 130              /// Convert from underlying bit representation. Unsafe because the
 131              /// bits are not guaranteed to represent valid flags.
 132              pub unsafe fn from_bits(bits: $T) -> $BitFlags {
 133                  $BitFlags { bits: bits }
 134              }
 135  
 136              /// Returns `true` if no flags are currently stored.
 137              pub fn is_empty(&self) -> bool {
 138                  *self == $BitFlags::empty()
 139              }
 140  
 141              /// Returns `true` if there are flags common to both `self` and `other`.
 142              pub fn intersects(&self, other: $BitFlags) -> bool {
 143                  !(self & other).is_empty()
 144              }
 145  
 146              /// Returns `true` all of the flags in `other` are contained within `self`.
 147              pub fn contains(&self, other: $BitFlags) -> bool {
 148                  (self & other) == other
 149              }
 150  
 151              /// Inserts the specified flags in-place.
 152              pub fn insert(&mut self, other: $BitFlags) {
 153                  self.bits |= other.bits;
 154              }
 155  
 156              /// Removes the specified flags in-place.
 157              pub fn remove(&mut self, other: $BitFlags) {
 158                  self.bits &= !other.bits;
 159              }
 160          }
 161  
 162          impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
 163              /// Returns the union of the two sets of flags.
 164              #[inline]
 165              fn bitor(&self, other&$BitFlags) -> $BitFlags {
 166                  $BitFlags { bits: self.bits | other.bits }
 167              }
 168          }
 169  
 170          impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
 171              /// Returns the intersection between the two sets of flags.
 172              #[inline]
 173              fn bitand(&self, other&$BitFlags) -> $BitFlags {
 174                  $BitFlags { bits: self.bits & other.bits }
 175              }
 176          }
 177  
 178          impl Sub<$BitFlags, $BitFlags> for $BitFlags {
 179              /// Returns the set difference of the two sets of flags.
 180              #[inline]
 181              fn sub(&self, other&$BitFlags) -> $BitFlags {
 182                  $BitFlags { bits: self.bits & !other.bits }
 183              }
 184          }
 185      )
 186  )
 187  
 188  #[cfg(test)]
 189  mod tests {
 190      use ops::{BitOr, BitAnd, Sub};
 191  
 192      bitflags!(
 193          flags Flags: u32 {
 194              static FlagA       = 0x00000001,
 195              static FlagB       = 0x00000010,
 196              static FlagC       = 0x00000100,
 197              static FlagABC     = FlagA.bits
 198                                 | FlagB.bits
 199                                 | FlagC.bits
 200          }
 201      )
 202  
 203      #[test]
 204      fn test_bits(){
 205          assert_eq!(Flags::empty().bits(), 0x00000000);
 206          assert_eq!(FlagA.bits(), 0x00000001);
 207          assert_eq!(FlagABC.bits(), 0x00000111);
 208      }
 209  
 210      #[test]
 211      fn test_is_empty(){
 212          assert!(Flags::empty().is_empty());
 213          assert!(!FlagA.is_empty());
 214          assert!(!FlagABC.is_empty());
 215      }
 216  
 217      #[test]
 218      fn test_two_empties_do_not_intersect() {
 219          let e1 = Flags::empty();
 220          let e2 = Flags::empty();
 221          assert!(!e1.intersects(e2));
 222      }
 223  
 224      #[test]
 225      fn test_empty_does_not_intersect_with_full() {
 226          let e1 = Flags::empty();
 227          let e2 = FlagABC;
 228          assert!(!e1.intersects(e2));
 229      }
 230  
 231      #[test]
 232      fn test_disjoint_intersects() {
 233          let e1 = FlagA;
 234          let e2 = FlagB;
 235          assert!(!e1.intersects(e2));
 236      }
 237  
 238      #[test]
 239      fn test_overlapping_intersects() {
 240          let e1 = FlagA;
 241          let e2 = FlagA | FlagB;
 242          assert!(e1.intersects(e2));
 243      }
 244  
 245      #[test]
 246      fn test_contains() {
 247          let e1 = FlagA;
 248          let e2 = FlagA | FlagB;
 249          assert!(!e1.contains(e2));
 250          assert!(e2.contains(e1));
 251          assert!(FlagABC.contains(e2));
 252      }
 253  
 254      #[test]
 255      fn test_insert(){
 256          let mut e1 = FlagA;
 257          let e2 = FlagA | FlagB;
 258          e1.insert(e2);
 259          assert!(e1 == e2);
 260      }
 261  
 262      #[test]
 263      fn test_remove(){
 264          let mut e1 = FlagA | FlagB;
 265          let e2 = FlagA | FlagC;
 266          e1.remove(e2);
 267          assert!(e1 == FlagB);
 268      }
 269  
 270      #[test]
 271      fn test_operators() {
 272          let e1 = FlagA | FlagC;
 273          let e2 = FlagB | FlagC;
 274          assert!((e1 | e2) == FlagABC);   // union
 275          assert!((e1 & e2) == FlagC);     // intersection
 276          assert!((e1 - e2) == FlagA);     // set difference
 277      }
 278  }