]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
c34b1796 AL |
11 | |
12 | // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) | |
13 | #![cfg_attr(stage0, feature(custom_attribute))] | |
85aaf69f | 14 | #![crate_name = "rustc_bitflags"] |
d9579d0f | 15 | #![feature(associated_consts)] |
85aaf69f SL |
16 | #![feature(staged_api)] |
17 | #![staged_api] | |
18 | #![crate_type = "rlib"] | |
19 | #![feature(no_std)] | |
20 | #![no_std] | |
21 | #![unstable(feature = "rustc_private")] | |
62682a34 | 22 | #![cfg_attr(test, feature(hash_default))] |
1a4d82fc JJ |
23 | |
24 | //! A typesafe bitmask flag generator. | |
25 | ||
85aaf69f SL |
26 | #[cfg(test)] #[macro_use] extern crate std; |
27 | ||
1a4d82fc JJ |
28 | /// The `bitflags!` macro generates a `struct` that holds a set of C-style |
29 | /// bitmask flags. It is useful for creating typesafe wrappers for C APIs. | |
30 | /// | |
31 | /// The flags should only be defined for integer types, otherwise unexpected | |
32 | /// type errors may occur at compile time. | |
33 | /// | |
c34b1796 | 34 | /// # Examples |
1a4d82fc JJ |
35 | /// |
36 | /// ```{.rust} | |
c1a9b12d SL |
37 | /// #![feature(rustc_private)] |
38 | /// #![feature(associated_consts)] | |
85aaf69f SL |
39 | /// #[macro_use] extern crate rustc_bitflags; |
40 | /// | |
1a4d82fc JJ |
41 | /// bitflags! { |
42 | /// flags Flags: u32 { | |
43 | /// const FLAG_A = 0b00000001, | |
44 | /// const FLAG_B = 0b00000010, | |
45 | /// const FLAG_C = 0b00000100, | |
d9579d0f AL |
46 | /// const FLAG_ABC = Flags::FLAG_A.bits |
47 | /// | Flags::FLAG_B.bits | |
48 | /// | Flags::FLAG_C.bits, | |
1a4d82fc JJ |
49 | /// } |
50 | /// } | |
51 | /// | |
52 | /// fn main() { | |
d9579d0f AL |
53 | /// let e1 = Flags::FLAG_A | Flags::FLAG_C; |
54 | /// let e2 = Flags::FLAG_B | Flags::FLAG_C; | |
55 | /// assert!((e1 | e2) == Flags::FLAG_ABC); // union | |
56 | /// assert!((e1 & e2) == Flags::FLAG_C); // intersection | |
57 | /// assert!((e1 - e2) == Flags::FLAG_A); // set difference | |
58 | /// assert!(!e2 == Flags::FLAG_A); // set complement | |
1a4d82fc JJ |
59 | /// } |
60 | /// ``` | |
61 | /// | |
62 | /// The generated `struct`s can also be extended with type and trait implementations: | |
63 | /// | |
64 | /// ```{.rust} | |
c1a9b12d | 65 | /// #![feature(rustc_private)] |
85aaf69f SL |
66 | /// #[macro_use] extern crate rustc_bitflags; |
67 | /// | |
1a4d82fc JJ |
68 | /// use std::fmt; |
69 | /// | |
70 | /// bitflags! { | |
71 | /// flags Flags: u32 { | |
72 | /// const FLAG_A = 0b00000001, | |
73 | /// const FLAG_B = 0b00000010, | |
74 | /// } | |
75 | /// } | |
76 | /// | |
77 | /// impl Flags { | |
78 | /// pub fn clear(&mut self) { | |
79 | /// self.bits = 0; // The `bits` field can be accessed from within the | |
80 | /// // same module where the `bitflags!` macro was invoked. | |
81 | /// } | |
82 | /// } | |
83 | /// | |
85aaf69f | 84 | /// impl fmt::Debug for Flags { |
1a4d82fc JJ |
85 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
86 | /// write!(f, "hi!") | |
87 | /// } | |
88 | /// } | |
89 | /// | |
90 | /// fn main() { | |
d9579d0f | 91 | /// let mut flags = Flags::FLAG_A | Flags::FLAG_B; |
1a4d82fc JJ |
92 | /// flags.clear(); |
93 | /// assert!(flags.is_empty()); | |
c34b1796 | 94 | /// assert_eq!(format!("{:?}", flags), "hi!"); |
1a4d82fc JJ |
95 | /// } |
96 | /// ``` | |
97 | /// | |
98 | /// # Attributes | |
99 | /// | |
100 | /// Attributes can be attached to the generated `struct` by placing them | |
101 | /// before the `flags` keyword. | |
102 | /// | |
103 | /// # Derived traits | |
104 | /// | |
105 | /// The `PartialEq` and `Clone` traits are automatically derived for the `struct` using | |
106 | /// the `deriving` attribute. Additional traits can be derived by providing an | |
107 | /// explicit `deriving` attribute on `flags`. | |
108 | /// | |
109 | /// # Operators | |
110 | /// | |
111 | /// The following operator traits are implemented for the generated `struct`: | |
112 | /// | |
113 | /// - `BitOr`: union | |
114 | /// - `BitAnd`: intersection | |
115 | /// - `BitXor`: toggle | |
116 | /// - `Sub`: set difference | |
117 | /// - `Not`: set complement | |
118 | /// | |
119 | /// # Methods | |
120 | /// | |
121 | /// The following methods are defined for the generated `struct`: | |
122 | /// | |
123 | /// - `empty`: an empty set of flags | |
124 | /// - `all`: the set of all flags | |
125 | /// - `bits`: the raw value of the flags currently stored | |
126 | /// - `from_bits`: convert from underlying bit representation, unless that | |
127 | /// representation contains bits that do not correspond to a flag | |
128 | /// - `from_bits_truncate`: convert from underlying bit representation, dropping | |
129 | /// any bits that do not correspond to flags | |
130 | /// - `is_empty`: `true` if no flags are currently stored | |
131 | /// - `is_all`: `true` if all flags are currently set | |
132 | /// - `intersects`: `true` if there are flags common to both `self` and `other` | |
133 | /// - `contains`: `true` all of the flags in `other` are contained within `self` | |
134 | /// - `insert`: inserts the specified flags in-place | |
135 | /// - `remove`: removes the specified flags in-place | |
136 | /// - `toggle`: the specified flags will be inserted if not present, and removed | |
137 | /// if they are. | |
138 | #[macro_export] | |
139 | macro_rules! bitflags { | |
140 | ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { | |
141 | $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+ | |
142 | }) => { | |
143 | #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] | |
144 | $(#[$attr])* | |
145 | pub struct $BitFlags { | |
146 | bits: $T, | |
147 | } | |
148 | ||
1a4d82fc | 149 | impl $BitFlags { |
d9579d0f AL |
150 | $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+ |
151 | ||
1a4d82fc JJ |
152 | /// Returns an empty set of flags. |
153 | #[inline] | |
154 | pub fn empty() -> $BitFlags { | |
155 | $BitFlags { bits: 0 } | |
156 | } | |
157 | ||
158 | /// Returns the set containing all flags. | |
159 | #[inline] | |
160 | pub fn all() -> $BitFlags { | |
161 | $BitFlags { bits: $($value)|+ } | |
162 | } | |
163 | ||
164 | /// Returns the raw value of the flags currently stored. | |
165 | #[inline] | |
166 | pub fn bits(&self) -> $T { | |
167 | self.bits | |
168 | } | |
169 | ||
170 | /// Convert from underlying bit representation, unless that | |
171 | /// representation contains bits that do not correspond to a flag. | |
172 | #[inline] | |
173 | pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> { | |
174 | if (bits & !$BitFlags::all().bits()) != 0 { | |
175 | ::std::option::Option::None | |
176 | } else { | |
177 | ::std::option::Option::Some($BitFlags { bits: bits }) | |
178 | } | |
179 | } | |
180 | ||
181 | /// Convert from underlying bit representation, dropping any bits | |
182 | /// that do not correspond to flags. | |
183 | #[inline] | |
184 | pub fn from_bits_truncate(bits: $T) -> $BitFlags { | |
185 | $BitFlags { bits: bits } & $BitFlags::all() | |
186 | } | |
187 | ||
188 | /// Returns `true` if no flags are currently stored. | |
189 | #[inline] | |
190 | pub fn is_empty(&self) -> bool { | |
191 | *self == $BitFlags::empty() | |
192 | } | |
193 | ||
194 | /// Returns `true` if all flags are currently set. | |
195 | #[inline] | |
196 | pub fn is_all(&self) -> bool { | |
197 | *self == $BitFlags::all() | |
198 | } | |
199 | ||
200 | /// Returns `true` if there are flags common to both `self` and `other`. | |
201 | #[inline] | |
202 | pub fn intersects(&self, other: $BitFlags) -> bool { | |
203 | !(*self & other).is_empty() | |
204 | } | |
205 | ||
206 | /// Returns `true` all of the flags in `other` are contained within `self`. | |
207 | #[inline] | |
208 | pub fn contains(&self, other: $BitFlags) -> bool { | |
209 | (*self & other) == other | |
210 | } | |
211 | ||
212 | /// Inserts the specified flags in-place. | |
213 | #[inline] | |
214 | pub fn insert(&mut self, other: $BitFlags) { | |
215 | self.bits |= other.bits; | |
216 | } | |
217 | ||
218 | /// Removes the specified flags in-place. | |
219 | #[inline] | |
220 | pub fn remove(&mut self, other: $BitFlags) { | |
221 | self.bits &= !other.bits; | |
222 | } | |
223 | ||
224 | /// Toggles the specified flags in-place. | |
225 | #[inline] | |
226 | pub fn toggle(&mut self, other: $BitFlags) { | |
227 | self.bits ^= other.bits; | |
228 | } | |
229 | } | |
230 | ||
231 | impl ::std::ops::BitOr for $BitFlags { | |
232 | type Output = $BitFlags; | |
233 | ||
234 | /// Returns the union of the two sets of flags. | |
235 | #[inline] | |
236 | fn bitor(self, other: $BitFlags) -> $BitFlags { | |
237 | $BitFlags { bits: self.bits | other.bits } | |
238 | } | |
239 | } | |
240 | ||
241 | impl ::std::ops::BitXor for $BitFlags { | |
242 | type Output = $BitFlags; | |
243 | ||
244 | /// Returns the left flags, but with all the right flags toggled. | |
245 | #[inline] | |
246 | fn bitxor(self, other: $BitFlags) -> $BitFlags { | |
247 | $BitFlags { bits: self.bits ^ other.bits } | |
248 | } | |
249 | } | |
250 | ||
251 | impl ::std::ops::BitAnd for $BitFlags { | |
252 | type Output = $BitFlags; | |
253 | ||
254 | /// Returns the intersection between the two sets of flags. | |
255 | #[inline] | |
256 | fn bitand(self, other: $BitFlags) -> $BitFlags { | |
257 | $BitFlags { bits: self.bits & other.bits } | |
258 | } | |
259 | } | |
260 | ||
261 | impl ::std::ops::Sub for $BitFlags { | |
262 | type Output = $BitFlags; | |
263 | ||
264 | /// Returns the set difference of the two sets of flags. | |
265 | #[inline] | |
266 | fn sub(self, other: $BitFlags) -> $BitFlags { | |
267 | $BitFlags { bits: self.bits & !other.bits } | |
268 | } | |
269 | } | |
270 | ||
271 | impl ::std::ops::Not for $BitFlags { | |
272 | type Output = $BitFlags; | |
273 | ||
274 | /// Returns the complement of this set of flags. | |
275 | #[inline] | |
276 | fn not(self) -> $BitFlags { | |
277 | $BitFlags { bits: !self.bits } & $BitFlags::all() | |
278 | } | |
279 | } | |
280 | }; | |
281 | ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty { | |
282 | $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+, | |
283 | }) => { | |
284 | bitflags! { | |
285 | $(#[$attr])* | |
286 | flags $BitFlags: $T { | |
287 | $($(#[$Flag_attr])* const $Flag = $value),+ | |
288 | } | |
289 | } | |
290 | }; | |
291 | } | |
292 | ||
85aaf69f SL |
293 | // This is a no_std crate. So the test code's invocation of #[derive] etc, via |
294 | // bitflags!, will use names from the underlying crates. | |
295 | #[cfg(test)] | |
296 | mod core { | |
297 | pub use std::{fmt, hash, clone, cmp, marker, option}; | |
298 | } | |
299 | ||
1a4d82fc JJ |
300 | #[cfg(test)] |
301 | #[allow(non_upper_case_globals)] | |
302 | mod tests { | |
85aaf69f SL |
303 | use std::hash::{self, SipHasher}; |
304 | use std::option::Option::{Some, None}; | |
1a4d82fc JJ |
305 | |
306 | bitflags! { | |
307 | #[doc = "> The first principle is that you must not fool yourself — and"] | |
308 | #[doc = "> you are the easiest person to fool."] | |
309 | #[doc = "> "] | |
310 | #[doc = "> - Richard Feynman"] | |
311 | flags Flags: u32 { | |
312 | const FlagA = 0b00000001, | |
313 | #[doc = "<pcwalton> macros are way better at generating code than trans is"] | |
314 | const FlagB = 0b00000010, | |
315 | const FlagC = 0b00000100, | |
316 | #[doc = "* cmr bed"] | |
317 | #[doc = "* strcat table"] | |
318 | #[doc = "<strcat> wait what?"] | |
d9579d0f AL |
319 | const FlagABC = Flags::FlagA.bits |
320 | | Flags::FlagB.bits | |
321 | | Flags::FlagC.bits, | |
1a4d82fc JJ |
322 | } |
323 | } | |
324 | ||
325 | bitflags! { | |
326 | flags AnotherSetOfFlags: i8 { | |
c34b1796 | 327 | const AnotherFlag = -1, |
1a4d82fc JJ |
328 | } |
329 | } | |
330 | ||
331 | #[test] | |
332 | fn test_bits(){ | |
333 | assert_eq!(Flags::empty().bits(), 0b00000000); | |
d9579d0f AL |
334 | assert_eq!(Flags::FlagA.bits(), 0b00000001); |
335 | assert_eq!(Flags::FlagABC.bits(), 0b00000111); | |
1a4d82fc JJ |
336 | |
337 | assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); | |
d9579d0f | 338 | assert_eq!(AnotherSetOfFlags::AnotherFlag.bits(), !0); |
1a4d82fc JJ |
339 | } |
340 | ||
341 | #[test] | |
342 | fn test_from_bits() { | |
343 | assert!(Flags::from_bits(0) == Some(Flags::empty())); | |
d9579d0f AL |
344 | assert!(Flags::from_bits(0b1) == Some(Flags::FlagA)); |
345 | assert!(Flags::from_bits(0b10) == Some(Flags::FlagB)); | |
346 | assert!(Flags::from_bits(0b11) == Some(Flags::FlagA | Flags::FlagB)); | |
1a4d82fc JJ |
347 | assert!(Flags::from_bits(0b1000) == None); |
348 | ||
d9579d0f | 349 | assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherSetOfFlags::AnotherFlag)); |
1a4d82fc JJ |
350 | } |
351 | ||
352 | #[test] | |
353 | fn test_from_bits_truncate() { | |
354 | assert!(Flags::from_bits_truncate(0) == Flags::empty()); | |
d9579d0f AL |
355 | assert!(Flags::from_bits_truncate(0b1) == Flags::FlagA); |
356 | assert!(Flags::from_bits_truncate(0b10) == Flags::FlagB); | |
357 | assert!(Flags::from_bits_truncate(0b11) == (Flags::FlagA | Flags::FlagB)); | |
1a4d82fc | 358 | assert!(Flags::from_bits_truncate(0b1000) == Flags::empty()); |
d9579d0f | 359 | assert!(Flags::from_bits_truncate(0b1001) == Flags::FlagA); |
1a4d82fc | 360 | |
c34b1796 | 361 | assert!(AnotherSetOfFlags::from_bits_truncate(0) == AnotherSetOfFlags::empty()); |
1a4d82fc JJ |
362 | } |
363 | ||
364 | #[test] | |
365 | fn test_is_empty(){ | |
366 | assert!(Flags::empty().is_empty()); | |
d9579d0f AL |
367 | assert!(!Flags::FlagA.is_empty()); |
368 | assert!(!Flags::FlagABC.is_empty()); | |
1a4d82fc | 369 | |
d9579d0f | 370 | assert!(!AnotherSetOfFlags::AnotherFlag.is_empty()); |
1a4d82fc JJ |
371 | } |
372 | ||
373 | #[test] | |
374 | fn test_is_all() { | |
375 | assert!(Flags::all().is_all()); | |
d9579d0f AL |
376 | assert!(!Flags::FlagA.is_all()); |
377 | assert!(Flags::FlagABC.is_all()); | |
1a4d82fc | 378 | |
d9579d0f | 379 | assert!(AnotherSetOfFlags::AnotherFlag.is_all()); |
1a4d82fc JJ |
380 | } |
381 | ||
382 | #[test] | |
383 | fn test_two_empties_do_not_intersect() { | |
384 | let e1 = Flags::empty(); | |
385 | let e2 = Flags::empty(); | |
386 | assert!(!e1.intersects(e2)); | |
387 | ||
d9579d0f | 388 | assert!(AnotherSetOfFlags::AnotherFlag.intersects(AnotherSetOfFlags::AnotherFlag)); |
1a4d82fc JJ |
389 | } |
390 | ||
391 | #[test] | |
392 | fn test_empty_does_not_intersect_with_full() { | |
393 | let e1 = Flags::empty(); | |
d9579d0f | 394 | let e2 = Flags::FlagABC; |
1a4d82fc JJ |
395 | assert!(!e1.intersects(e2)); |
396 | } | |
397 | ||
398 | #[test] | |
399 | fn test_disjoint_intersects() { | |
d9579d0f AL |
400 | let e1 = Flags::FlagA; |
401 | let e2 = Flags::FlagB; | |
1a4d82fc JJ |
402 | assert!(!e1.intersects(e2)); |
403 | } | |
404 | ||
405 | #[test] | |
406 | fn test_overlapping_intersects() { | |
d9579d0f AL |
407 | let e1 = Flags::FlagA; |
408 | let e2 = Flags::FlagA | Flags::FlagB; | |
1a4d82fc JJ |
409 | assert!(e1.intersects(e2)); |
410 | } | |
411 | ||
412 | #[test] | |
413 | fn test_contains() { | |
d9579d0f AL |
414 | let e1 = Flags::FlagA; |
415 | let e2 = Flags::FlagA | Flags::FlagB; | |
1a4d82fc JJ |
416 | assert!(!e1.contains(e2)); |
417 | assert!(e2.contains(e1)); | |
d9579d0f | 418 | assert!(Flags::FlagABC.contains(e2)); |
1a4d82fc | 419 | |
d9579d0f | 420 | assert!(AnotherSetOfFlags::AnotherFlag.contains(AnotherSetOfFlags::AnotherFlag)); |
1a4d82fc JJ |
421 | } |
422 | ||
423 | #[test] | |
424 | fn test_insert(){ | |
d9579d0f AL |
425 | let mut e1 = Flags::FlagA; |
426 | let e2 = Flags::FlagA | Flags::FlagB; | |
1a4d82fc JJ |
427 | e1.insert(e2); |
428 | assert!(e1 == e2); | |
429 | ||
430 | let mut e3 = AnotherSetOfFlags::empty(); | |
d9579d0f AL |
431 | e3.insert(AnotherSetOfFlags::AnotherFlag); |
432 | assert!(e3 == AnotherSetOfFlags::AnotherFlag); | |
1a4d82fc JJ |
433 | } |
434 | ||
435 | #[test] | |
436 | fn test_remove(){ | |
d9579d0f AL |
437 | let mut e1 = Flags::FlagA | Flags::FlagB; |
438 | let e2 = Flags::FlagA | Flags::FlagC; | |
1a4d82fc | 439 | e1.remove(e2); |
d9579d0f | 440 | assert!(e1 == Flags::FlagB); |
1a4d82fc | 441 | |
d9579d0f AL |
442 | let mut e3 = AnotherSetOfFlags::AnotherFlag; |
443 | e3.remove(AnotherSetOfFlags::AnotherFlag); | |
1a4d82fc JJ |
444 | assert!(e3 == AnotherSetOfFlags::empty()); |
445 | } | |
446 | ||
447 | #[test] | |
448 | fn test_operators() { | |
d9579d0f AL |
449 | let e1 = Flags::FlagA | Flags::FlagC; |
450 | let e2 = Flags::FlagB | Flags::FlagC; | |
451 | assert!((e1 | e2) == Flags::FlagABC); // union | |
452 | assert!((e1 & e2) == Flags::FlagC); // intersection | |
453 | assert!((e1 - e2) == Flags::FlagA); // set difference | |
454 | assert!(!e2 == Flags::FlagA); // set complement | |
455 | assert!(e1 ^ e2 == Flags::FlagA | Flags::FlagB); // toggle | |
1a4d82fc JJ |
456 | let mut e3 = e1; |
457 | e3.toggle(e2); | |
d9579d0f | 458 | assert!(e3 == Flags::FlagA | Flags::FlagB); |
1a4d82fc JJ |
459 | |
460 | let mut m4 = AnotherSetOfFlags::empty(); | |
461 | m4.toggle(AnotherSetOfFlags::empty()); | |
462 | assert!(m4 == AnotherSetOfFlags::empty()); | |
463 | } | |
464 | ||
465 | #[test] | |
466 | fn test_lt() { | |
467 | let mut a = Flags::empty(); | |
468 | let mut b = Flags::empty(); | |
469 | ||
470 | assert!(!(a < b) && !(b < a)); | |
d9579d0f | 471 | b = Flags::FlagB; |
1a4d82fc | 472 | assert!(a < b); |
d9579d0f | 473 | a = Flags::FlagC; |
1a4d82fc | 474 | assert!(!(a < b) && b < a); |
d9579d0f | 475 | b = Flags::FlagC | Flags::FlagB; |
1a4d82fc JJ |
476 | assert!(a < b); |
477 | } | |
478 | ||
479 | #[test] | |
480 | fn test_ord() { | |
481 | let mut a = Flags::empty(); | |
482 | let mut b = Flags::empty(); | |
483 | ||
484 | assert!(a <= b && a >= b); | |
d9579d0f | 485 | a = Flags::FlagA; |
1a4d82fc JJ |
486 | assert!(a > b && a >= b); |
487 | assert!(b < a && b <= a); | |
d9579d0f | 488 | b = Flags::FlagB; |
1a4d82fc JJ |
489 | assert!(b > a && b >= a); |
490 | assert!(a < b && a <= b); | |
491 | } | |
492 | ||
493 | #[test] | |
494 | fn test_hash() { | |
495 | let mut x = Flags::empty(); | |
496 | let mut y = Flags::empty(); | |
497 | assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y)); | |
498 | x = Flags::all(); | |
d9579d0f | 499 | y = Flags::FlagABC; |
1a4d82fc JJ |
500 | assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y)); |
501 | } | |
502 | } |