bitflags_core/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#![feature(no_std)]
12#![no_std]
13
14//! A typesafe bitmask flag generator.
15
16/// The `bitflags!` macro generates a `struct` that holds a set of C-style
17/// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
18///
19/// The flags should only be defined for integer types, otherwise unexpected
20/// type errors may occur at compile time.
21///
22/// # Example
23///
24/// ```{.rust}
25/// #[macro_use]
26/// extern crate bitflags;
27///
28/// bitflags! {
29/// flags Flags: u32 {
30/// const FLAG_A = 0b00000001,
31/// const FLAG_B = 0b00000010,
32/// const FLAG_C = 0b00000100,
33/// const FLAG_ABC = FLAG_A.bits
34/// | FLAG_B.bits
35/// | FLAG_C.bits,
36/// }
37/// }
38///
39/// fn main() {
40/// let e1 = FLAG_A | FLAG_C;
41/// let e2 = FLAG_B | FLAG_C;
42/// assert!((e1 | e2) == FLAG_ABC); // union
43/// assert!((e1 & e2) == FLAG_C); // intersection
44/// assert!((e1 - e2) == FLAG_A); // set difference
45/// assert!(!e2 == FLAG_A); // set complement
46/// }
47/// ```
48///
49/// The generated `struct`s can also be extended with type and trait
50/// implementations:
51///
52/// ```{.rust}
53/// #[macro_use]
54/// extern crate bitflags;
55///
56/// use std::fmt;
57///
58/// bitflags! {
59/// flags Flags: u32 {
60/// const FLAG_A = 0b00000001,
61/// const FLAG_B = 0b00000010,
62/// }
63/// }
64///
65/// impl Flags {
66/// pub fn clear(&mut self) {
67/// self.bits = 0; // The `bits` field can be accessed from within the
68/// // same module where the `bitflags!` macro was invoked.
69/// }
70/// }
71///
72/// impl fmt::Display for Flags {
73/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74/// write!(f, "hi!")
75/// }
76/// }
77///
78/// fn main() {
79/// let mut flags = FLAG_A | FLAG_B;
80/// flags.clear();
81/// assert!(flags.is_empty());
82/// assert_eq!(format!("{}", flags), "hi!");
83/// assert_eq!(format!("{:?}", FLAG_A | FLAG_B), "FLAG_A | FLAG_B");
84/// assert_eq!(format!("{:?}", FLAG_B), "FLAG_B");
85/// }
86/// ```
87///
88/// # Attributes
89///
90/// Attributes can be attached to the generated `struct` by placing them
91/// before the `flags` keyword.
92///
93/// # Trait implementations
94///
95/// The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
96/// traits automatically derived for the `struct` using the `derive` attribute.
97/// Additional traits can be derived by providing an explicit `derive`
98/// attribute on `flags`.
99///
100/// The `FromIterator` trait is implemented for the `struct`, too, calculating
101/// the union of the instances of the `struct` iterated over.
102///
103/// The `Debug` trait is also implemented by displaying the bits value of the
104/// internal struct.
105///
106/// ## Operators
107///
108/// The following operator traits are implemented for the generated `struct`:
109///
110/// - `BitOr`: union
111/// - `BitAnd`: intersection
112/// - `BitXor`: toggle
113/// - `Sub`: set difference
114/// - `Not`: set complement
115///
116/// # Methods
117///
118/// The following methods are defined for the generated `struct`:
119///
120/// - `empty`: an empty set of flags
121/// - `all`: the set of all flags
122/// - `bits`: the raw value of the flags currently stored
123/// - `from_bits`: convert from underlying bit representation, unless that
124/// representation contains bits that do not correspond to a flag
125/// - `from_bits_truncate`: convert from underlying bit representation, dropping
126/// any bits that do not correspond to flags
127/// - `is_empty`: `true` if no flags are currently stored
128/// - `is_all`: `true` if all flags are currently set
129/// - `intersects`: `true` if there are flags common to both `self` and `other`
130/// - `contains`: `true` all of the flags in `other` are contained within `self`
131/// - `insert`: inserts the specified flags in-place
132/// - `remove`: removes the specified flags in-place
133/// - `toggle`: the specified flags will be inserted if not present, and removed
134/// if they are.
135#[macro_export]
136macro_rules! bitflags {
137 ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
138 $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
139 }) => {
140 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
141 $(#[$attr])*
142 pub struct $BitFlags {
143 bits: $T,
144 }
145
146 $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+
147
148 impl ::core::fmt::Debug for $BitFlags {
149 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
150 // This convoluted approach is to handle #[cfg]-based flag
151 // omission correctly. Some of the $Flag variants may not be
152 // defined in this module so we create an inner module which
153 // defines *all* flags to the value of 0. Afterwards when the
154 // glob import variants from the outer module, shadowing all
155 // defined variants, leaving only the undefined ones with the
156 // bit value of 0.
157 #[allow(dead_code)]
158 mod dummy {
159 // Now we define the "undefined" versions of the flags.
160 // This way, all the names exist, even if some are #[cfg]ed
161 // out.
162 $(const $Flag: super::$BitFlags = super::$BitFlags { bits: 0 };)+
163
164 #[inline]
165 pub fn fmt(self_: &super::$BitFlags,
166 f: &mut ::core::fmt::Formatter)
167 -> ::core::fmt::Result {
168 // Now we import the real values for the flags.
169 // Only ones that are #[cfg]ed out will be 0.
170 use super::*;
171
172 let mut _first = true;
173 $(
174 // $Flag.bits == 0 means that $Flag doesn't exist
175 if $Flag.bits != 0 && self_.contains($Flag) {
176 if !_first {
177 try!(f.write_str(" | "));
178 }
179 _first = false;
180 try!(f.write_str(stringify!($Flag)));
181 }
182 )+
183 Ok(())
184 }
185 }
186 dummy::fmt(self, f)
187 }
188 }
189
190 #[allow(dead_code)]
191 impl $BitFlags {
192 /// Returns an empty set of flags.
193 #[inline]
194 pub fn empty() -> $BitFlags {
195 $BitFlags { bits: 0 }
196 }
197
198 /// Returns the set containing all flags.
199 #[inline]
200 pub fn all() -> $BitFlags {
201 // See above `dummy` module for why this approach is taken.
202 #[allow(dead_code)]
203 mod dummy {
204 $(const $Flag: super::$BitFlags = super::$BitFlags { bits: 0 };)+
205
206 #[inline]
207 pub fn all() -> super::$BitFlags {
208 use super::*;
209 $BitFlags { bits: $($Flag.bits)|+ }
210 }
211 }
212 dummy::all()
213 }
214
215 /// Returns the raw value of the flags currently stored.
216 #[inline]
217 pub fn bits(&self) -> $T {
218 self.bits
219 }
220
221 /// Convert from underlying bit representation, unless that
222 /// representation contains bits that do not correspond to a flag.
223 #[inline]
224 pub fn from_bits(bits: $T) -> ::core::option::Option<$BitFlags> {
225 if (bits & !$BitFlags::all().bits()) != 0 {
226 ::core::option::Option::None
227 } else {
228 ::core::option::Option::Some($BitFlags { bits: bits })
229 }
230 }
231
232 /// Convert from underlying bit representation, dropping any bits
233 /// that do not correspond to flags.
234 #[inline]
235 pub fn from_bits_truncate(bits: $T) -> $BitFlags {
236 $BitFlags { bits: bits } & $BitFlags::all()
237 }
238
239 /// Returns `true` if no flags are currently stored.
240 #[inline]
241 pub fn is_empty(&self) -> bool {
242 *self == $BitFlags::empty()
243 }
244
245 /// Returns `true` if all flags are currently set.
246 #[inline]
247 pub fn is_all(&self) -> bool {
248 *self == $BitFlags::all()
249 }
250
251 /// Returns `true` if there are flags common to both `self` and `other`.
252 #[inline]
253 pub fn intersects(&self, other: $BitFlags) -> bool {
254 !(*self & other).is_empty()
255 }
256
257 /// Returns `true` all of the flags in `other` are contained within `self`.
258 #[inline]
259 pub fn contains(&self, other: $BitFlags) -> bool {
260 (*self & other) == other
261 }
262
263 /// Inserts the specified flags in-place.
264 #[inline]
265 pub fn insert(&mut self, other: $BitFlags) {
266 self.bits |= other.bits;
267 }
268
269 /// Removes the specified flags in-place.
270 #[inline]
271 pub fn remove(&mut self, other: $BitFlags) {
272 self.bits &= !other.bits;
273 }
274
275 /// Toggles the specified flags in-place.
276 #[inline]
277 pub fn toggle(&mut self, other: $BitFlags) {
278 self.bits ^= other.bits;
279 }
280 }
281
282 impl ::core::ops::BitOr for $BitFlags {
283 type Output = $BitFlags;
284
285 /// Returns the union of the two sets of flags.
286 #[inline]
287 fn bitor(self, other: $BitFlags) -> $BitFlags {
288 $BitFlags { bits: self.bits | other.bits }
289 }
290 }
291
292 impl ::core::ops::BitXor for $BitFlags {
293 type Output = $BitFlags;
294
295 /// Returns the left flags, but with all the right flags toggled.
296 #[inline]
297 fn bitxor(self, other: $BitFlags) -> $BitFlags {
298 $BitFlags { bits: self.bits ^ other.bits }
299 }
300 }
301
302 impl ::core::ops::BitAnd for $BitFlags {
303 type Output = $BitFlags;
304
305 /// Returns the intersection between the two sets of flags.
306 #[inline]
307 fn bitand(self, other: $BitFlags) -> $BitFlags {
308 $BitFlags { bits: self.bits & other.bits }
309 }
310 }
311
312 impl ::core::ops::Sub for $BitFlags {
313 type Output = $BitFlags;
314
315 /// Returns the set difference of the two sets of flags.
316 #[inline]
317 fn sub(self, other: $BitFlags) -> $BitFlags {
318 $BitFlags { bits: self.bits & !other.bits }
319 }
320 }
321
322 impl ::core::ops::Not for $BitFlags {
323 type Output = $BitFlags;
324
325 /// Returns the complement of this set of flags.
326 #[inline]
327 fn not(self) -> $BitFlags {
328 $BitFlags { bits: !self.bits } & $BitFlags::all()
329 }
330 }
331
332 impl ::core::iter::FromIterator<$BitFlags> for $BitFlags {
333 fn from_iter<T: ::core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
334 let mut result = Self::empty();
335 for item in iterator {
336 result.insert(item)
337 }
338 result
339 }
340 }
341 };
342 ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
343 $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+,
344 }) => {
345 bitflags! {
346 $(#[$attr])*
347 flags $BitFlags: $T {
348 $($(#[$Flag_attr])* const $Flag = $value),+
349 }
350 }
351 };
352}