(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 }