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