/rust/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
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 | | //! 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 `struct`s that manage 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 | | //! use bitflags::bitflags; |
22 | | //! |
23 | | //! bitflags! { |
24 | | //! struct Flags: u32 { |
25 | | //! const A = 0b00000001; |
26 | | //! const B = 0b00000010; |
27 | | //! const C = 0b00000100; |
28 | | //! const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
29 | | //! } |
30 | | //! } |
31 | | //! |
32 | | //! fn main() { |
33 | | //! let e1 = Flags::A | Flags::C; |
34 | | //! let e2 = Flags::B | Flags::C; |
35 | | //! assert_eq!((e1 | e2), Flags::ABC); // union |
36 | | //! assert_eq!((e1 & e2), Flags::C); // intersection |
37 | | //! assert_eq!((e1 - e2), Flags::A); // set difference |
38 | | //! assert_eq!(!e2, Flags::A); // set complement |
39 | | //! } |
40 | | //! ``` |
41 | | //! |
42 | | //! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code |
43 | | //! generated by the above `bitflags!` expansion. |
44 | | //! |
45 | | //! The generated `struct`s can also be extended with type and trait |
46 | | //! implementations: |
47 | | //! |
48 | | //! ``` |
49 | | //! use std::fmt; |
50 | | //! |
51 | | //! use bitflags::bitflags; |
52 | | //! |
53 | | //! bitflags! { |
54 | | //! struct Flags: u32 { |
55 | | //! const A = 0b00000001; |
56 | | //! const B = 0b00000010; |
57 | | //! } |
58 | | //! } |
59 | | //! |
60 | | //! impl Flags { |
61 | | //! pub fn clear(&mut self) { |
62 | | //! self.bits = 0; // The `bits` field can be accessed from within the |
63 | | //! // same module where the `bitflags!` macro was invoked. |
64 | | //! } |
65 | | //! } |
66 | | //! |
67 | | //! impl fmt::Display for Flags { |
68 | | //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
69 | | //! write!(f, "hi!") |
70 | | //! } |
71 | | //! } |
72 | | //! |
73 | | //! fn main() { |
74 | | //! let mut flags = Flags::A | Flags::B; |
75 | | //! flags.clear(); |
76 | | //! assert!(flags.is_empty()); |
77 | | //! assert_eq!(format!("{}", flags), "hi!"); |
78 | | //! assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
79 | | //! assert_eq!(format!("{:?}", Flags::B), "B"); |
80 | | //! } |
81 | | //! ``` |
82 | | //! |
83 | | //! # Visibility |
84 | | //! |
85 | | //! The generated structs and their associated flag constants are not exported |
86 | | //! out of the current module by default. A definition can be exported out of |
87 | | //! the current module by adding `pub` before `struct`: |
88 | | //! |
89 | | //! ``` |
90 | | //! mod example { |
91 | | //! use bitflags::bitflags; |
92 | | //! |
93 | | //! bitflags! { |
94 | | //! pub struct Flags1: u32 { |
95 | | //! const A = 0b00000001; |
96 | | //! } |
97 | | //! |
98 | | //! # pub |
99 | | //! struct Flags2: u32 { |
100 | | //! const B = 0b00000010; |
101 | | //! } |
102 | | //! } |
103 | | //! } |
104 | | //! |
105 | | //! fn main() { |
106 | | //! let flag1 = example::Flags1::A; |
107 | | //! let flag2 = example::Flags2::B; // error: const `B` is private |
108 | | //! } |
109 | | //! ``` |
110 | | //! |
111 | | //! # Attributes |
112 | | //! |
113 | | //! Attributes can be attached to the generated `struct`s by placing them |
114 | | //! before the `struct` keyword. |
115 | | //! |
116 | | //! ## Representations |
117 | | //! |
118 | | //! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type |
119 | | //! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype. |
120 | | //! |
121 | | //! ``` |
122 | | //! use bitflags::bitflags; |
123 | | //! |
124 | | //! bitflags! { |
125 | | //! #[repr(transparent)] |
126 | | //! struct Flags: u32 { |
127 | | //! const A = 0b00000001; |
128 | | //! const B = 0b00000010; |
129 | | //! const C = 0b00000100; |
130 | | //! } |
131 | | //! } |
132 | | //! ``` |
133 | | //! |
134 | | //! # Trait implementations |
135 | | //! |
136 | | //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` |
137 | | //! traits are automatically derived for the `struct`s using the `derive` attribute. |
138 | | //! Additional traits can be derived by providing an explicit `derive` |
139 | | //! attribute on `struct`. |
140 | | //! |
141 | | //! The `Extend` and `FromIterator` traits are implemented for the `struct`s, |
142 | | //! too: `Extend` adds the union of the instances of the `struct` iterated over, |
143 | | //! while `FromIterator` calculates the union. |
144 | | //! |
145 | | //! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also |
146 | | //! implemented by displaying the bits value of the internal struct. |
147 | | //! |
148 | | //! ## Operators |
149 | | //! |
150 | | //! The following operator traits are implemented for the generated `struct`s: |
151 | | //! |
152 | | //! - `BitOr` and `BitOrAssign`: union |
153 | | //! - `BitAnd` and `BitAndAssign`: intersection |
154 | | //! - `BitXor` and `BitXorAssign`: toggle |
155 | | //! - `Sub` and `SubAssign`: set difference |
156 | | //! - `Not`: set complement |
157 | | //! |
158 | | //! # Methods |
159 | | //! |
160 | | //! The following methods are defined for the generated `struct`s: |
161 | | //! |
162 | | //! - `empty`: an empty set of flags |
163 | | //! - `all`: the set of all defined flags |
164 | | //! - `bits`: the raw value of the flags currently stored |
165 | | //! - `from_bits`: convert from underlying bit representation, unless that |
166 | | //! representation contains bits that do not correspond to a |
167 | | //! defined flag |
168 | | //! - `from_bits_truncate`: convert from underlying bit representation, dropping |
169 | | //! any bits that do not correspond to defined flags |
170 | | //! - `from_bits_unchecked`: convert from underlying bit representation, keeping |
171 | | //! all bits (even those not corresponding to defined |
172 | | //! flags) |
173 | | //! - `is_empty`: `true` if no flags are currently stored |
174 | | //! - `is_all`: `true` if currently set flags exactly equal all defined flags |
175 | | //! - `intersects`: `true` if there are flags common to both `self` and `other` |
176 | | //! - `contains`: `true` if all of the flags in `other` are contained within `self` |
177 | | //! - `insert`: inserts the specified flags in-place |
178 | | //! - `remove`: removes the specified flags in-place |
179 | | //! - `toggle`: the specified flags will be inserted if not present, and removed |
180 | | //! if they are. |
181 | | //! - `set`: inserts or removes the specified flags depending on the passed value |
182 | | //! - `intersection`: returns a new set of flags, containing only the flags present |
183 | | //! in both `self` and `other` (the argument to the function). |
184 | | //! - `union`: returns a new set of flags, containing any flags present in |
185 | | //! either `self` or `other` (the argument to the function). |
186 | | //! - `difference`: returns a new set of flags, containing all flags present in |
187 | | //! `self` without any of the flags present in `other` (the |
188 | | //! argument to the function). |
189 | | //! - `symmetric_difference`: returns a new set of flags, containing all flags |
190 | | //! present in either `self` or `other` (the argument |
191 | | //! to the function), but not both. |
192 | | //! - `complement`: returns a new set of flags, containing all flags which are |
193 | | //! not set in `self`, but which are allowed for this type. |
194 | | //! |
195 | | //! ## Default |
196 | | //! |
197 | | //! The `Default` trait is not automatically implemented for the generated structs. |
198 | | //! |
199 | | //! If your default value is equal to `0` (which is the same value as calling `empty()` |
200 | | //! on the generated struct), you can simply derive `Default`: |
201 | | //! |
202 | | //! ``` |
203 | | //! use bitflags::bitflags; |
204 | | //! |
205 | | //! bitflags! { |
206 | | //! // Results in default value with bits: 0 |
207 | | //! #[derive(Default)] |
208 | | //! struct Flags: u32 { |
209 | | //! const A = 0b00000001; |
210 | | //! const B = 0b00000010; |
211 | | //! const C = 0b00000100; |
212 | | //! } |
213 | | //! } |
214 | | //! |
215 | | //! fn main() { |
216 | | //! let derived_default: Flags = Default::default(); |
217 | | //! assert_eq!(derived_default.bits(), 0); |
218 | | //! } |
219 | | //! ``` |
220 | | //! |
221 | | //! If your default value is not equal to `0` you need to implement `Default` yourself: |
222 | | //! |
223 | | //! ``` |
224 | | //! use bitflags::bitflags; |
225 | | //! |
226 | | //! bitflags! { |
227 | | //! struct Flags: u32 { |
228 | | //! const A = 0b00000001; |
229 | | //! const B = 0b00000010; |
230 | | //! const C = 0b00000100; |
231 | | //! } |
232 | | //! } |
233 | | //! |
234 | | //! // explicit `Default` implementation |
235 | | //! impl Default for Flags { |
236 | | //! fn default() -> Flags { |
237 | | //! Flags::A | Flags::C |
238 | | //! } |
239 | | //! } |
240 | | //! |
241 | | //! fn main() { |
242 | | //! let implemented_default: Flags = Default::default(); |
243 | | //! assert_eq!(implemented_default, (Flags::A | Flags::C)); |
244 | | //! } |
245 | | //! ``` |
246 | | //! |
247 | | //! # Zero Flags |
248 | | //! |
249 | | //! Flags with a value equal to zero will have some strange behavior that one should be aware of. |
250 | | //! |
251 | | //! ``` |
252 | | //! use bitflags::bitflags; |
253 | | //! |
254 | | //! bitflags! { |
255 | | //! struct Flags: u32 { |
256 | | //! const NONE = 0b00000000; |
257 | | //! const SOME = 0b00000001; |
258 | | //! } |
259 | | //! } |
260 | | //! |
261 | | //! fn main() { |
262 | | //! let empty = Flags::empty(); |
263 | | //! let none = Flags::NONE; |
264 | | //! let some = Flags::SOME; |
265 | | //! |
266 | | //! // Zero flags are treated as always present |
267 | | //! assert!(empty.contains(Flags::NONE)); |
268 | | //! assert!(none.contains(Flags::NONE)); |
269 | | //! assert!(some.contains(Flags::NONE)); |
270 | | //! |
271 | | //! // Zero flags will be ignored when testing for emptiness |
272 | | //! assert!(none.is_empty()); |
273 | | //! } |
274 | | //! ``` |
275 | | //! |
276 | | //! Users should generally avoid defining a flag with a value of zero. |
277 | | |
278 | | #![cfg_attr(not(test), no_std)] |
279 | | #![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")] |
280 | | |
281 | | #[doc(hidden)] |
282 | | pub extern crate core as _core; |
283 | | |
284 | | /// The macro used to generate the flag structures. |
285 | | /// |
286 | | /// See the [crate level docs](../bitflags/index.html) for complete documentation. |
287 | | /// |
288 | | /// # Example |
289 | | /// |
290 | | /// ``` |
291 | | /// use bitflags::bitflags; |
292 | | /// |
293 | | /// bitflags! { |
294 | | /// struct Flags: u32 { |
295 | | /// const A = 0b00000001; |
296 | | /// const B = 0b00000010; |
297 | | /// const C = 0b00000100; |
298 | | /// const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
299 | | /// } |
300 | | /// } |
301 | | /// |
302 | | /// fn main() { |
303 | | /// let e1 = Flags::A | Flags::C; |
304 | | /// let e2 = Flags::B | Flags::C; |
305 | | /// assert_eq!((e1 | e2), Flags::ABC); // union |
306 | | /// assert_eq!((e1 & e2), Flags::C); // intersection |
307 | | /// assert_eq!((e1 - e2), Flags::A); // set difference |
308 | | /// assert_eq!(!e2, Flags::A); // set complement |
309 | | /// } |
310 | | /// ``` |
311 | | /// |
312 | | /// The generated `struct`s can also be extended with type and trait |
313 | | /// implementations: |
314 | | /// |
315 | | /// ``` |
316 | | /// use std::fmt; |
317 | | /// |
318 | | /// use bitflags::bitflags; |
319 | | /// |
320 | | /// bitflags! { |
321 | | /// struct Flags: u32 { |
322 | | /// const A = 0b00000001; |
323 | | /// const B = 0b00000010; |
324 | | /// } |
325 | | /// } |
326 | | /// |
327 | | /// impl Flags { |
328 | | /// pub fn clear(&mut self) { |
329 | | /// self.bits = 0; // The `bits` field can be accessed from within the |
330 | | /// // same module where the `bitflags!` macro was invoked. |
331 | | /// } |
332 | | /// } |
333 | | /// |
334 | | /// impl fmt::Display for Flags { |
335 | | /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
336 | | /// write!(f, "hi!") |
337 | | /// } |
338 | | /// } |
339 | | /// |
340 | | /// fn main() { |
341 | | /// let mut flags = Flags::A | Flags::B; |
342 | | /// flags.clear(); |
343 | | /// assert!(flags.is_empty()); |
344 | | /// assert_eq!(format!("{}", flags), "hi!"); |
345 | | /// assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
346 | | /// assert_eq!(format!("{:?}", Flags::B), "B"); |
347 | | /// } |
348 | | /// ``` |
349 | | #[macro_export(local_inner_macros)] |
350 | | macro_rules! bitflags { |
351 | | ( |
352 | | $(#[$outer:meta])* |
353 | | $vis:vis struct $BitFlags:ident: $T:ty { |
354 | | $( |
355 | | $(#[$inner:ident $($args:tt)*])* |
356 | | const $Flag:ident = $value:expr; |
357 | | )* |
358 | | } |
359 | | |
360 | | $($t:tt)* |
361 | | ) => { |
362 | | $(#[$outer])* |
363 | | #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] |
364 | | $vis struct $BitFlags { |
365 | | bits: $T, |
366 | | } |
367 | | |
368 | | __impl_bitflags! { |
369 | | $BitFlags: $T { |
370 | | $( |
371 | | $(#[$inner $($args)*])* |
372 | | $Flag = $value; |
373 | | )* |
374 | | } |
375 | | } |
376 | | |
377 | | bitflags! { |
378 | | $($t)* |
379 | | } |
380 | | }; |
381 | | () => {}; |
382 | | } |
383 | | |
384 | | // A helper macro to implement the `all` function. |
385 | | #[macro_export(local_inner_macros)] |
386 | | #[doc(hidden)] |
387 | | macro_rules! __impl_all_bitflags { |
388 | | ( |
389 | | $BitFlags:ident: $T:ty { |
390 | | $( |
391 | | $(#[$attr:ident $($args:tt)*])* |
392 | | $Flag:ident = $value:expr; |
393 | | )+ |
394 | | } |
395 | | ) => { |
396 | | // See `Debug::fmt` for why this approach is taken. |
397 | | #[allow(non_snake_case)] |
398 | | trait __BitFlags { |
399 | | $( |
400 | | const $Flag: $T = 0; |
401 | | )+ |
402 | | } |
403 | | #[allow(non_snake_case)] |
404 | | impl __BitFlags for $BitFlags { |
405 | | $( |
406 | | __impl_bitflags! { |
407 | | #[allow(deprecated)] |
408 | | $(? #[$attr $($args)*])* |
409 | | const $Flag: $T = Self::$Flag.bits; |
410 | | } |
411 | | )+ |
412 | | } |
413 | | Self { bits: $(<Self as __BitFlags>::$Flag)|+ } |
414 | | }; |
415 | | ( |
416 | | $BitFlags:ident: $T:ty { } |
417 | | ) => { |
418 | | Self { bits: 0 } |
419 | | }; |
420 | | } |
421 | | |
422 | | #[macro_export(local_inner_macros)] |
423 | | #[doc(hidden)] |
424 | | macro_rules! __impl_bitflags { |
425 | | ( |
426 | | $BitFlags:ident: $T:ty { |
427 | | $( |
428 | | $(#[$attr:ident $($args:tt)*])* |
429 | | $Flag:ident = $value:expr; |
430 | | )* |
431 | | } |
432 | | ) => { |
433 | | impl $crate::_core::fmt::Debug for $BitFlags { |
434 | 0 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
435 | | // This convoluted approach is to handle #[cfg]-based flag |
436 | | // omission correctly. For example it needs to support: |
437 | | // |
438 | | // #[cfg(unix)] const A: Flag = /* ... */; |
439 | | // #[cfg(windows)] const B: Flag = /* ... */; |
440 | | |
441 | | // Unconditionally define a check for every flag, even disabled |
442 | | // ones. |
443 | | #[allow(non_snake_case)] |
444 | | trait __BitFlags { |
445 | | $( |
446 | | #[inline] |
447 | 0 | fn $Flag(&self) -> bool { false } Unexecuted instantiation: <_ as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::IDENTITY Unexecuted instantiation: <_ as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::STRIP_16 Unexecuted instantiation: <_ as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::EXPAND Unexecuted instantiation: <_ as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::ALPHA |
448 | | )* |
449 | | } |
450 | | |
451 | | // Conditionally override the check for just those flags that |
452 | | // are not #[cfg]ed away. |
453 | | #[allow(non_snake_case)] |
454 | | impl __BitFlags for $BitFlags { |
455 | | $( |
456 | | __impl_bitflags! { |
457 | | #[allow(deprecated)] |
458 | | #[inline] |
459 | | $(? #[$attr $($args)*])* |
460 | 0 | fn $Flag(&self) -> bool { |
461 | 0 | if Self::$Flag.bits == 0 && self.bits != 0 { |
462 | 0 | false |
463 | | } else { |
464 | 0 | self.bits & Self::$Flag.bits == Self::$Flag.bits Unexecuted instantiation: <png::common::Transformations as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::IDENTITY Unexecuted instantiation: <png::common::Transformations as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::STRIP_16 Unexecuted instantiation: <png::common::Transformations as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::EXPAND Unexecuted instantiation: <png::common::Transformations as <png::common::Transformations as core::fmt::Debug>::fmt::__BitFlags>::ALPHA |
465 | | } |
466 | | } |
467 | | } |
468 | | )* |
469 | | } |
470 | | |
471 | 0 | let mut first = true; |
472 | | $( |
473 | 0 | if <Self as __BitFlags>::$Flag(self) { |
474 | 0 | if !first { |
475 | 0 | f.write_str(" | ")?; |
476 | 0 | } |
477 | 0 | first = false; |
478 | 0 | f.write_str($crate::_core::stringify!($Flag))?; |
479 | 0 | } |
480 | 0 | )* |
481 | 0 | let extra_bits = self.bits & !Self::all().bits(); |
482 | 0 | if extra_bits != 0 { |
483 | 0 | if !first { |
484 | 0 | f.write_str(" | ")?; |
485 | 0 | } |
486 | 0 | first = false; |
487 | 0 | f.write_str("0x")?; |
488 | 0 | $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?; |
489 | 0 | } |
490 | 0 | if first { |
491 | 0 | f.write_str("(empty)")?; |
492 | 0 | } |
493 | 0 | Ok(()) |
494 | 0 | } |
495 | 0 | } |
496 | 0 | impl $crate::_core::fmt::Binary for $BitFlags { |
497 | 0 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
498 | 0 | $crate::_core::fmt::Binary::fmt(&self.bits, f) |
499 | 0 | } |
500 | | } |
501 | | impl $crate::_core::fmt::Octal for $BitFlags { |
502 | 0 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
503 | 0 | $crate::_core::fmt::Octal::fmt(&self.bits, f) |
504 | 0 | } |
505 | | } |
506 | | impl $crate::_core::fmt::LowerHex for $BitFlags { |
507 | 0 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
508 | 0 | $crate::_core::fmt::LowerHex::fmt(&self.bits, f) |
509 | 0 | } |
510 | | } |
511 | | impl $crate::_core::fmt::UpperHex for $BitFlags { |
512 | 0 | fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result { |
513 | 0 | $crate::_core::fmt::UpperHex::fmt(&self.bits, f) |
514 | 0 | } |
515 | | } |
516 | | |
517 | | #[allow(dead_code)] |
518 | | impl $BitFlags { |
519 | | $( |
520 | | $(#[$attr $($args)*])* |
521 | | pub const $Flag: Self = Self { bits: $value }; |
522 | | )* |
523 | | |
524 | | /// Returns an empty set of flags. |
525 | | #[inline] |
526 | 312 | pub const fn empty() -> Self { |
527 | 312 | Self { bits: 0 } |
528 | 312 | } Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty <png::common::Transformations>::empty Line | Count | Source | 526 | 312 | pub const fn empty() -> Self { | 527 | 312 | Self { bits: 0 } | 528 | 312 | } |
Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty Unexecuted instantiation: <png::common::Transformations>::empty |
529 | | |
530 | | /// Returns the set containing all flags. |
531 | | #[inline] |
532 | 0 | pub const fn all() -> Self { |
533 | 0 | __impl_all_bitflags! { |
534 | 0 | $BitFlags: $T { |
535 | 0 | $( |
536 | 0 | $(#[$attr $($args)*])* |
537 | 0 | $Flag = $value; |
538 | 0 | )* |
539 | 0 | } |
540 | 0 | } |
541 | 0 | } |
542 | | |
543 | | /// Returns the raw value of the flags currently stored. |
544 | | #[inline] |
545 | 624 | pub const fn bits(&self) -> $T { |
546 | 624 | self.bits |
547 | 624 | } Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits <png::common::Transformations>::bits Line | Count | Source | 545 | 624 | pub const fn bits(&self) -> $T { | 546 | 624 | self.bits | 547 | 624 | } |
Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits Unexecuted instantiation: <png::common::Transformations>::bits |
548 | | |
549 | | /// Convert from underlying bit representation, unless that |
550 | | /// representation contains bits that do not correspond to a flag. |
551 | | #[inline] |
552 | 0 | pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> { |
553 | 0 | if (bits & !Self::all().bits()) == 0 { |
554 | 0 | $crate::_core::option::Option::Some(Self { bits }) |
555 | | } else { |
556 | 0 | $crate::_core::option::Option::None |
557 | | } |
558 | 0 | } |
559 | 0 |
|
560 | 0 | /// Convert from underlying bit representation, dropping any bits |
561 | 0 | /// that do not correspond to flags. |
562 | 0 | #[inline] |
563 | 0 | pub const fn from_bits_truncate(bits: $T) -> Self { |
564 | 0 | Self { bits: bits & Self::all().bits } |
565 | 0 | } |
566 | | |
567 | | /// Convert from underlying bit representation, preserving all |
568 | | /// bits (even those not corresponding to a defined flag). |
569 | | /// |
570 | | /// # Safety |
571 | | /// |
572 | | /// The caller of the `bitflags!` macro can chose to allow or |
573 | | /// disallow extra bits for their bitflags type. |
574 | | /// |
575 | | /// The caller of `from_bits_unchecked()` has to ensure that |
576 | | /// all bits correspond to a defined flag or that extra bits |
577 | | /// are valid for this bitflags type. |
578 | | #[inline] |
579 | 0 | pub const unsafe fn from_bits_unchecked(bits: $T) -> Self { |
580 | 0 | Self { bits } |
581 | 0 | } |
582 | | |
583 | | /// Returns `true` if no flags are currently stored. |
584 | | #[inline] |
585 | 312 | pub const fn is_empty(&self) -> bool { |
586 | 312 | self.bits() == Self::empty().bits() |
587 | 312 | } Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty <png::common::Transformations>::is_empty Line | Count | Source | 585 | 312 | pub const fn is_empty(&self) -> bool { | 586 | 312 | self.bits() == Self::empty().bits() | 587 | 312 | } |
Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty Unexecuted instantiation: <png::common::Transformations>::is_empty |
588 | | |
589 | | /// Returns `true` if all flags are currently set. |
590 | | #[inline] |
591 | 0 | pub const fn is_all(&self) -> bool { |
592 | 0 | Self::all().bits | self.bits == self.bits |
593 | 0 | } |
594 | | |
595 | | /// Returns `true` if there are flags common to both `self` and `other`. |
596 | | #[inline] |
597 | 312 | pub const fn intersects(&self, other: Self) -> bool { |
598 | 312 | !(Self { bits: self.bits & other.bits}).is_empty() |
599 | 312 | } Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects <png::common::Transformations>::intersects Line | Count | Source | 597 | 312 | pub const fn intersects(&self, other: Self) -> bool { | 598 | 312 | !(Self { bits: self.bits & other.bits}).is_empty() | 599 | 312 | } |
Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects Unexecuted instantiation: <png::common::Transformations>::intersects |
600 | | |
601 | | /// Returns `true` if all of the flags in `other` are contained within `self`. |
602 | | #[inline] |
603 | 76.7k | pub const fn contains(&self, other: Self) -> bool { |
604 | 76.7k | (self.bits & other.bits) == other.bits |
605 | 76.7k | } Unexecuted instantiation: <png::common::Transformations>::contains <png::common::Transformations>::contains Line | Count | Source | 603 | 2.26k | pub const fn contains(&self, other: Self) -> bool { | 604 | 2.26k | (self.bits & other.bits) == other.bits | 605 | 2.26k | } |
Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains <png::common::Transformations>::contains Line | Count | Source | 603 | 74.4k | pub const fn contains(&self, other: Self) -> bool { | 604 | 74.4k | (self.bits & other.bits) == other.bits | 605 | 74.4k | } |
Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains Unexecuted instantiation: <png::common::Transformations>::contains |
606 | | |
607 | | /// Inserts the specified flags in-place. |
608 | | #[inline] |
609 | 0 | pub fn insert(&mut self, other: Self) { |
610 | 0 | self.bits |= other.bits; |
611 | 0 | } |
612 | | |
613 | | /// Removes the specified flags in-place. |
614 | | #[inline] |
615 | 0 | pub fn remove(&mut self, other: Self) { |
616 | 0 | self.bits &= !other.bits; |
617 | 0 | } |
618 | | |
619 | | /// Toggles the specified flags in-place. |
620 | | #[inline] |
621 | 0 | pub fn toggle(&mut self, other: Self) { |
622 | 0 | self.bits ^= other.bits; |
623 | 0 | } |
624 | | |
625 | | /// Inserts or removes the specified flags depending on the passed value. |
626 | | #[inline] |
627 | 0 | pub fn set(&mut self, other: Self, value: bool) { |
628 | 0 | if value { |
629 | 0 | self.insert(other); |
630 | 0 | } else { |
631 | 0 | self.remove(other); |
632 | 0 | } |
633 | 0 | } |
634 | 0 |
|
635 | 0 | /// Returns the intersection between the flags in `self` and |
636 | 0 | /// `other`. |
637 | 0 | /// |
638 | 0 | /// Specifically, the returned set contains only the flags which are |
639 | 0 | /// present in *both* `self` *and* `other`. |
640 | 0 | /// |
641 | 0 | /// This is equivalent to using the `&` operator (e.g. |
642 | 0 | /// [`ops::BitAnd`]), as in `flags & other`. |
643 | 0 | /// |
644 | 0 | /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html |
645 | 0 | #[inline] |
646 | 0 | #[must_use] |
647 | 0 | pub const fn intersection(self, other: Self) -> Self { |
648 | 0 | Self { bits: self.bits & other.bits } |
649 | 0 | } |
650 | | |
651 | | /// Returns the union of between the flags in `self` and `other`. |
652 | | /// |
653 | | /// Specifically, the returned set contains all flags which are |
654 | | /// present in *either* `self` *or* `other`, including any which are |
655 | | /// present in both (see [`Self::symmetric_difference`] if that |
656 | | /// is undesirable). |
657 | | /// |
658 | | /// This is equivalent to using the `|` operator (e.g. |
659 | | /// [`ops::BitOr`]), as in `flags | other`. |
660 | | /// |
661 | | /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html |
662 | | #[inline] |
663 | | #[must_use] |
664 | 0 | pub const fn union(self, other: Self) -> Self { |
665 | 0 | Self { bits: self.bits | other.bits } |
666 | 0 | } |
667 | | |
668 | | /// Returns the difference between the flags in `self` and `other`. |
669 | | /// |
670 | | /// Specifically, the returned set contains all flags present in |
671 | | /// `self`, except for the ones present in `other`. |
672 | | /// |
673 | | /// It is also conceptually equivalent to the "bit-clear" operation: |
674 | | /// `flags & !other` (and this syntax is also supported). |
675 | | /// |
676 | | /// This is equivalent to using the `-` operator (e.g. |
677 | | /// [`ops::Sub`]), as in `flags - other`. |
678 | | /// |
679 | | /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html |
680 | | #[inline] |
681 | | #[must_use] |
682 | 0 | pub const fn difference(self, other: Self) -> Self { |
683 | 0 | Self { bits: self.bits & !other.bits } |
684 | 0 | } |
685 | | |
686 | | /// Returns the [symmetric difference][sym-diff] between the flags |
687 | | /// in `self` and `other`. |
688 | | /// |
689 | | /// Specifically, the returned set contains the flags present which |
690 | | /// are present in `self` or `other`, but that are not present in |
691 | | /// both. Equivalently, it contains the flags present in *exactly |
692 | | /// one* of the sets `self` and `other`. |
693 | | /// |
694 | | /// This is equivalent to using the `^` operator (e.g. |
695 | | /// [`ops::BitXor`]), as in `flags ^ other`. |
696 | | /// |
697 | | /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference |
698 | | /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html |
699 | | #[inline] |
700 | | #[must_use] |
701 | 0 | pub const fn symmetric_difference(self, other: Self) -> Self { |
702 | 0 | Self { bits: self.bits ^ other.bits } |
703 | 0 | } |
704 | | |
705 | | /// Returns the complement of this set of flags. |
706 | | /// |
707 | | /// Specifically, the returned set contains all the flags which are |
708 | | /// not set in `self`, but which are allowed for this type. |
709 | | /// |
710 | | /// Alternatively, it can be thought of as the set difference |
711 | | /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`) |
712 | | /// |
713 | | /// This is equivalent to using the `!` operator (e.g. |
714 | | /// [`ops::Not`]), as in `!flags`. |
715 | | /// |
716 | | /// [`Self::all()`]: Self::all |
717 | | /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html |
718 | | #[inline] |
719 | | #[must_use] |
720 | 0 | pub const fn complement(self) -> Self { |
721 | 0 | Self::from_bits_truncate(!self.bits) |
722 | 0 | } |
723 | | |
724 | | } |
725 | | |
726 | | impl $crate::_core::ops::BitOr for $BitFlags { |
727 | | type Output = Self; |
728 | | |
729 | | /// Returns the union of the two sets of flags. |
730 | | #[inline] |
731 | 0 | fn bitor(self, other: $BitFlags) -> Self { |
732 | 0 | Self { bits: self.bits | other.bits } |
733 | 0 | } |
734 | | } |
735 | | |
736 | | impl $crate::_core::ops::BitOrAssign for $BitFlags { |
737 | | /// Adds the set of flags. |
738 | | #[inline] |
739 | 0 | fn bitor_assign(&mut self, other: Self) { |
740 | 0 | self.bits |= other.bits; |
741 | 0 | } |
742 | | } |
743 | | |
744 | | impl $crate::_core::ops::BitXor for $BitFlags { |
745 | | type Output = Self; |
746 | | |
747 | | /// Returns the left flags, but with all the right flags toggled. |
748 | | #[inline] |
749 | 0 | fn bitxor(self, other: Self) -> Self { |
750 | 0 | Self { bits: self.bits ^ other.bits } |
751 | 0 | } |
752 | | } |
753 | | |
754 | | impl $crate::_core::ops::BitXorAssign for $BitFlags { |
755 | | /// Toggles the set of flags. |
756 | | #[inline] |
757 | 0 | fn bitxor_assign(&mut self, other: Self) { |
758 | 0 | self.bits ^= other.bits; |
759 | 0 | } |
760 | | } |
761 | | |
762 | | impl $crate::_core::ops::BitAnd for $BitFlags { |
763 | | type Output = Self; |
764 | | |
765 | | /// Returns the intersection between the two sets of flags. |
766 | | #[inline] |
767 | 0 | fn bitand(self, other: Self) -> Self { |
768 | 0 | Self { bits: self.bits & other.bits } |
769 | 0 | } |
770 | | } |
771 | | |
772 | | impl $crate::_core::ops::BitAndAssign for $BitFlags { |
773 | | /// Disables all flags disabled in the set. |
774 | | #[inline] |
775 | 0 | fn bitand_assign(&mut self, other: Self) { |
776 | 0 | self.bits &= other.bits; |
777 | 0 | } |
778 | | } |
779 | | |
780 | | impl $crate::_core::ops::Sub for $BitFlags { |
781 | | type Output = Self; |
782 | | |
783 | | /// Returns the set difference of the two sets of flags. |
784 | | #[inline] |
785 | 0 | fn sub(self, other: Self) -> Self { |
786 | 0 | Self { bits: self.bits & !other.bits } |
787 | 0 | } |
788 | | } |
789 | | |
790 | | impl $crate::_core::ops::SubAssign for $BitFlags { |
791 | | /// Disables all flags enabled in the set. |
792 | | #[inline] |
793 | 0 | fn sub_assign(&mut self, other: Self) { |
794 | 0 | self.bits &= !other.bits; |
795 | 0 | } |
796 | | } |
797 | | |
798 | | impl $crate::_core::ops::Not for $BitFlags { |
799 | | type Output = Self; |
800 | | |
801 | | /// Returns the complement of this set of flags. |
802 | | #[inline] |
803 | 0 | fn not(self) -> Self { |
804 | 0 | Self { bits: !self.bits } & Self::all() |
805 | 0 | } |
806 | | } |
807 | | |
808 | | impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags { |
809 | 0 | fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) { |
810 | 0 | for item in iterator { |
811 | 0 | self.insert(item) |
812 | | } |
813 | 0 | } |
814 | 0 | } |
815 | 0 |
|
816 | 0 | impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags { |
817 | 0 | fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self { |
818 | 0 | let mut result = Self::empty(); |
819 | 0 | result.extend(iterator); |
820 | 0 | result |
821 | 0 | } |
822 | | } |
823 | | }; |
824 | | |
825 | | // Every attribute that the user writes on a const is applied to the |
826 | | // corresponding const that we generate, but within the implementation of |
827 | | // Debug and all() we want to ignore everything but #[cfg] attributes. In |
828 | | // particular, including a #[deprecated] attribute on those items would fail |
829 | | // to compile. |
830 | | // https://github.com/bitflags/bitflags/issues/109 |
831 | | // |
832 | | // Input: |
833 | | // |
834 | | // ? #[cfg(feature = "advanced")] |
835 | | // ? #[deprecated(note = "Use something else.")] |
836 | | // ? #[doc = r"High quality documentation."] |
837 | | // fn f() -> i32 { /* ... */ } |
838 | | // |
839 | | // Output: |
840 | | // |
841 | | // #[cfg(feature = "advanced")] |
842 | | // fn f() -> i32 { /* ... */ } |
843 | | ( |
844 | | $(#[$filtered:meta])* |
845 | | ? #[cfg $($cfgargs:tt)*] |
846 | | $(? #[$rest:ident $($restargs:tt)*])* |
847 | | fn $($item:tt)* |
848 | | ) => { |
849 | | __impl_bitflags! { |
850 | | $(#[$filtered])* |
851 | | #[cfg $($cfgargs)*] |
852 | | $(? #[$rest $($restargs)*])* |
853 | | fn $($item)* |
854 | | } |
855 | | }; |
856 | | ( |
857 | | $(#[$filtered:meta])* |
858 | | // $next != `cfg` |
859 | | ? #[$next:ident $($nextargs:tt)*] |
860 | | $(? #[$rest:ident $($restargs:tt)*])* |
861 | | fn $($item:tt)* |
862 | | ) => { |
863 | | __impl_bitflags! { |
864 | | $(#[$filtered])* |
865 | | // $next filtered out |
866 | | $(? #[$rest $($restargs)*])* |
867 | | fn $($item)* |
868 | | } |
869 | | }; |
870 | | ( |
871 | | $(#[$filtered:meta])* |
872 | | fn $($item:tt)* |
873 | | ) => { |
874 | | $(#[$filtered])* |
875 | | fn $($item)* |
876 | | }; |
877 | | |
878 | | // Every attribute that the user writes on a const is applied to the |
879 | | // corresponding const that we generate, but within the implementation of |
880 | | // Debug and all() we want to ignore everything but #[cfg] attributes. In |
881 | | // particular, including a #[deprecated] attribute on those items would fail |
882 | | // to compile. |
883 | | // https://github.com/bitflags/bitflags/issues/109 |
884 | | // |
885 | | // const version |
886 | | // |
887 | | // Input: |
888 | | // |
889 | | // ? #[cfg(feature = "advanced")] |
890 | | // ? #[deprecated(note = "Use something else.")] |
891 | | // ? #[doc = r"High quality documentation."] |
892 | | // const f: i32 { /* ... */ } |
893 | | // |
894 | | // Output: |
895 | | // |
896 | | // #[cfg(feature = "advanced")] |
897 | | // const f: i32 { /* ... */ } |
898 | | ( |
899 | | $(#[$filtered:meta])* |
900 | | ? #[cfg $($cfgargs:tt)*] |
901 | | $(? #[$rest:ident $($restargs:tt)*])* |
902 | | const $($item:tt)* |
903 | | ) => { |
904 | | __impl_bitflags! { |
905 | | $(#[$filtered])* |
906 | | #[cfg $($cfgargs)*] |
907 | | $(? #[$rest $($restargs)*])* |
908 | | const $($item)* |
909 | | } |
910 | | }; |
911 | | ( |
912 | | $(#[$filtered:meta])* |
913 | | // $next != `cfg` |
914 | | ? #[$next:ident $($nextargs:tt)*] |
915 | | $(? #[$rest:ident $($restargs:tt)*])* |
916 | | const $($item:tt)* |
917 | | ) => { |
918 | | __impl_bitflags! { |
919 | | $(#[$filtered])* |
920 | | // $next filtered out |
921 | | $(? #[$rest $($restargs)*])* |
922 | | const $($item)* |
923 | | } |
924 | | }; |
925 | | ( |
926 | | $(#[$filtered:meta])* |
927 | | const $($item:tt)* |
928 | | ) => { |
929 | | $(#[$filtered])* |
930 | | const $($item)* |
931 | | }; |
932 | | } |
933 | | |
934 | | #[cfg(feature = "example_generated")] |
935 | | pub mod example_generated; |
936 | | |
937 | | #[cfg(test)] |
938 | | mod tests { |
939 | | use std::collections::hash_map::DefaultHasher; |
940 | | use std::hash::{Hash, Hasher}; |
941 | | |
942 | | bitflags! { |
943 | | #[doc = "> The first principle is that you must not fool yourself — and"] |
944 | | #[doc = "> you are the easiest person to fool."] |
945 | | #[doc = "> "] |
946 | | #[doc = "> - Richard Feynman"] |
947 | | #[derive(Default)] |
948 | | struct Flags: u32 { |
949 | | const A = 0b00000001; |
950 | | #[doc = "<pcwalton> macros are way better at generating code than trans is"] |
951 | | const B = 0b00000010; |
952 | | const C = 0b00000100; |
953 | | #[doc = "* cmr bed"] |
954 | | #[doc = "* strcat table"] |
955 | | #[doc = "<strcat> wait what?"] |
956 | | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
957 | | } |
958 | | |
959 | | struct _CfgFlags: u32 { |
960 | | #[cfg(unix)] |
961 | | const _CFG_A = 0b01; |
962 | | #[cfg(windows)] |
963 | | const _CFG_B = 0b01; |
964 | | #[cfg(unix)] |
965 | | const _CFG_C = Self::_CFG_A.bits | 0b10; |
966 | | } |
967 | | |
968 | | struct AnotherSetOfFlags: i8 { |
969 | | const ANOTHER_FLAG = -1_i8; |
970 | | } |
971 | | |
972 | | struct LongFlags: u32 { |
973 | | const LONG_A = 0b1111111111111111; |
974 | | } |
975 | | } |
976 | | |
977 | | bitflags! { |
978 | | struct EmptyFlags: u32 { |
979 | | } |
980 | | } |
981 | | |
982 | | #[test] |
983 | | fn test_bits() { |
984 | | assert_eq!(Flags::empty().bits(), 0b00000000); |
985 | | assert_eq!(Flags::A.bits(), 0b00000001); |
986 | | assert_eq!(Flags::ABC.bits(), 0b00000111); |
987 | | |
988 | | assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); |
989 | | assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8); |
990 | | |
991 | | assert_eq!(EmptyFlags::empty().bits(), 0b00000000); |
992 | | } |
993 | | |
994 | | #[test] |
995 | | fn test_from_bits() { |
996 | | assert_eq!(Flags::from_bits(0), Some(Flags::empty())); |
997 | | assert_eq!(Flags::from_bits(0b1), Some(Flags::A)); |
998 | | assert_eq!(Flags::from_bits(0b10), Some(Flags::B)); |
999 | | assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B)); |
1000 | | assert_eq!(Flags::from_bits(0b1000), None); |
1001 | | |
1002 | | assert_eq!( |
1003 | | AnotherSetOfFlags::from_bits(!0_i8), |
1004 | | Some(AnotherSetOfFlags::ANOTHER_FLAG) |
1005 | | ); |
1006 | | |
1007 | | assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty())); |
1008 | | assert_eq!(EmptyFlags::from_bits(0b1), None); |
1009 | | } |
1010 | | |
1011 | | #[test] |
1012 | | fn test_from_bits_truncate() { |
1013 | | assert_eq!(Flags::from_bits_truncate(0), Flags::empty()); |
1014 | | assert_eq!(Flags::from_bits_truncate(0b1), Flags::A); |
1015 | | assert_eq!(Flags::from_bits_truncate(0b10), Flags::B); |
1016 | | assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B)); |
1017 | | assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty()); |
1018 | | assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A); |
1019 | | |
1020 | | assert_eq!( |
1021 | | AnotherSetOfFlags::from_bits_truncate(0_i8), |
1022 | | AnotherSetOfFlags::empty() |
1023 | | ); |
1024 | | |
1025 | | assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty()); |
1026 | | assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty()); |
1027 | | } |
1028 | | |
1029 | | #[test] |
1030 | | fn test_from_bits_unchecked() { |
1031 | | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1032 | | assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty()); |
1033 | | assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A); |
1034 | | assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B); |
1035 | | |
1036 | | assert_eq!( |
1037 | | unsafe { Flags::from_bits_unchecked(0b11) }, |
1038 | | (Flags::A | Flags::B) |
1039 | | ); |
1040 | | assert_eq!( |
1041 | | unsafe { Flags::from_bits_unchecked(0b1000) }, |
1042 | | (extra | Flags::empty()) |
1043 | | ); |
1044 | | assert_eq!( |
1045 | | unsafe { Flags::from_bits_unchecked(0b1001) }, |
1046 | | (extra | Flags::A) |
1047 | | ); |
1048 | | |
1049 | | let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) }; |
1050 | | assert_eq!( |
1051 | | unsafe { EmptyFlags::from_bits_unchecked(0b1000) }, |
1052 | | (extra | EmptyFlags::empty()) |
1053 | | ); |
1054 | | } |
1055 | | |
1056 | | #[test] |
1057 | | fn test_is_empty() { |
1058 | | assert!(Flags::empty().is_empty()); |
1059 | | assert!(!Flags::A.is_empty()); |
1060 | | assert!(!Flags::ABC.is_empty()); |
1061 | | |
1062 | | assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty()); |
1063 | | |
1064 | | assert!(EmptyFlags::empty().is_empty()); |
1065 | | assert!(EmptyFlags::all().is_empty()); |
1066 | | } |
1067 | | |
1068 | | #[test] |
1069 | | fn test_is_all() { |
1070 | | assert!(Flags::all().is_all()); |
1071 | | assert!(!Flags::A.is_all()); |
1072 | | assert!(Flags::ABC.is_all()); |
1073 | | |
1074 | | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1075 | | assert!(!extra.is_all()); |
1076 | | assert!(!(Flags::A | extra).is_all()); |
1077 | | assert!((Flags::ABC | extra).is_all()); |
1078 | | |
1079 | | assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all()); |
1080 | | |
1081 | | assert!(EmptyFlags::all().is_all()); |
1082 | | assert!(EmptyFlags::empty().is_all()); |
1083 | | } |
1084 | | |
1085 | | #[test] |
1086 | | fn test_two_empties_do_not_intersect() { |
1087 | | let e1 = Flags::empty(); |
1088 | | let e2 = Flags::empty(); |
1089 | | assert!(!e1.intersects(e2)); |
1090 | | |
1091 | | assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG)); |
1092 | | } |
1093 | | |
1094 | | #[test] |
1095 | | fn test_empty_does_not_intersect_with_full() { |
1096 | | let e1 = Flags::empty(); |
1097 | | let e2 = Flags::ABC; |
1098 | | assert!(!e1.intersects(e2)); |
1099 | | } |
1100 | | |
1101 | | #[test] |
1102 | | fn test_disjoint_intersects() { |
1103 | | let e1 = Flags::A; |
1104 | | let e2 = Flags::B; |
1105 | | assert!(!e1.intersects(e2)); |
1106 | | } |
1107 | | |
1108 | | #[test] |
1109 | | fn test_overlapping_intersects() { |
1110 | | let e1 = Flags::A; |
1111 | | let e2 = Flags::A | Flags::B; |
1112 | | assert!(e1.intersects(e2)); |
1113 | | } |
1114 | | |
1115 | | #[test] |
1116 | | fn test_contains() { |
1117 | | let e1 = Flags::A; |
1118 | | let e2 = Flags::A | Flags::B; |
1119 | | assert!(!e1.contains(e2)); |
1120 | | assert!(e2.contains(e1)); |
1121 | | assert!(Flags::ABC.contains(e2)); |
1122 | | |
1123 | | assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG)); |
1124 | | |
1125 | | assert!(EmptyFlags::empty().contains(EmptyFlags::empty())); |
1126 | | } |
1127 | | |
1128 | | #[test] |
1129 | | fn test_insert() { |
1130 | | let mut e1 = Flags::A; |
1131 | | let e2 = Flags::A | Flags::B; |
1132 | | e1.insert(e2); |
1133 | | assert_eq!(e1, e2); |
1134 | | |
1135 | | let mut e3 = AnotherSetOfFlags::empty(); |
1136 | | e3.insert(AnotherSetOfFlags::ANOTHER_FLAG); |
1137 | | assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG); |
1138 | | } |
1139 | | |
1140 | | #[test] |
1141 | | fn test_remove() { |
1142 | | let mut e1 = Flags::A | Flags::B; |
1143 | | let e2 = Flags::A | Flags::C; |
1144 | | e1.remove(e2); |
1145 | | assert_eq!(e1, Flags::B); |
1146 | | |
1147 | | let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG; |
1148 | | e3.remove(AnotherSetOfFlags::ANOTHER_FLAG); |
1149 | | assert_eq!(e3, AnotherSetOfFlags::empty()); |
1150 | | } |
1151 | | |
1152 | | #[test] |
1153 | | fn test_operators() { |
1154 | | let e1 = Flags::A | Flags::C; |
1155 | | let e2 = Flags::B | Flags::C; |
1156 | | assert_eq!((e1 | e2), Flags::ABC); // union |
1157 | | assert_eq!((e1 & e2), Flags::C); // intersection |
1158 | | assert_eq!((e1 - e2), Flags::A); // set difference |
1159 | | assert_eq!(!e2, Flags::A); // set complement |
1160 | | assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle |
1161 | | let mut e3 = e1; |
1162 | | e3.toggle(e2); |
1163 | | assert_eq!(e3, Flags::A | Flags::B); |
1164 | | |
1165 | | let mut m4 = AnotherSetOfFlags::empty(); |
1166 | | m4.toggle(AnotherSetOfFlags::empty()); |
1167 | | assert_eq!(m4, AnotherSetOfFlags::empty()); |
1168 | | } |
1169 | | |
1170 | | #[test] |
1171 | | fn test_operators_unchecked() { |
1172 | | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1173 | | let e1 = Flags::A | Flags::C | extra; |
1174 | | let e2 = Flags::B | Flags::C; |
1175 | | assert_eq!((e1 | e2), (Flags::ABC | extra)); // union |
1176 | | assert_eq!((e1 & e2), Flags::C); // intersection |
1177 | | assert_eq!((e1 - e2), (Flags::A | extra)); // set difference |
1178 | | assert_eq!(!e2, Flags::A); // set complement |
1179 | | assert_eq!(!e1, Flags::B); // set complement |
1180 | | assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle |
1181 | | let mut e3 = e1; |
1182 | | e3.toggle(e2); |
1183 | | assert_eq!(e3, Flags::A | Flags::B | extra); |
1184 | | } |
1185 | | |
1186 | | #[test] |
1187 | | fn test_set_ops_basic() { |
1188 | | let ab = Flags::A.union(Flags::B); |
1189 | | let ac = Flags::A.union(Flags::C); |
1190 | | let bc = Flags::B.union(Flags::C); |
1191 | | assert_eq!(ab.bits, 0b011); |
1192 | | assert_eq!(bc.bits, 0b110); |
1193 | | assert_eq!(ac.bits, 0b101); |
1194 | | |
1195 | | assert_eq!(ab, Flags::B.union(Flags::A)); |
1196 | | assert_eq!(ac, Flags::C.union(Flags::A)); |
1197 | | assert_eq!(bc, Flags::C.union(Flags::B)); |
1198 | | |
1199 | | assert_eq!(ac, Flags::A | Flags::C); |
1200 | | assert_eq!(bc, Flags::B | Flags::C); |
1201 | | assert_eq!(ab.union(bc), Flags::ABC); |
1202 | | |
1203 | | assert_eq!(ac, Flags::A | Flags::C); |
1204 | | assert_eq!(bc, Flags::B | Flags::C); |
1205 | | |
1206 | | assert_eq!(ac.union(bc), ac | bc); |
1207 | | assert_eq!(ac.union(bc), Flags::ABC); |
1208 | | assert_eq!(bc.union(ac), Flags::ABC); |
1209 | | |
1210 | | assert_eq!(ac.intersection(bc), ac & bc); |
1211 | | assert_eq!(ac.intersection(bc), Flags::C); |
1212 | | assert_eq!(bc.intersection(ac), Flags::C); |
1213 | | |
1214 | | assert_eq!(ac.difference(bc), ac - bc); |
1215 | | assert_eq!(bc.difference(ac), bc - ac); |
1216 | | assert_eq!(ac.difference(bc), Flags::A); |
1217 | | assert_eq!(bc.difference(ac), Flags::B); |
1218 | | |
1219 | | assert_eq!(bc.complement(), !bc); |
1220 | | assert_eq!(bc.complement(), Flags::A); |
1221 | | assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B)); |
1222 | | assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B)); |
1223 | | } |
1224 | | |
1225 | | #[test] |
1226 | | fn test_set_ops_const() { |
1227 | | // These just test that these compile and don't cause use-site panics |
1228 | | // (would be possible if we had some sort of UB) |
1229 | | const INTERSECT: Flags = Flags::all().intersection(Flags::C); |
1230 | | const UNION: Flags = Flags::A.union(Flags::C); |
1231 | | const DIFFERENCE: Flags = Flags::all().difference(Flags::A); |
1232 | | const COMPLEMENT: Flags = Flags::C.complement(); |
1233 | | const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE); |
1234 | | assert_eq!(INTERSECT, Flags::C); |
1235 | | assert_eq!(UNION, Flags::A | Flags::C); |
1236 | | assert_eq!(DIFFERENCE, Flags::all() - Flags::A); |
1237 | | assert_eq!(COMPLEMENT, !Flags::C); |
1238 | | assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A)); |
1239 | | } |
1240 | | |
1241 | | #[test] |
1242 | | fn test_set_ops_unchecked() { |
1243 | | let extra = unsafe { Flags::from_bits_unchecked(0b1000) }; |
1244 | | let e1 = Flags::A.union(Flags::C).union(extra); |
1245 | | let e2 = Flags::B.union(Flags::C); |
1246 | | assert_eq!(e1.bits, 0b1101); |
1247 | | assert_eq!(e1.union(e2), (Flags::ABC | extra)); |
1248 | | assert_eq!(e1.intersection(e2), Flags::C); |
1249 | | assert_eq!(e1.difference(e2), Flags::A | extra); |
1250 | | assert_eq!(e2.difference(e1), Flags::B); |
1251 | | assert_eq!(e2.complement(), Flags::A); |
1252 | | assert_eq!(e1.complement(), Flags::B); |
1253 | | assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle |
1254 | | } |
1255 | | |
1256 | | #[test] |
1257 | | fn test_set_ops_exhaustive() { |
1258 | | // Define a flag that contains gaps to help exercise edge-cases, |
1259 | | // especially around "unknown" flags (e.g. ones outside of `all()` |
1260 | | // `from_bits_unchecked`). |
1261 | | // - when lhs and rhs both have different sets of unknown flags. |
1262 | | // - unknown flags at both ends, and in the middle |
1263 | | // - cases with "gaps". |
1264 | | bitflags! { |
1265 | | struct Test: u16 { |
1266 | | // Intentionally no `A` |
1267 | | const B = 0b000000010; |
1268 | | // Intentionally no `C` |
1269 | | const D = 0b000001000; |
1270 | | const E = 0b000010000; |
1271 | | const F = 0b000100000; |
1272 | | const G = 0b001000000; |
1273 | | // Intentionally no `H` |
1274 | | const I = 0b100000000; |
1275 | | } |
1276 | | } |
1277 | | let iter_test_flags = |
1278 | | || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) }); |
1279 | | |
1280 | | for a in iter_test_flags() { |
1281 | | assert_eq!( |
1282 | | a.complement(), |
1283 | | Test::from_bits_truncate(!a.bits), |
1284 | | "wrong result: !({:?})", |
1285 | | a, |
1286 | | ); |
1287 | | assert_eq!(a.complement(), !a, "named != op: !({:?})", a); |
1288 | | for b in iter_test_flags() { |
1289 | | // Check that the named operations produce the expected bitwise |
1290 | | // values. |
1291 | | assert_eq!( |
1292 | | a.union(b).bits, |
1293 | | a.bits | b.bits, |
1294 | | "wrong result: `{:?}` | `{:?}`", |
1295 | | a, |
1296 | | b, |
1297 | | ); |
1298 | | assert_eq!( |
1299 | | a.intersection(b).bits, |
1300 | | a.bits & b.bits, |
1301 | | "wrong result: `{:?}` & `{:?}`", |
1302 | | a, |
1303 | | b, |
1304 | | ); |
1305 | | assert_eq!( |
1306 | | a.symmetric_difference(b).bits, |
1307 | | a.bits ^ b.bits, |
1308 | | "wrong result: `{:?}` ^ `{:?}`", |
1309 | | a, |
1310 | | b, |
1311 | | ); |
1312 | | assert_eq!( |
1313 | | a.difference(b).bits, |
1314 | | a.bits & !b.bits, |
1315 | | "wrong result: `{:?}` - `{:?}`", |
1316 | | a, |
1317 | | b, |
1318 | | ); |
1319 | | // Note: Difference is checked as both `a - b` and `b - a` |
1320 | | assert_eq!( |
1321 | | b.difference(a).bits, |
1322 | | b.bits & !a.bits, |
1323 | | "wrong result: `{:?}` - `{:?}`", |
1324 | | b, |
1325 | | a, |
1326 | | ); |
1327 | | // Check that the named set operations are equivalent to the |
1328 | | // bitwise equivalents |
1329 | | assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,); |
1330 | | assert_eq!( |
1331 | | a.intersection(b), |
1332 | | a & b, |
1333 | | "named != op: `{:?}` & `{:?}`", |
1334 | | a, |
1335 | | b, |
1336 | | ); |
1337 | | assert_eq!( |
1338 | | a.symmetric_difference(b), |
1339 | | a ^ b, |
1340 | | "named != op: `{:?}` ^ `{:?}`", |
1341 | | a, |
1342 | | b, |
1343 | | ); |
1344 | | assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,); |
1345 | | // Note: Difference is checked as both `a - b` and `b - a` |
1346 | | assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,); |
1347 | | // Verify that the operations which should be symmetric are |
1348 | | // actually symmetric. |
1349 | | assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,); |
1350 | | assert_eq!( |
1351 | | a.intersection(b), |
1352 | | b.intersection(a), |
1353 | | "asymmetry: `{:?}` & `{:?}`", |
1354 | | a, |
1355 | | b, |
1356 | | ); |
1357 | | assert_eq!( |
1358 | | a.symmetric_difference(b), |
1359 | | b.symmetric_difference(a), |
1360 | | "asymmetry: `{:?}` ^ `{:?}`", |
1361 | | a, |
1362 | | b, |
1363 | | ); |
1364 | | } |
1365 | | } |
1366 | | } |
1367 | | |
1368 | | #[test] |
1369 | | fn test_set() { |
1370 | | let mut e1 = Flags::A | Flags::C; |
1371 | | e1.set(Flags::B, true); |
1372 | | e1.set(Flags::C, false); |
1373 | | |
1374 | | assert_eq!(e1, Flags::A | Flags::B); |
1375 | | } |
1376 | | |
1377 | | #[test] |
1378 | | fn test_assignment_operators() { |
1379 | | let mut m1 = Flags::empty(); |
1380 | | let e1 = Flags::A | Flags::C; |
1381 | | // union |
1382 | | m1 |= Flags::A; |
1383 | | assert_eq!(m1, Flags::A); |
1384 | | // intersection |
1385 | | m1 &= e1; |
1386 | | assert_eq!(m1, Flags::A); |
1387 | | // set difference |
1388 | | m1 -= m1; |
1389 | | assert_eq!(m1, Flags::empty()); |
1390 | | // toggle |
1391 | | m1 ^= e1; |
1392 | | assert_eq!(m1, e1); |
1393 | | } |
1394 | | |
1395 | | #[test] |
1396 | | fn test_const_fn() { |
1397 | | const _M1: Flags = Flags::empty(); |
1398 | | |
1399 | | const M2: Flags = Flags::A; |
1400 | | assert_eq!(M2, Flags::A); |
1401 | | |
1402 | | const M3: Flags = Flags::C; |
1403 | | assert_eq!(M3, Flags::C); |
1404 | | } |
1405 | | |
1406 | | #[test] |
1407 | | fn test_extend() { |
1408 | | let mut flags; |
1409 | | |
1410 | | flags = Flags::empty(); |
1411 | | flags.extend([].iter().cloned()); |
1412 | | assert_eq!(flags, Flags::empty()); |
1413 | | |
1414 | | flags = Flags::empty(); |
1415 | | flags.extend([Flags::A, Flags::B].iter().cloned()); |
1416 | | assert_eq!(flags, Flags::A | Flags::B); |
1417 | | |
1418 | | flags = Flags::A; |
1419 | | flags.extend([Flags::A, Flags::B].iter().cloned()); |
1420 | | assert_eq!(flags, Flags::A | Flags::B); |
1421 | | |
1422 | | flags = Flags::B; |
1423 | | flags.extend([Flags::A, Flags::ABC].iter().cloned()); |
1424 | | assert_eq!(flags, Flags::ABC); |
1425 | | } |
1426 | | |
1427 | | #[test] |
1428 | | fn test_from_iterator() { |
1429 | | assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty()); |
1430 | | assert_eq!( |
1431 | | [Flags::A, Flags::B].iter().cloned().collect::<Flags>(), |
1432 | | Flags::A | Flags::B |
1433 | | ); |
1434 | | assert_eq!( |
1435 | | [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(), |
1436 | | Flags::ABC |
1437 | | ); |
1438 | | } |
1439 | | |
1440 | | #[test] |
1441 | | fn test_lt() { |
1442 | | let mut a = Flags::empty(); |
1443 | | let mut b = Flags::empty(); |
1444 | | |
1445 | | assert!(!(a < b) && !(b < a)); |
1446 | | b = Flags::B; |
1447 | | assert!(a < b); |
1448 | | a = Flags::C; |
1449 | | assert!(!(a < b) && b < a); |
1450 | | b = Flags::C | Flags::B; |
1451 | | assert!(a < b); |
1452 | | } |
1453 | | |
1454 | | #[test] |
1455 | | fn test_ord() { |
1456 | | let mut a = Flags::empty(); |
1457 | | let mut b = Flags::empty(); |
1458 | | |
1459 | | assert!(a <= b && a >= b); |
1460 | | a = Flags::A; |
1461 | | assert!(a > b && a >= b); |
1462 | | assert!(b < a && b <= a); |
1463 | | b = Flags::B; |
1464 | | assert!(b > a && b >= a); |
1465 | | assert!(a < b && a <= b); |
1466 | | } |
1467 | | |
1468 | | fn hash<T: Hash>(t: &T) -> u64 { |
1469 | | let mut s = DefaultHasher::new(); |
1470 | | t.hash(&mut s); |
1471 | | s.finish() |
1472 | | } |
1473 | | |
1474 | | #[test] |
1475 | | fn test_hash() { |
1476 | | let mut x = Flags::empty(); |
1477 | | let mut y = Flags::empty(); |
1478 | | assert_eq!(hash(&x), hash(&y)); |
1479 | | x = Flags::all(); |
1480 | | y = Flags::ABC; |
1481 | | assert_eq!(hash(&x), hash(&y)); |
1482 | | } |
1483 | | |
1484 | | #[test] |
1485 | | fn test_default() { |
1486 | | assert_eq!(Flags::empty(), Flags::default()); |
1487 | | } |
1488 | | |
1489 | | #[test] |
1490 | | fn test_debug() { |
1491 | | assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); |
1492 | | assert_eq!(format!("{:?}", Flags::empty()), "(empty)"); |
1493 | | assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC"); |
1494 | | let extra = unsafe { Flags::from_bits_unchecked(0xb8) }; |
1495 | | assert_eq!(format!("{:?}", extra), "0xb8"); |
1496 | | assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8"); |
1497 | | |
1498 | | assert_eq!( |
1499 | | format!("{:?}", Flags::ABC | extra), |
1500 | | "A | B | C | ABC | 0xb8" |
1501 | | ); |
1502 | | |
1503 | | assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)"); |
1504 | | } |
1505 | | |
1506 | | #[test] |
1507 | | fn test_binary() { |
1508 | | assert_eq!(format!("{:b}", Flags::ABC), "111"); |
1509 | | assert_eq!(format!("{:#b}", Flags::ABC), "0b111"); |
1510 | | let extra = unsafe { Flags::from_bits_unchecked(0b1010000) }; |
1511 | | assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111"); |
1512 | | assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111"); |
1513 | | } |
1514 | | |
1515 | | #[test] |
1516 | | fn test_octal() { |
1517 | | assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777"); |
1518 | | assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777"); |
1519 | | let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) }; |
1520 | | assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777"); |
1521 | | assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777"); |
1522 | | } |
1523 | | |
1524 | | #[test] |
1525 | | fn test_lowerhex() { |
1526 | | assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff"); |
1527 | | assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff"); |
1528 | | let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; |
1529 | | assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff"); |
1530 | | assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff"); |
1531 | | } |
1532 | | |
1533 | | #[test] |
1534 | | fn test_upperhex() { |
1535 | | assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF"); |
1536 | | assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF"); |
1537 | | let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) }; |
1538 | | assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF"); |
1539 | | assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF"); |
1540 | | } |
1541 | | |
1542 | | mod submodule { |
1543 | | bitflags! { |
1544 | | pub struct PublicFlags: i8 { |
1545 | | const X = 0; |
1546 | | } |
1547 | | |
1548 | | struct PrivateFlags: i8 { |
1549 | | const Y = 0; |
1550 | | } |
1551 | | } |
1552 | | |
1553 | | #[test] |
1554 | | fn test_private() { |
1555 | | let _ = PrivateFlags::Y; |
1556 | | } |
1557 | | } |
1558 | | |
1559 | | #[test] |
1560 | | fn test_public() { |
1561 | | let _ = submodule::PublicFlags::X; |
1562 | | } |
1563 | | |
1564 | | mod t1 { |
1565 | | mod foo { |
1566 | | pub type Bar = i32; |
1567 | | } |
1568 | | |
1569 | | bitflags! { |
1570 | | /// baz |
1571 | | struct Flags: foo::Bar { |
1572 | | const A = 0b00000001; |
1573 | | #[cfg(foo)] |
1574 | | const B = 0b00000010; |
1575 | | #[cfg(foo)] |
1576 | | const C = 0b00000010; |
1577 | | } |
1578 | | } |
1579 | | } |
1580 | | |
1581 | | #[test] |
1582 | | fn test_in_function() { |
1583 | | bitflags! { |
1584 | | struct Flags: u8 { |
1585 | | const A = 1; |
1586 | | #[cfg(any())] // false |
1587 | | const B = 2; |
1588 | | } |
1589 | | } |
1590 | | assert_eq!(Flags::all(), Flags::A); |
1591 | | assert_eq!(format!("{:?}", Flags::A), "A"); |
1592 | | } |
1593 | | |
1594 | | #[test] |
1595 | | fn test_deprecated() { |
1596 | | bitflags! { |
1597 | | pub struct TestFlags: u32 { |
1598 | | #[deprecated(note = "Use something else.")] |
1599 | | const ONE = 1; |
1600 | | } |
1601 | | } |
1602 | | } |
1603 | | |
1604 | | #[test] |
1605 | | fn test_pub_crate() { |
1606 | | mod module { |
1607 | | bitflags! { |
1608 | | pub (crate) struct Test: u8 { |
1609 | | const FOO = 1; |
1610 | | } |
1611 | | } |
1612 | | } |
1613 | | |
1614 | | assert_eq!(module::Test::FOO.bits(), 1); |
1615 | | } |
1616 | | |
1617 | | #[test] |
1618 | | fn test_pub_in_module() { |
1619 | | mod module { |
1620 | | mod submodule { |
1621 | | bitflags! { |
1622 | | // `pub (in super)` means only the module `module` will |
1623 | | // be able to access this. |
1624 | | pub (in super) struct Test: u8 { |
1625 | | const FOO = 1; |
1626 | | } |
1627 | | } |
1628 | | } |
1629 | | |
1630 | | mod test { |
1631 | | // Note: due to `pub (in super)`, |
1632 | | // this cannot be accessed directly by the testing code. |
1633 | | pub(super) fn value() -> u8 { |
1634 | | super::submodule::Test::FOO.bits() |
1635 | | } |
1636 | | } |
1637 | | |
1638 | | pub fn value() -> u8 { |
1639 | | test::value() |
1640 | | } |
1641 | | } |
1642 | | |
1643 | | assert_eq!(module::value(), 1) |
1644 | | } |
1645 | | |
1646 | | #[test] |
1647 | | fn test_zero_value_flags() { |
1648 | | bitflags! { |
1649 | | struct Flags: u32 { |
1650 | | const NONE = 0b0; |
1651 | | const SOME = 0b1; |
1652 | | } |
1653 | | } |
1654 | | |
1655 | | assert!(Flags::empty().contains(Flags::NONE)); |
1656 | | assert!(Flags::SOME.contains(Flags::NONE)); |
1657 | | assert!(Flags::NONE.is_empty()); |
1658 | | |
1659 | | assert_eq!(format!("{:?}", Flags::empty()), "NONE"); |
1660 | | assert_eq!(format!("{:?}", Flags::SOME), "SOME"); |
1661 | | } |
1662 | | |
1663 | | #[test] |
1664 | | fn test_empty_bitflags() { |
1665 | | bitflags! {} |
1666 | | } |
1667 | | |
1668 | | #[test] |
1669 | | fn test_u128_bitflags() { |
1670 | | bitflags! { |
1671 | | struct Flags128: u128 { |
1672 | | const A = 0x0000_0000_0000_0000_0000_0000_0000_0001; |
1673 | | const B = 0x0000_0000_0000_1000_0000_0000_0000_0000; |
1674 | | const C = 0x8000_0000_0000_0000_0000_0000_0000_0000; |
1675 | | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; |
1676 | | } |
1677 | | } |
1678 | | |
1679 | | assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C); |
1680 | | assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001); |
1681 | | assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000); |
1682 | | assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000); |
1683 | | assert_eq!( |
1684 | | Flags128::ABC.bits, |
1685 | | 0x8000_0000_0000_1000_0000_0000_0000_0001 |
1686 | | ); |
1687 | | assert_eq!(format!("{:?}", Flags128::A), "A"); |
1688 | | assert_eq!(format!("{:?}", Flags128::B), "B"); |
1689 | | assert_eq!(format!("{:?}", Flags128::C), "C"); |
1690 | | assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC"); |
1691 | | } |
1692 | | |
1693 | | #[test] |
1694 | | fn test_serde_bitflags_serialize() { |
1695 | | let flags = SerdeFlags::A | SerdeFlags::B; |
1696 | | |
1697 | | let serialized = serde_json::to_string(&flags).unwrap(); |
1698 | | |
1699 | | assert_eq!(serialized, r#"{"bits":3}"#); |
1700 | | } |
1701 | | |
1702 | | #[test] |
1703 | | fn test_serde_bitflags_deserialize() { |
1704 | | let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap(); |
1705 | | |
1706 | | let expected = SerdeFlags::C | SerdeFlags::D; |
1707 | | |
1708 | | assert_eq!(deserialized.bits, expected.bits); |
1709 | | } |
1710 | | |
1711 | | #[test] |
1712 | | fn test_serde_bitflags_roundtrip() { |
1713 | | let flags = SerdeFlags::A | SerdeFlags::B; |
1714 | | |
1715 | | let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap(); |
1716 | | |
1717 | | assert_eq!(deserialized.bits, flags.bits); |
1718 | | } |
1719 | | |
1720 | | bitflags! { |
1721 | | #[derive(serde::Serialize, serde::Deserialize)] |
1722 | | struct SerdeFlags: u32 { |
1723 | | const A = 1; |
1724 | | const B = 2; |
1725 | | const C = 4; |
1726 | | const D = 8; |
1727 | | } |
1728 | | } |
1729 | | } |