]>
Commit | Line | Data |
---|---|---|
7cac9316 XL |
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 | ||
041b39d2 XL |
11 | //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags. |
12 | //! It can be used for creating typesafe wrappers around C APIs. | |
13 | //! | |
14 | //! The `bitflags!` macro generates a `struct` that manages a set of flags. The | |
15 | //! flags should only be defined for integer types, otherwise unexpected type | |
16 | //! errors may occur at compile time. | |
17 | //! | |
18 | //! # Example | |
19 | //! | |
20 | //! ``` | |
21 | //! #[macro_use] | |
22 | //! extern crate bitflags; | |
23 | //! | |
24 | //! bitflags! { | |
25 | //! struct Flags: u32 { | |
abe05a73 XL |
26 | //! const A = 0b00000001; |
27 | //! const B = 0b00000010; | |
28 | //! const C = 0b00000100; | |
29 | //! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; | |
041b39d2 XL |
30 | //! } |
31 | //! } | |
32 | //! | |
33 | //! fn main() { | |
abe05a73 XL |
34 | //! let e1 = Flags::A | Flags::C; |
35 | //! let e2 = Flags::B | Flags::C; | |
36 | //! assert_eq!((e1 | e2), Flags::ABC); // union | |
37 | //! assert_eq!((e1 & e2), Flags::C); // intersection | |
38 | //! assert_eq!((e1 - e2), Flags::A); // set difference | |
39 | //! assert_eq!(!e2, Flags::A); // set complement | |
041b39d2 XL |
40 | //! } |
41 | //! ``` | |
42 | //! | |
43 | //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code | |
44 | //! generated by the above `bitflags!` expansion. | |
45 | //! | |
46 | //! The generated `struct`s can also be extended with type and trait | |
47 | //! implementations: | |
48 | //! | |
49 | //! ``` | |
50 | //! #[macro_use] | |
51 | //! extern crate bitflags; | |
52 | //! | |
53 | //! use std::fmt; | |
54 | //! | |
55 | //! bitflags! { | |
56 | //! struct Flags: u32 { | |
abe05a73 XL |
57 | //! const A = 0b00000001; |
58 | //! const B = 0b00000010; | |
041b39d2 XL |
59 | //! } |
60 | //! } | |
61 | //! | |
62 | //! impl Flags { | |
63 | //! pub fn clear(&mut self) { | |
64 | //! self.bits = 0; // The `bits` field can be accessed from within the | |
65 | //! // same module where the `bitflags!` macro was invoked. | |
66 | //! } | |
67 | //! } | |
68 | //! | |
69 | //! impl fmt::Display for Flags { | |
70 | //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
71 | //! write!(f, "hi!") | |
72 | //! } | |
73 | //! } | |
74 | //! | |
75 | //! fn main() { | |
abe05a73 | 76 | //! let mut flags = Flags::A | Flags::B; |
041b39d2 XL |
77 | //! flags.clear(); |
78 | //! assert!(flags.is_empty()); | |
79 | //! assert_eq!(format!("{}", flags), "hi!"); | |
abe05a73 XL |
80 | //! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
81 | //! assert_eq!(format!("{:?}", Flags::B), "B"); | |
041b39d2 XL |
82 | //! } |
83 | //! ``` | |
84 | //! | |
85 | //! # Visibility | |
86 | //! | |
87 | //! The generated struct and its associated flag constants are not exported | |
88 | //! out of the current module by default. A definition can be exported out of | |
89 | //! the current module by adding `pub` before `flags`: | |
90 | //! | |
abe05a73 | 91 | //! ``` |
041b39d2 XL |
92 | //! #[macro_use] |
93 | //! extern crate bitflags; | |
94 | //! | |
95 | //! mod example { | |
96 | //! bitflags! { | |
97 | //! pub struct Flags1: u32 { | |
abe05a73 | 98 | //! const A = 0b00000001; |
041b39d2 XL |
99 | //! } |
100 | //! } | |
101 | //! bitflags! { | |
abe05a73 | 102 | //! # pub |
041b39d2 | 103 | //! struct Flags2: u32 { |
abe05a73 | 104 | //! const B = 0b00000010; |
041b39d2 XL |
105 | //! } |
106 | //! } | |
107 | //! } | |
108 | //! | |
109 | //! fn main() { | |
abe05a73 XL |
110 | //! let flag1 = example::Flags1::A; |
111 | //! let flag2 = example::Flags2::B; // error: const `B` is private | |
041b39d2 XL |
112 | //! } |
113 | //! ``` | |
114 | //! | |
115 | //! # Attributes | |
116 | //! | |
117 | //! Attributes can be attached to the generated `struct` by placing them | |
118 | //! before the `flags` keyword. | |
119 | //! | |
120 | //! # Trait implementations | |
121 | //! | |
122 | //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` | |
123 | //! traits automatically derived for the `struct` using the `derive` attribute. | |
124 | //! Additional traits can be derived by providing an explicit `derive` | |
125 | //! attribute on `flags`. | |
126 | //! | |
127 | //! The `Extend` and `FromIterator` traits are implemented for the `struct`, | |
128 | //! too: `Extend` adds the union of the instances of the `struct` iterated over, | |
129 | //! while `FromIterator` calculates the union. | |
130 | //! | |
131 | //! The `Binary`, `Debug`, `LowerExp`, `Octal` and `UpperExp` trait is also | |
132 | //! implemented by displaying the bits value of the internal struct. | |
133 | //! | |
134 | //! ## Operators | |
135 | //! | |
136 | //! The following operator traits are implemented for the generated `struct`: | |
137 | //! | |
138 | //! - `BitOr` and `BitOrAssign`: union | |
139 | //! - `BitAnd` and `BitAndAssign`: intersection | |
140 | //! - `BitXor` and `BitXorAssign`: toggle | |
141 | //! - `Sub` and `SubAssign`: set difference | |
142 | //! - `Not`: set complement | |
143 | //! | |
144 | //! # Methods | |
145 | //! | |
146 | //! The following methods are defined for the generated `struct`: | |
147 | //! | |
148 | //! - `empty`: an empty set of flags | |
149 | //! - `all`: the set of all flags | |
150 | //! - `bits`: the raw value of the flags currently stored | |
151 | //! - `from_bits`: convert from underlying bit representation, unless that | |
152 | //! representation contains bits that do not correspond to a flag | |
153 | //! - `from_bits_truncate`: convert from underlying bit representation, dropping | |
154 | //! any bits that do not correspond to flags | |
155 | //! - `is_empty`: `true` if no flags are currently stored | |
156 | //! - `is_all`: `true` if all flags are currently set | |
157 | //! - `intersects`: `true` if there are flags common to both `self` and `other` | |
158 | //! - `contains`: `true` all of the flags in `other` are contained within `self` | |
159 | //! - `insert`: inserts the specified flags in-place | |
160 | //! - `remove`: removes the specified flags in-place | |
161 | //! - `toggle`: the specified flags will be inserted if not present, and removed | |
162 | //! if they are. | |
ea8adc8c | 163 | //! - `set`: inserts or removes the specified flags depending on the passed value |
041b39d2 XL |
164 | //! |
165 | //! ## Default | |
166 | //! | |
167 | //! The `Default` trait is not automatically implemented for the generated struct. | |
168 | //! | |
169 | //! If your default value is equal to `0` (which is the same value as calling `empty()` | |
170 | //! on the generated struct), you can simply derive `Default`: | |
171 | //! | |
172 | //! ``` | |
173 | //! #[macro_use] | |
174 | //! extern crate bitflags; | |
175 | //! | |
176 | //! bitflags! { | |
177 | //! // Results in default value with bits: 0 | |
178 | //! #[derive(Default)] | |
179 | //! struct Flags: u32 { | |
abe05a73 XL |
180 | //! const A = 0b00000001; |
181 | //! const B = 0b00000010; | |
182 | //! const C = 0b00000100; | |
041b39d2 XL |
183 | //! } |
184 | //! } | |
185 | //! | |
186 | //! fn main() { | |
187 | //! let derived_default: Flags = Default::default(); | |
188 | //! assert_eq!(derived_default.bits(), 0); | |
189 | //! } | |
190 | //! ``` | |
191 | //! | |
192 | //! If your default value is not equal to `0` you need to implement `Default` yourself: | |
193 | //! | |
194 | //! ``` | |
195 | //! #[macro_use] | |
196 | //! extern crate bitflags; | |
197 | //! | |
198 | //! bitflags! { | |
199 | //! struct Flags: u32 { | |
abe05a73 XL |
200 | //! const A = 0b00000001; |
201 | //! const B = 0b00000010; | |
202 | //! const C = 0b00000100; | |
041b39d2 XL |
203 | //! } |
204 | //! } | |
205 | //! | |
206 | //! // explicit `Default` implementation | |
207 | //! impl Default for Flags { | |
208 | //! fn default() -> Flags { | |
abe05a73 | 209 | //! Flags::A | Flags::C |
041b39d2 XL |
210 | //! } |
211 | //! } | |
212 | //! | |
213 | //! fn main() { | |
214 | //! let implemented_default: Flags = Default::default(); | |
abe05a73 | 215 | //! assert_eq!(implemented_default, (Flags::A | Flags::C)); |
041b39d2 XL |
216 | //! } |
217 | //! ``` | |
7cac9316 XL |
218 | |
219 | #![no_std] | |
220 | ||
abe05a73 | 221 | #![doc(html_root_url = "https://docs.rs/bitflags/1.0.1")] |
041b39d2 | 222 | |
7cac9316 XL |
223 | #[cfg(test)] |
224 | #[macro_use] | |
225 | extern crate std; | |
226 | ||
abe05a73 XL |
227 | // Re-export libcore using an alias so that the macros can work without |
228 | // requiring `extern crate core` downstream. | |
7cac9316 | 229 | #[doc(hidden)] |
041b39d2 | 230 | pub extern crate core as _core; |
7cac9316 | 231 | |
041b39d2 | 232 | /// The macro used to generate the flag structure. |
7cac9316 | 233 | /// |
041b39d2 | 234 | /// See the [crate level docs](../bitflags/index.html) for complete documentation. |
7cac9316 XL |
235 | /// |
236 | /// # Example | |
237 | /// | |
041b39d2 | 238 | /// ``` |
7cac9316 XL |
239 | /// #[macro_use] |
240 | /// extern crate bitflags; | |
241 | /// | |
242 | /// bitflags! { | |
041b39d2 | 243 | /// struct Flags: u32 { |
abe05a73 XL |
244 | /// const A = 0b00000001; |
245 | /// const B = 0b00000010; | |
246 | /// const C = 0b00000100; | |
247 | /// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; | |
7cac9316 XL |
248 | /// } |
249 | /// } | |
250 | /// | |
251 | /// fn main() { | |
abe05a73 XL |
252 | /// let e1 = Flags::A | Flags::C; |
253 | /// let e2 = Flags::B | Flags::C; | |
254 | /// assert_eq!((e1 | e2), Flags::ABC); // union | |
255 | /// assert_eq!((e1 & e2), Flags::C); // intersection | |
256 | /// assert_eq!((e1 - e2), Flags::A); // set difference | |
257 | /// assert_eq!(!e2, Flags::A); // set complement | |
7cac9316 XL |
258 | /// } |
259 | /// ``` | |
260 | /// | |
261 | /// The generated `struct`s can also be extended with type and trait | |
262 | /// implementations: | |
263 | /// | |
041b39d2 | 264 | /// ``` |
7cac9316 XL |
265 | /// #[macro_use] |
266 | /// extern crate bitflags; | |
267 | /// | |
268 | /// use std::fmt; | |
269 | /// | |
270 | /// bitflags! { | |
041b39d2 | 271 | /// struct Flags: u32 { |
abe05a73 XL |
272 | /// const A = 0b00000001; |
273 | /// const B = 0b00000010; | |
7cac9316 XL |
274 | /// } |
275 | /// } | |
276 | /// | |
277 | /// impl Flags { | |
278 | /// pub fn clear(&mut self) { | |
279 | /// self.bits = 0; // The `bits` field can be accessed from within the | |
280 | /// // same module where the `bitflags!` macro was invoked. | |
281 | /// } | |
282 | /// } | |
283 | /// | |
284 | /// impl fmt::Display for Flags { | |
285 | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
286 | /// write!(f, "hi!") | |
287 | /// } | |
288 | /// } | |
289 | /// | |
290 | /// fn main() { | |
abe05a73 | 291 | /// let mut flags = Flags::A | Flags::B; |
7cac9316 XL |
292 | /// flags.clear(); |
293 | /// assert!(flags.is_empty()); | |
294 | /// assert_eq!(format!("{}", flags), "hi!"); | |
abe05a73 XL |
295 | /// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
296 | /// assert_eq!(format!("{:?}", Flags::B), "B"); | |
7cac9316 XL |
297 | /// } |
298 | /// ``` | |
7cac9316 XL |
299 | #[macro_export] |
300 | macro_rules! bitflags { | |
ea8adc8c XL |
301 | ( |
302 | $(#[$outer:meta])* | |
303 | pub struct $BitFlags:ident: $T:ty { | |
304 | $( | |
305 | $(#[$inner:ident $($args:tt)*])* | |
306 | const $Flag:ident = $value:expr; | |
307 | )+ | |
308 | } | |
309 | ) => { | |
abe05a73 XL |
310 | __bitflags! { |
311 | $(#[$outer])* | |
312 | (pub) $BitFlags: $T { | |
ea8adc8c XL |
313 | $( |
314 | $(#[$inner $($args)*])* | |
abe05a73 | 315 | $Flag = $value; |
ea8adc8c | 316 | )+ |
7cac9316 XL |
317 | } |
318 | } | |
319 | }; | |
ea8adc8c XL |
320 | ( |
321 | $(#[$outer:meta])* | |
322 | struct $BitFlags:ident: $T:ty { | |
323 | $( | |
324 | $(#[$inner:ident $($args:tt)*])* | |
325 | const $Flag:ident = $value:expr; | |
326 | )+ | |
327 | } | |
abe05a73 XL |
328 | ) => { |
329 | __bitflags! { | |
330 | $(#[$outer])* | |
331 | () $BitFlags: $T { | |
332 | $( | |
333 | $(#[$inner $($args)*])* | |
334 | $Flag = $value; | |
335 | )+ | |
336 | } | |
337 | } | |
338 | }; | |
339 | ( | |
340 | $(#[$outer:meta])* | |
341 | pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty { | |
342 | $( | |
343 | $(#[$inner:ident $($args:tt)*])* | |
344 | const $Flag:ident = $value:expr; | |
345 | )+ | |
346 | } | |
347 | ) => { | |
348 | __bitflags! { | |
349 | $(#[$outer])* | |
350 | (pub ($($vis)+)) $BitFlags: $T { | |
351 | $( | |
352 | $(#[$inner $($args)*])* | |
353 | $Flag = $value; | |
354 | )+ | |
355 | } | |
356 | } | |
357 | }; | |
358 | } | |
359 | ||
360 | #[macro_export] | |
361 | #[doc(hidden)] | |
362 | macro_rules! __bitflags { | |
363 | ( | |
364 | $(#[$outer:meta])* | |
365 | ($($vis:tt)*) $BitFlags:ident: $T:ty { | |
366 | $( | |
367 | $(#[$inner:ident $($args:tt)*])* | |
368 | $Flag:ident = $value:expr; | |
369 | )+ | |
370 | } | |
ea8adc8c | 371 | ) => { |
7cac9316 | 372 | #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] |
ea8adc8c | 373 | $(#[$outer])* |
abe05a73 | 374 | $($vis)* struct $BitFlags { |
7cac9316 XL |
375 | bits: $T, |
376 | } | |
377 | ||
041b39d2 | 378 | __impl_bitflags! { |
abe05a73 | 379 | $BitFlags: $T { |
ea8adc8c XL |
380 | $( |
381 | $(#[$inner $($args)*])* | |
abe05a73 | 382 | $Flag = $value; |
ea8adc8c | 383 | )+ |
7cac9316 XL |
384 | } |
385 | } | |
386 | }; | |
041b39d2 XL |
387 | } |
388 | ||
389 | #[macro_export] | |
390 | #[doc(hidden)] | |
391 | macro_rules! __impl_bitflags { | |
ea8adc8c | 392 | ( |
abe05a73 | 393 | $BitFlags:ident: $T:ty { |
ea8adc8c XL |
394 | $( |
395 | $(#[$attr:ident $($args:tt)*])* | |
abe05a73 | 396 | $Flag:ident = $value:expr; |
ea8adc8c XL |
397 | )+ |
398 | } | |
399 | ) => { | |
041b39d2 XL |
400 | impl $crate::_core::fmt::Debug for $BitFlags { |
401 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { | |
7cac9316 | 402 | // This convoluted approach is to handle #[cfg]-based flag |
041b39d2 XL |
403 | // omission correctly. For example it needs to support: |
404 | // | |
405 | // #[cfg(unix)] const A: Flag = /* ... */; | |
406 | // #[cfg(windows)] const B: Flag = /* ... */; | |
407 | ||
408 | // Unconditionally define a check for every flag, even disabled | |
409 | // ones. | |
410 | #[allow(non_snake_case)] | |
411 | trait __BitFlags { | |
412 | $( | |
abe05a73 | 413 | #[inline] |
041b39d2 XL |
414 | fn $Flag(&self) -> bool { false } |
415 | )+ | |
416 | } | |
417 | ||
418 | // Conditionally override the check for just those flags that | |
419 | // are not #[cfg]ed away. | |
420 | impl __BitFlags for $BitFlags { | |
421 | $( | |
ea8adc8c XL |
422 | __impl_bitflags! { |
423 | #[allow(deprecated)] | |
abe05a73 | 424 | #[inline] |
ea8adc8c XL |
425 | $(? #[$attr $($args)*])* |
426 | fn $Flag(&self) -> bool { | |
427 | self.bits & Self::$Flag.bits == Self::$Flag.bits | |
428 | } | |
041b39d2 XL |
429 | } |
430 | )+ | |
431 | } | |
432 | ||
433 | let mut first = true; | |
434 | $( | |
435 | if <$BitFlags as __BitFlags>::$Flag(self) { | |
436 | if !first { | |
437 | try!(f.write_str(" | ")); | |
438 | } | |
439 | first = false; | |
440 | try!(f.write_str(stringify!($Flag))); | |
7cac9316 | 441 | } |
041b39d2 XL |
442 | )+ |
443 | if first { | |
444 | try!(f.write_str("(empty)")); | |
7cac9316 | 445 | } |
041b39d2 XL |
446 | Ok(()) |
447 | } | |
448 | } | |
449 | impl $crate::_core::fmt::Binary for $BitFlags { | |
450 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { | |
451 | $crate::_core::fmt::Binary::fmt(&self.bits, f) | |
452 | } | |
453 | } | |
454 | impl $crate::_core::fmt::Octal for $BitFlags { | |
455 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { | |
456 | $crate::_core::fmt::Octal::fmt(&self.bits, f) | |
457 | } | |
458 | } | |
459 | impl $crate::_core::fmt::LowerHex for $BitFlags { | |
460 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { | |
461 | $crate::_core::fmt::LowerHex::fmt(&self.bits, f) | |
462 | } | |
463 | } | |
464 | impl $crate::_core::fmt::UpperHex for $BitFlags { | |
465 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { | |
466 | $crate::_core::fmt::UpperHex::fmt(&self.bits, f) | |
7cac9316 XL |
467 | } |
468 | } | |
469 | ||
470 | #[allow(dead_code)] | |
471 | impl $BitFlags { | |
ea8adc8c XL |
472 | $( |
473 | $(#[$attr $($args)*])* | |
474 | pub const $Flag: $BitFlags = $BitFlags { bits: $value }; | |
475 | )+ | |
476 | ||
7cac9316 XL |
477 | /// Returns an empty set of flags. |
478 | #[inline] | |
479 | pub fn empty() -> $BitFlags { | |
480 | $BitFlags { bits: 0 } | |
481 | } | |
482 | ||
483 | /// Returns the set containing all flags. | |
484 | #[inline] | |
485 | pub fn all() -> $BitFlags { | |
041b39d2 XL |
486 | // See `Debug::fmt` for why this approach is taken. |
487 | #[allow(non_snake_case)] | |
488 | trait __BitFlags { | |
489 | $( | |
abe05a73 | 490 | #[inline] |
041b39d2 XL |
491 | fn $Flag() -> $T { 0 } |
492 | )+ | |
493 | } | |
494 | impl __BitFlags for $BitFlags { | |
495 | $( | |
ea8adc8c XL |
496 | __impl_bitflags! { |
497 | #[allow(deprecated)] | |
abe05a73 | 498 | #[inline] |
ea8adc8c XL |
499 | $(? #[$attr $($args)*])* |
500 | fn $Flag() -> $T { Self::$Flag.bits } | |
501 | } | |
041b39d2 | 502 | )+ |
7cac9316 | 503 | } |
041b39d2 | 504 | $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag())|+ } |
7cac9316 XL |
505 | } |
506 | ||
507 | /// Returns the raw value of the flags currently stored. | |
508 | #[inline] | |
509 | pub fn bits(&self) -> $T { | |
510 | self.bits | |
511 | } | |
512 | ||
513 | /// Convert from underlying bit representation, unless that | |
514 | /// representation contains bits that do not correspond to a flag. | |
515 | #[inline] | |
041b39d2 | 516 | pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> { |
7cac9316 | 517 | if (bits & !$BitFlags::all().bits()) == 0 { |
041b39d2 | 518 | $crate::_core::option::Option::Some($BitFlags { bits: bits }) |
7cac9316 | 519 | } else { |
041b39d2 | 520 | $crate::_core::option::Option::None |
7cac9316 XL |
521 | } |
522 | } | |
523 | ||
524 | /// Convert from underlying bit representation, dropping any bits | |
525 | /// that do not correspond to flags. | |
526 | #[inline] | |
527 | pub fn from_bits_truncate(bits: $T) -> $BitFlags { | |
528 | $BitFlags { bits: bits } & $BitFlags::all() | |
529 | } | |
530 | ||
531 | /// Returns `true` if no flags are currently stored. | |
532 | #[inline] | |
533 | pub fn is_empty(&self) -> bool { | |
534 | *self == $BitFlags::empty() | |
535 | } | |
536 | ||
537 | /// Returns `true` if all flags are currently set. | |
538 | #[inline] | |
539 | pub fn is_all(&self) -> bool { | |
540 | *self == $BitFlags::all() | |
541 | } | |
542 | ||
543 | /// Returns `true` if there are flags common to both `self` and `other`. | |
544 | #[inline] | |
545 | pub fn intersects(&self, other: $BitFlags) -> bool { | |
546 | !(*self & other).is_empty() | |
547 | } | |
548 | ||
549 | /// Returns `true` all of the flags in `other` are contained within `self`. | |
550 | #[inline] | |
551 | pub fn contains(&self, other: $BitFlags) -> bool { | |
552 | (*self & other) == other | |
553 | } | |
554 | ||
555 | /// Inserts the specified flags in-place. | |
556 | #[inline] | |
557 | pub fn insert(&mut self, other: $BitFlags) { | |
558 | self.bits |= other.bits; | |
559 | } | |
560 | ||
561 | /// Removes the specified flags in-place. | |
562 | #[inline] | |
563 | pub fn remove(&mut self, other: $BitFlags) { | |
564 | self.bits &= !other.bits; | |
565 | } | |
566 | ||
567 | /// Toggles the specified flags in-place. | |
568 | #[inline] | |
569 | pub fn toggle(&mut self, other: $BitFlags) { | |
570 | self.bits ^= other.bits; | |
571 | } | |
041b39d2 XL |
572 | |
573 | /// Inserts or removes the specified flags depending on the passed value. | |
574 | #[inline] | |
575 | pub fn set(&mut self, other: $BitFlags, value: bool) { | |
576 | if value { | |
577 | self.insert(other); | |
578 | } else { | |
579 | self.remove(other); | |
580 | } | |
581 | } | |
7cac9316 XL |
582 | } |
583 | ||
041b39d2 | 584 | impl $crate::_core::ops::BitOr for $BitFlags { |
7cac9316 XL |
585 | type Output = $BitFlags; |
586 | ||
587 | /// Returns the union of the two sets of flags. | |
588 | #[inline] | |
589 | fn bitor(self, other: $BitFlags) -> $BitFlags { | |
590 | $BitFlags { bits: self.bits | other.bits } | |
591 | } | |
592 | } | |
593 | ||
041b39d2 | 594 | impl $crate::_core::ops::BitOrAssign for $BitFlags { |
7cac9316 XL |
595 | |
596 | /// Adds the set of flags. | |
597 | #[inline] | |
598 | fn bitor_assign(&mut self, other: $BitFlags) { | |
599 | self.bits |= other.bits; | |
600 | } | |
601 | } | |
602 | ||
041b39d2 | 603 | impl $crate::_core::ops::BitXor for $BitFlags { |
7cac9316 XL |
604 | type Output = $BitFlags; |
605 | ||
606 | /// Returns the left flags, but with all the right flags toggled. | |
607 | #[inline] | |
608 | fn bitxor(self, other: $BitFlags) -> $BitFlags { | |
609 | $BitFlags { bits: self.bits ^ other.bits } | |
610 | } | |
611 | } | |
612 | ||
041b39d2 | 613 | impl $crate::_core::ops::BitXorAssign for $BitFlags { |
7cac9316 XL |
614 | |
615 | /// Toggles the set of flags. | |
616 | #[inline] | |
617 | fn bitxor_assign(&mut self, other: $BitFlags) { | |
618 | self.bits ^= other.bits; | |
619 | } | |
620 | } | |
621 | ||
041b39d2 | 622 | impl $crate::_core::ops::BitAnd for $BitFlags { |
7cac9316 XL |
623 | type Output = $BitFlags; |
624 | ||
625 | /// Returns the intersection between the two sets of flags. | |
626 | #[inline] | |
627 | fn bitand(self, other: $BitFlags) -> $BitFlags { | |
628 | $BitFlags { bits: self.bits & other.bits } | |
629 | } | |
630 | } | |
631 | ||
041b39d2 | 632 | impl $crate::_core::ops::BitAndAssign for $BitFlags { |
7cac9316 XL |
633 | |
634 | /// Disables all flags disabled in the set. | |
635 | #[inline] | |
636 | fn bitand_assign(&mut self, other: $BitFlags) { | |
637 | self.bits &= other.bits; | |
638 | } | |
639 | } | |
640 | ||
041b39d2 | 641 | impl $crate::_core::ops::Sub for $BitFlags { |
7cac9316 XL |
642 | type Output = $BitFlags; |
643 | ||
644 | /// Returns the set difference of the two sets of flags. | |
645 | #[inline] | |
646 | fn sub(self, other: $BitFlags) -> $BitFlags { | |
647 | $BitFlags { bits: self.bits & !other.bits } | |
648 | } | |
649 | } | |
650 | ||
041b39d2 | 651 | impl $crate::_core::ops::SubAssign for $BitFlags { |
7cac9316 XL |
652 | |
653 | /// Disables all flags enabled in the set. | |
654 | #[inline] | |
655 | fn sub_assign(&mut self, other: $BitFlags) { | |
656 | self.bits &= !other.bits; | |
657 | } | |
658 | } | |
659 | ||
041b39d2 | 660 | impl $crate::_core::ops::Not for $BitFlags { |
7cac9316 XL |
661 | type Output = $BitFlags; |
662 | ||
663 | /// Returns the complement of this set of flags. | |
664 | #[inline] | |
665 | fn not(self) -> $BitFlags { | |
666 | $BitFlags { bits: !self.bits } & $BitFlags::all() | |
667 | } | |
668 | } | |
669 | ||
041b39d2 XL |
670 | impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { |
671 | fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) { | |
7cac9316 XL |
672 | for item in iterator { |
673 | self.insert(item) | |
674 | } | |
675 | } | |
676 | } | |
677 | ||
041b39d2 XL |
678 | impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { |
679 | fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags { | |
7cac9316 XL |
680 | let mut result = Self::empty(); |
681 | result.extend(iterator); | |
682 | result | |
683 | } | |
684 | } | |
685 | }; | |
ea8adc8c XL |
686 | |
687 | // Every attribute that the user writes on a const is applied to the | |
688 | // corresponding const that we generate, but within the implementation of | |
689 | // Debug and all() we want to ignore everything but #[cfg] attributes. In | |
690 | // particular, including a #[deprecated] attribute on those items would fail | |
691 | // to compile. | |
692 | // https://github.com/rust-lang-nursery/bitflags/issues/109 | |
693 | // | |
694 | // Input: | |
695 | // | |
696 | // ? #[cfg(feature = "advanced")] | |
697 | // ? #[deprecated(note = "Use somthing else.")] | |
698 | // ? #[doc = r"High quality documentation."] | |
699 | // fn f() -> i32 { /* ... */ } | |
700 | // | |
701 | // Output: | |
702 | // | |
703 | // #[cfg(feature = "advanced")] | |
704 | // fn f() -> i32 { /* ... */ } | |
705 | ( | |
706 | $(#[$filtered:meta])* | |
707 | ? #[cfg $($cfgargs:tt)*] | |
708 | $(? #[$rest:ident $($restargs:tt)*])* | |
709 | fn $($item:tt)* | |
710 | ) => { | |
711 | __impl_bitflags! { | |
712 | $(#[$filtered])* | |
713 | #[cfg $($cfgargs)*] | |
714 | $(? #[$rest $($restargs)*])* | |
715 | fn $($item)* | |
716 | } | |
717 | }; | |
718 | ( | |
719 | $(#[$filtered:meta])* | |
720 | // $next != `cfg` | |
721 | ? #[$next:ident $($nextargs:tt)*] | |
722 | $(? #[$rest:ident $($restargs:tt)*])* | |
723 | fn $($item:tt)* | |
724 | ) => { | |
725 | __impl_bitflags! { | |
726 | $(#[$filtered])* | |
727 | // $next filtered out | |
728 | $(? #[$rest $($restargs)*])* | |
729 | fn $($item)* | |
730 | } | |
731 | }; | |
732 | ( | |
733 | $(#[$filtered:meta])* | |
734 | fn $($item:tt)* | |
735 | ) => { | |
736 | $(#[$filtered])* | |
737 | fn $($item)* | |
738 | }; | |
7cac9316 XL |
739 | } |
740 | ||
041b39d2 XL |
741 | #[cfg(feature = "example_generated")] |
742 | pub mod example_generated; | |
743 | ||
7cac9316 | 744 | #[cfg(test)] |
7cac9316 | 745 | mod tests { |
041b39d2 XL |
746 | use std::hash::{Hash, Hasher}; |
747 | use std::collections::hash_map::DefaultHasher; | |
7cac9316 XL |
748 | |
749 | bitflags! { | |
750 | #[doc = "> The first principle is that you must not fool yourself — and"] | |
751 | #[doc = "> you are the easiest person to fool."] | |
752 | #[doc = "> "] | |
753 | #[doc = "> - Richard Feynman"] | |
041b39d2 | 754 | struct Flags: u32 { |
abe05a73 | 755 | const A = 0b00000001; |
7cac9316 | 756 | #[doc = "<pcwalton> macros are way better at generating code than trans is"] |
abe05a73 XL |
757 | const B = 0b00000010; |
758 | const C = 0b00000100; | |
7cac9316 XL |
759 | #[doc = "* cmr bed"] |
760 | #[doc = "* strcat table"] | |
761 | #[doc = "<strcat> wait what?"] | |
abe05a73 | 762 | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
7cac9316 XL |
763 | } |
764 | } | |
765 | ||
766 | bitflags! { | |
041b39d2 | 767 | struct _CfgFlags: u32 { |
7cac9316 | 768 | #[cfg(windows)] |
ea8adc8c | 769 | const _CFG_A = 0b01; |
7cac9316 | 770 | #[cfg(unix)] |
ea8adc8c | 771 | const _CFG_B = 0b01; |
7cac9316 | 772 | #[cfg(windows)] |
ea8adc8c | 773 | const _CFG_C = _CFG_A.bits | 0b10; |
041b39d2 XL |
774 | } |
775 | } | |
776 | ||
777 | bitflags! { | |
778 | struct AnotherSetOfFlags: i8 { | |
ea8adc8c | 779 | const ANOTHER_FLAG = -1_i8; |
7cac9316 XL |
780 | } |
781 | } | |
782 | ||
783 | bitflags! { | |
041b39d2 | 784 | struct LongFlags: u32 { |
abe05a73 | 785 | const LONG_A = 0b1111111111111111; |
7cac9316 XL |
786 | } |
787 | } | |
788 | ||
789 | #[test] | |
790 | fn test_bits(){ | |
791 | assert_eq!(Flags::empty().bits(), 0b00000000); | |
abe05a73 XL |
792 | assert_eq!(Flags::A.bits(), 0b00000001); |
793 | assert_eq!(Flags::ABC.bits(), 0b00000111); | |
7cac9316 XL |
794 | |
795 | assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); | |
ea8adc8c | 796 | assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8); |
7cac9316 XL |
797 | } |
798 | ||
799 | #[test] | |
800 | fn test_from_bits() { | |
801 | assert_eq!(Flags::from_bits(0), Some(Flags::empty())); | |
abe05a73 XL |
802 | assert_eq!(Flags::from_bits(0b1), Some(Flags::A)); |
803 | assert_eq!(Flags::from_bits(0b10), Some(Flags::B)); | |
804 | assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B)); | |
7cac9316 XL |
805 | assert_eq!(Flags::from_bits(0b1000), None); |
806 | ||
ea8adc8c | 807 | assert_eq!(AnotherSetOfFlags::from_bits(!0_i8), Some(AnotherSetOfFlags::ANOTHER_FLAG)); |
7cac9316 XL |
808 | } |
809 | ||
810 | #[test] | |
811 | fn test_from_bits_truncate() { | |
812 | assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); | |
abe05a73 XL |
813 | assert_eq!(Flags::from_bits_truncate(0b1), Flags::A); |
814 | assert_eq!(Flags::from_bits_truncate(0b10), Flags::B); | |
815 | assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B)); | |
7cac9316 | 816 | assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); |
abe05a73 | 817 | assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A); |
7cac9316 XL |
818 | |
819 | assert_eq!(AnotherSetOfFlags::from_bits_truncate(0_i8), AnotherSetOfFlags::empty()); | |
820 | } | |
821 | ||
822 | #[test] | |
823 | fn test_is_empty(){ | |
824 | assert!(Flags::empty().is_empty()); | |
abe05a73 XL |
825 | assert!(!Flags::A.is_empty()); |
826 | assert!(!Flags::ABC.is_empty()); | |
7cac9316 | 827 | |
ea8adc8c | 828 | assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty()); |
7cac9316 XL |
829 | } |
830 | ||
831 | #[test] | |
832 | fn test_is_all() { | |
833 | assert!(Flags::all().is_all()); | |
abe05a73 XL |
834 | assert!(!Flags::A.is_all()); |
835 | assert!(Flags::ABC.is_all()); | |
7cac9316 | 836 | |
ea8adc8c | 837 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all()); |
7cac9316 XL |
838 | } |
839 | ||
840 | #[test] | |
841 | fn test_two_empties_do_not_intersect() { | |
842 | let e1 = Flags::empty(); | |
843 | let e2 = Flags::empty(); | |
844 | assert!(!e1.intersects(e2)); | |
845 | ||
ea8adc8c | 846 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG)); |
7cac9316 XL |
847 | } |
848 | ||
849 | #[test] | |
850 | fn test_empty_does_not_intersect_with_full() { | |
851 | let e1 = Flags::empty(); | |
abe05a73 | 852 | let e2 = Flags::ABC; |
7cac9316 XL |
853 | assert!(!e1.intersects(e2)); |
854 | } | |
855 | ||
856 | #[test] | |
857 | fn test_disjoint_intersects() { | |
abe05a73 XL |
858 | let e1 = Flags::A; |
859 | let e2 = Flags::B; | |
7cac9316 XL |
860 | assert!(!e1.intersects(e2)); |
861 | } | |
862 | ||
863 | #[test] | |
864 | fn test_overlapping_intersects() { | |
abe05a73 XL |
865 | let e1 = Flags::A; |
866 | let e2 = Flags::A | Flags::B; | |
7cac9316 XL |
867 | assert!(e1.intersects(e2)); |
868 | } | |
869 | ||
870 | #[test] | |
871 | fn test_contains() { | |
abe05a73 XL |
872 | let e1 = Flags::A; |
873 | let e2 = Flags::A | Flags::B; | |
7cac9316 XL |
874 | assert!(!e1.contains(e2)); |
875 | assert!(e2.contains(e1)); | |
abe05a73 | 876 | assert!(Flags::ABC.contains(e2)); |
7cac9316 | 877 | |
ea8adc8c | 878 | assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG)); |
7cac9316 XL |
879 | } |
880 | ||
881 | #[test] | |
882 | fn test_insert(){ | |
abe05a73 XL |
883 | let mut e1 = Flags::A; |
884 | let e2 = Flags::A | Flags::B; | |
7cac9316 XL |
885 | e1.insert(e2); |
886 | assert_eq!(e1, e2); | |
887 | ||
888 | let mut e3 = AnotherSetOfFlags::empty(); | |
ea8adc8c XL |
889 | e3.insert(AnotherSetOfFlags::ANOTHER_FLAG); |
890 | assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG); | |
7cac9316 XL |
891 | } |
892 | ||
893 | #[test] | |
894 | fn test_remove(){ | |
abe05a73 XL |
895 | let mut e1 = Flags::A | Flags::B; |
896 | let e2 = Flags::A | Flags::C; | |
7cac9316 | 897 | e1.remove(e2); |
abe05a73 | 898 | assert_eq!(e1, Flags::B); |
7cac9316 | 899 | |
ea8adc8c XL |
900 | let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG; |
901 | e3.remove(AnotherSetOfFlags::ANOTHER_FLAG); | |
7cac9316 XL |
902 | assert_eq!(e3, AnotherSetOfFlags::empty()); |
903 | } | |
904 | ||
905 | #[test] | |
906 | fn test_operators() { | |
abe05a73 XL |
907 | let e1 = Flags::A | Flags::C; |
908 | let e2 = Flags::B | Flags::C; | |
909 | assert_eq!((e1 | e2), Flags::ABC); // union | |
910 | assert_eq!((e1 & e2), Flags::C); // intersection | |
911 | assert_eq!((e1 - e2), Flags::A); // set difference | |
912 | assert_eq!(!e2, Flags::A); // set complement | |
913 | assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle | |
7cac9316 XL |
914 | let mut e3 = e1; |
915 | e3.toggle(e2); | |
abe05a73 | 916 | assert_eq!(e3, Flags::A | Flags::B); |
7cac9316 XL |
917 | |
918 | let mut m4 = AnotherSetOfFlags::empty(); | |
919 | m4.toggle(AnotherSetOfFlags::empty()); | |
920 | assert_eq!(m4, AnotherSetOfFlags::empty()); | |
921 | } | |
922 | ||
041b39d2 XL |
923 | #[test] |
924 | fn test_set() { | |
abe05a73 XL |
925 | let mut e1 = Flags::A | Flags::C; |
926 | e1.set(Flags::B, true); | |
927 | e1.set(Flags::C, false); | |
041b39d2 | 928 | |
abe05a73 | 929 | assert_eq!(e1, Flags::A | Flags::B); |
041b39d2 XL |
930 | } |
931 | ||
7cac9316 XL |
932 | #[test] |
933 | fn test_assignment_operators() { | |
934 | let mut m1 = Flags::empty(); | |
abe05a73 | 935 | let e1 = Flags::A | Flags::C; |
7cac9316 | 936 | // union |
abe05a73 XL |
937 | m1 |= Flags::A; |
938 | assert_eq!(m1, Flags::A); | |
7cac9316 XL |
939 | // intersection |
940 | m1 &= e1; | |
abe05a73 | 941 | assert_eq!(m1, Flags::A); |
7cac9316 XL |
942 | // set difference |
943 | m1 -= m1; | |
944 | assert_eq!(m1, Flags::empty()); | |
945 | // toggle | |
946 | m1 ^= e1; | |
947 | assert_eq!(m1, e1); | |
948 | } | |
949 | ||
950 | #[test] | |
951 | fn test_extend() { | |
952 | let mut flags; | |
953 | ||
954 | flags = Flags::empty(); | |
955 | flags.extend([].iter().cloned()); | |
956 | assert_eq!(flags, Flags::empty()); | |
957 | ||
958 | flags = Flags::empty(); | |
abe05a73 XL |
959 | flags.extend([Flags::A, Flags::B].iter().cloned()); |
960 | assert_eq!(flags, Flags::A | Flags::B); | |
7cac9316 | 961 | |
abe05a73 XL |
962 | flags = Flags::A; |
963 | flags.extend([Flags::A, Flags::B].iter().cloned()); | |
964 | assert_eq!(flags, Flags::A | Flags::B); | |
7cac9316 | 965 | |
abe05a73 XL |
966 | flags = Flags::B; |
967 | flags.extend([Flags::A, Flags::ABC].iter().cloned()); | |
968 | assert_eq!(flags, Flags::ABC); | |
7cac9316 XL |
969 | } |
970 | ||
971 | #[test] | |
972 | fn test_from_iterator() { | |
973 | assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty()); | |
abe05a73 XL |
974 | assert_eq!([Flags::A, Flags::B].iter().cloned().collect::<Flags>(), |
975 | Flags::A | Flags::B); | |
976 | assert_eq!([Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(), | |
977 | Flags::ABC); | |
7cac9316 XL |
978 | } |
979 | ||
980 | #[test] | |
981 | fn test_lt() { | |
982 | let mut a = Flags::empty(); | |
983 | let mut b = Flags::empty(); | |
984 | ||
985 | assert!(!(a < b) && !(b < a)); | |
abe05a73 | 986 | b = Flags::B; |
7cac9316 | 987 | assert!(a < b); |
abe05a73 | 988 | a = Flags::C; |
7cac9316 | 989 | assert!(!(a < b) && b < a); |
abe05a73 | 990 | b = Flags::C | Flags::B; |
7cac9316 XL |
991 | assert!(a < b); |
992 | } | |
993 | ||
994 | #[test] | |
995 | fn test_ord() { | |
996 | let mut a = Flags::empty(); | |
997 | let mut b = Flags::empty(); | |
998 | ||
999 | assert!(a <= b && a >= b); | |
abe05a73 | 1000 | a = Flags::A; |
7cac9316 XL |
1001 | assert!(a > b && a >= b); |
1002 | assert!(b < a && b <= a); | |
abe05a73 | 1003 | b = Flags::B; |
7cac9316 XL |
1004 | assert!(b > a && b >= a); |
1005 | assert!(a < b && a <= b); | |
1006 | } | |
1007 | ||
1008 | fn hash<T: Hash>(t: &T) -> u64 { | |
041b39d2 | 1009 | let mut s = DefaultHasher::new(); |
7cac9316 XL |
1010 | t.hash(&mut s); |
1011 | s.finish() | |
1012 | } | |
1013 | ||
1014 | #[test] | |
1015 | fn test_hash() { | |
1016 | let mut x = Flags::empty(); | |
1017 | let mut y = Flags::empty(); | |
1018 | assert_eq!(hash(&x), hash(&y)); | |
1019 | x = Flags::all(); | |
abe05a73 | 1020 | y = Flags::ABC; |
7cac9316 XL |
1021 | assert_eq!(hash(&x), hash(&y)); |
1022 | } | |
1023 | ||
1024 | #[test] | |
1025 | fn test_debug() { | |
abe05a73 | 1026 | assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
041b39d2 | 1027 | assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); |
abe05a73 | 1028 | assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); |
7cac9316 XL |
1029 | } |
1030 | ||
041b39d2 XL |
1031 | #[test] |
1032 | fn test_binary() { | |
abe05a73 XL |
1033 | assert_eq!(format!("{:b}", Flags::ABC), "111"); |
1034 | assert_eq!(format!("{:#b}", Flags::ABC), "0b111"); | |
041b39d2 XL |
1035 | } |
1036 | ||
1037 | #[test] | |
1038 | fn test_octal() { | |
abe05a73 XL |
1039 | assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777"); |
1040 | assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777"); | |
041b39d2 XL |
1041 | } |
1042 | ||
1043 | #[test] | |
1044 | fn test_lowerhex() { | |
abe05a73 XL |
1045 | assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff"); |
1046 | assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff"); | |
041b39d2 XL |
1047 | } |
1048 | ||
1049 | #[test] | |
1050 | fn test_upperhex() { | |
abe05a73 XL |
1051 | assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF"); |
1052 | assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF"); | |
041b39d2 XL |
1053 | } |
1054 | ||
7cac9316 XL |
1055 | mod submodule { |
1056 | bitflags! { | |
041b39d2 | 1057 | pub struct PublicFlags: i8 { |
abe05a73 | 1058 | const X = 0; |
7cac9316 XL |
1059 | } |
1060 | } | |
1061 | bitflags! { | |
041b39d2 | 1062 | struct PrivateFlags: i8 { |
abe05a73 | 1063 | const Y = 0; |
7cac9316 XL |
1064 | } |
1065 | } | |
1066 | ||
1067 | #[test] | |
1068 | fn test_private() { | |
ea8adc8c | 1069 | |
abe05a73 | 1070 | let _ = PrivateFlags::Y; |
7cac9316 XL |
1071 | } |
1072 | } | |
1073 | ||
1074 | #[test] | |
1075 | fn test_public() { | |
abe05a73 | 1076 | let _ = submodule::PublicFlags::X; |
7cac9316 XL |
1077 | } |
1078 | ||
1079 | mod t1 { | |
1080 | mod foo { | |
1081 | pub type Bar = i32; | |
1082 | } | |
1083 | ||
1084 | bitflags! { | |
1085 | /// baz | |
041b39d2 | 1086 | struct Flags: foo::Bar { |
abe05a73 | 1087 | const A = 0b00000001; |
7cac9316 | 1088 | #[cfg(foo)] |
abe05a73 | 1089 | const B = 0b00000010; |
7cac9316 | 1090 | #[cfg(foo)] |
abe05a73 | 1091 | const C = 0b00000010; |
041b39d2 XL |
1092 | } |
1093 | } | |
1094 | } | |
1095 | ||
1096 | #[test] | |
1097 | fn test_in_function() { | |
1098 | bitflags! { | |
1099 | struct Flags: u8 { | |
1100 | const A = 1; | |
1101 | #[cfg(any())] // false | |
1102 | const B = 2; | |
7cac9316 XL |
1103 | } |
1104 | } | |
ea8adc8c XL |
1105 | assert_eq!(Flags::all(), Flags::A); |
1106 | assert_eq!(format!("{:?}", Flags::A), "A"); | |
1107 | } | |
1108 | ||
1109 | #[test] | |
1110 | fn test_deprecated() { | |
1111 | bitflags! { | |
1112 | pub struct TestFlags: u32 { | |
1113 | #[deprecated(note = "Use something else.")] | |
abe05a73 XL |
1114 | const ONE = 1; |
1115 | } | |
1116 | } | |
1117 | } | |
1118 | ||
1119 | #[test] | |
1120 | fn test_pub_crate() { | |
1121 | mod module { | |
1122 | bitflags! { | |
1123 | pub (crate) struct Test: u8 { | |
1124 | const FOO = 1; | |
1125 | } | |
ea8adc8c XL |
1126 | } |
1127 | } | |
abe05a73 XL |
1128 | |
1129 | assert_eq!(module::Test::FOO.bits(), 1); | |
1130 | } | |
1131 | ||
1132 | #[test] | |
1133 | fn test_pub_in_module() { | |
1134 | mod module { | |
1135 | mod submodule { | |
1136 | bitflags! { | |
1137 | // `pub (in super)` means only the module `module` will | |
1138 | // be able to access this. | |
1139 | pub (in super) struct Test: u8 { | |
1140 | const FOO = 1; | |
1141 | } | |
1142 | } | |
1143 | } | |
1144 | ||
1145 | mod test { | |
1146 | // Note: due to `pub (in super)`, | |
1147 | // this cannot be accessed directly by the testing code. | |
1148 | pub (in super) fn value() -> u8 { | |
1149 | super::submodule::Test::FOO.bits() | |
1150 | } | |
1151 | } | |
1152 | ||
1153 | pub fn value() -> u8 { | |
1154 | test::value() | |
1155 | } | |
1156 | } | |
1157 | ||
1158 | assert_eq!(module::value(), 1) | |
7cac9316 XL |
1159 | } |
1160 | } |