1 // 2 // Copyright 2019 Red Hat, Inc. 3 // 4 // Author: Nathaniel McCallum <npmccallum@redhat.com> 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 // 18 19 //! # Welcome to FlagSet! 20 //! 21 //! FlagSet is a new, ergonomic approach to handling flags that combines the 22 //! best of existing crates like `bitflags` and `enumflags` without their 23 //! downsides. 24 //! 25 //! ## Existing Implementations 26 //! 27 //! The `bitflags` crate has long been part of the Rust ecosystem. 28 //! Unfortunately, it doesn't feel like natural Rust. The `bitflags` crate 29 //! uses a wierd struct format to define flags. Flags themselves are just 30 //! integers constants, so there is little type-safety involved. But it doesn't 31 //! have any dependencies. It also allows you to define implied flags (otherwise 32 //! known as overlapping flags). 33 //! 34 //! The `enumflags` crate tried to improve on `bitflags` by using enumerations 35 //! to define flags. This was a big improvement to the natural feel of the code. 36 //! Unfortunately, there are some design flaws. To generate the flags, 37 //! procedural macros were used. This implied two separate crates plus 38 //! additional dependencies. Further, `enumflags` specifies the size of the 39 //! flags using a `repr($size)` attribute. Unfortunately, this attribute 40 //! cannot resolve type aliases, such as `c_int`. This makes `enumflags` a 41 //! poor fit for FFI, which is the most important place for a flags library. 42 //! The `enumflags` crate also disallows overlapping flags and is not 43 //! maintained. 44 //! 45 //! FlagSet improves on both of these by adopting the `enumflags` natural feel 46 //! and the `bitflags` mode of flag generation; as well as additional API usage 47 //! niceties. FlagSet has no dependencies and is extensively documented and 48 //! tested. It also tries very hard to prevent you from making mistakes by 49 //! avoiding external usage of the integer types. FlagSet is also a zero-cost 50 //! abstraction: all functions are inlineable and should reduce to the core 51 //! integer operations. FlagSet also does not depend on stdlib, so it can be 52 //! used in `no_std` libraries and applications. 53 //! 54 //! ## Defining Flags 55 //! 56 //! Flags are defined using the `flags!` macro: 57 //! 58 //! ``` 59 //! use flagset::{FlagSet, flags}; 60 //! use std::os::raw::c_int; 61 //! 62 //! flags! { 63 //! enum FlagsA: u8 { 64 //! Foo, 65 //! Bar, 66 //! Baz, 67 //! } 68 //! 69 //! enum FlagsB: c_int { 70 //! Foo, 71 //! Bar, 72 //! Baz, 73 //! } 74 //! } 75 //! ``` 76 //! 77 //! Notice that a flag definition looks just like a regular enumeration, with 78 //! the addition of the field-size type. The field-size type is required and 79 //! can be either a type or a type alias. Both examples are given above. 80 //! 81 //! Also note that the field-size type specifies the size of the corresponding 82 //! `FlagSet` type, not size of the enumeration itself. To specify the size of 83 //! the enumeration, use the `repr($size)` attribute as specified below. 84 //! 85 //! ## Flag Values 86 //! 87 //! Flags often need values assigned to them. This can be done implicitly, 88 //! where the value depends on the order of the flags: 89 //! 90 //! ``` 91 //! use flagset::{FlagSet, flags}; 92 //! 93 //! flags! { 94 //! enum Flags: u16 { 95 //! Foo, // Implicit Value: 0b0001 96 //! Bar, // Implicit Value: 0b0010 97 //! Baz, // Implicit Value: 0b0100 98 //! } 99 //! } 100 //! ``` 101 //! 102 //! Alternatively, flag values can be defined explicitly, by specifying any 103 //! `const` expression: 104 //! 105 //! ``` 106 //! use flagset::{FlagSet, flags}; 107 //! 108 //! flags! { 109 //! enum Flags: u16 { 110 //! Foo = 0x01, // Explicit Value: 0b0001 111 //! Bar = 2, // Explicit Value: 0b0010 112 //! Baz = 0b0100, // Explicit Value: 0b0100 113 //! } 114 //! } 115 //! ``` 116 //! 117 //! Flags can also overlap or "imply" other flags: 118 //! 119 //! ``` 120 //! use flagset::{FlagSet, flags}; 121 //! 122 //! flags! { 123 //! enum Flags: u16 { 124 //! Foo = 0b0001, 125 //! Bar = 0b0010, 126 //! Baz = 0b0110, // Implies Bar 127 //! All = (Flags::Foo | Flags::Bar | Flags::Baz).bits(), 128 //! } 129 //! } 130 //! ``` 131 //! 132 //! ## Specifying Attributes 133 //! 134 //! Attributes can be used on the enumeration itself or any of the values: 135 //! 136 //! ``` 137 //! use flagset::{FlagSet, flags}; 138 //! 139 //! flags! { 140 //! #[derive(PartialOrd, Ord)] 141 //! enum Flags: u8 { 142 //! Foo, 143 //! #[deprecated] 144 //! Bar, 145 //! Baz, 146 //! } 147 //! } 148 //! ``` 149 //! 150 //! ## Collections of Flags 151 //! 152 //! A collection of flags is a `FlagSet<T>`. If you are storing the flags in 153 //! memory, the raw `FlagSet<T>` type should be used. However, if you want to 154 //! receive flags as an input to a function, you should use 155 //! `impl Into<FlagSet<T>>`. This allows for very ergonomic APIs: 156 //! 157 //! ``` 158 //! use flagset::{FlagSet, flags}; 159 //! 160 //! flags! { 161 //! enum Flags: u8 { 162 //! Foo, 163 //! Bar, 164 //! Baz, 165 //! } 166 //! } 167 //! 168 //! struct Container(FlagSet<Flags>); 169 //! 170 //! impl Container { 171 //! fn new(flags: impl Into<FlagSet<Flags>>) -> Container { 172 //! Container(flags.into()) 173 //! } 174 //! } 175 //! 176 //! assert_eq!(Container::new(Flags::Foo | Flags::Bar).0.bits(), 0b011); 177 //! assert_eq!(Container::new(Flags::Foo).0.bits(), 0b001); 178 //! assert_eq!(Container::new(None).0.bits(), 0b000); 179 //! ``` 180 //! 181 //! ## Operations 182 //! 183 //! Operations can be performed on a `FlagSet<F>` or on individual flags: 184 //! 185 //! | Operator | Assignment Operator | Meaning | 186 //! |----------|---------------------|------------------------| 187 //! | \| | \|= | Union | 188 //! | & | &= | Intersection | 189 //! | ^ | ^= | Toggle specified flags | 190 //! | - | -= | Difference | 191 //! | % | %= | Symmetric difference | 192 //! | ! | | Toggle all flags | 193 //! 194 #![cfg_attr( 195 feature = "serde", 196 doc = r#" 197 198 ## Optional Serde support 199 200 [Serde] support can be enabled with the 'serde' feature flag. You can then serialize and 201 deserialize `FlagSet<T>` to and from any of the [supported formats]: 202 203 ``` 204 use flagset::{FlagSet, flags}; 205 206 flags! { 207 enum Flags: u8 { 208 Foo, 209 Bar, 210 } 211 } 212 213 let flagset = Flags::Foo | Flags::Bar; 214 let json = serde_json::to_string(&flagset).unwrap(); 215 let flagset: FlagSet<Flags> = serde_json::from_str(&json).unwrap(); 216 assert_eq!(flagset.bits(), 0b011); 217 ``` 218 219 For serialization and deserialization of flags enum itself, you can use the [`serde_repr`] crate 220 (or implement `serde::ser::Serialize` and `serde:de::Deserialize` manually), combined with the 221 appropriate `repr` attribute: 222 223 ``` 224 use flagset::{FlagSet, flags}; 225 use serde_repr::{Serialize_repr, Deserialize_repr}; 226 227 flags! { 228 #[repr(u8)] 229 #[derive(Deserialize_repr, Serialize_repr)] 230 enum Flags: u8 { 231 Foo, 232 Bar, 233 } 234 } 235 236 let json = serde_json::to_string(&Flags::Foo).unwrap(); 237 let flag: Flags = serde_json::from_str(&json).unwrap(); 238 assert_eq!(flag, Flags::Foo); 239 ``` 240 241 [Serde]: https://serde.rs/ 242 [supported formats]: https://serde.rs/#data-formats 243 [`serde_repr`]: https://crates.io/crates/serde_repr 244 "# 245 )] 246 #![allow(unknown_lints)] 247 #![warn(clippy::all)] 248 #![no_std] 249 250 /// Local Android change: Use std to allow building as a dylib. 251 #[cfg(android_dylib)] 252 extern crate std; 253 254 use core::fmt::{Debug, Formatter, Result}; 255 use core::ops::*; 256 257 /// Error type returned when creating a new flagset from bits is invalid or undefined. 258 /// ``` 259 /// use flagset::{FlagSet, flags}; 260 /// 261 /// flags! { 262 /// pub enum Flag: u16 { 263 /// Foo = 0b0001, 264 /// Bar = 0b0010, 265 /// Baz = 0b0100, 266 /// Qux = 0b1010, // Implies Bar 267 /// } 268 /// } 269 /// 270 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid 271 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown 272 /// ``` 273 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 274 pub struct InvalidBits; 275 276 impl core::fmt::Display for InvalidBits { 277 #[inline] fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result278 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 279 write!(f, "invalid bits") 280 } 281 } 282 283 #[doc(hidden)] 284 pub trait Flags: 285 Copy 286 + Clone 287 + Debug 288 + PartialEq 289 + Eq 290 + BitAnd<Self, Output = FlagSet<Self>> 291 + BitOr<Self, Output = FlagSet<Self>> 292 + BitXor<Self, Output = FlagSet<Self>> 293 + Sub<Self, Output = FlagSet<Self>> 294 + Rem<Self, Output = FlagSet<Self>> 295 + Not<Output = FlagSet<Self>> 296 + Into<FlagSet<Self>> 297 + 'static 298 { 299 type Type: Copy 300 + Clone 301 + Debug 302 + PartialEq 303 + Eq 304 + Default 305 + BitAnd<Self::Type, Output = Self::Type> 306 + BitAndAssign<Self::Type> 307 + BitOr<Self::Type, Output = Self::Type> 308 + BitOrAssign<Self::Type> 309 + BitXor<Self::Type, Output = Self::Type> 310 + BitXorAssign<Self::Type> 311 + Not<Output = Self::Type>; 312 313 /// A slice containing all the possible flag values. 314 const LIST: &'static [Self]; 315 316 /// Creates an empty `FlagSet` of this type 317 #[inline] none() -> FlagSet<Self>318 fn none() -> FlagSet<Self> { 319 FlagSet::default() 320 } 321 } 322 323 #[derive(Copy, Clone, Eq)] 324 pub struct FlagSet<F: Flags>(F::Type); 325 326 #[doc(hidden)] 327 #[derive(Copy, Clone)] 328 pub struct Iter<F: Flags>(FlagSet<F>, usize); 329 330 impl<F: Flags> Iterator for Iter<F> { 331 type Item = F; 332 333 #[inline] next(&mut self) -> Option<Self::Item>334 fn next(&mut self) -> Option<Self::Item> { 335 while self.1 < F::LIST.len() { 336 let next = F::LIST[self.1]; 337 self.1 += 1; 338 339 if self.0.contains(next) { 340 return Some(next); 341 } 342 } 343 344 None 345 } 346 } 347 348 impl<F: Flags> IntoIterator for FlagSet<F> { 349 type Item = F; 350 type IntoIter = Iter<F>; 351 352 /// Iterate over the flags in the set. 353 /// 354 /// **NOTE**: The order in which the flags are iterated is undefined. 355 /// 356 /// ``` 357 /// use flagset::{FlagSet, flags}; 358 /// 359 /// flags! { 360 /// enum Flag: u8 { 361 /// Foo = 0b001, 362 /// Bar = 0b010, 363 /// Baz = 0b100 364 /// } 365 /// } 366 /// 367 /// let set = Flag::Foo | Flag::Bar; 368 /// let mut iter = set.into_iter(); 369 /// assert_eq!(iter.next(), Some(Flag::Foo)); 370 /// assert_eq!(iter.next(), Some(Flag::Bar)); 371 /// assert_eq!(iter.next(), None); 372 /// ``` 373 #[inline] into_iter(self) -> Self::IntoIter374 fn into_iter(self) -> Self::IntoIter { 375 Iter(self, 0) 376 } 377 } 378 379 impl<F: Flags> Debug for FlagSet<F> { 380 #[inline] fmt(&self, f: &mut Formatter) -> Result381 fn fmt(&self, f: &mut Formatter) -> Result { 382 write!(f, "FlagSet(")?; 383 for (i, flag) in self.into_iter().enumerate() { 384 write!(f, "{}{:?}", if i > 0 { " | " } else { "" }, flag)?; 385 } 386 write!(f, ")") 387 } 388 } 389 390 impl<F: Flags, R: Copy + Into<FlagSet<F>>> PartialEq<R> for FlagSet<F> { 391 #[inline] eq(&self, rhs: &R) -> bool392 fn eq(&self, rhs: &R) -> bool { 393 self.0 == (*rhs).into().0 394 } 395 } 396 397 impl<F: Flags> AsRef<F::Type> for FlagSet<F> { 398 #[inline] as_ref(&self) -> &F::Type399 fn as_ref(&self) -> &F::Type { 400 &self.0 401 } 402 } 403 404 impl<F: Flags> From<Option<FlagSet<F>>> for FlagSet<F> { 405 /// Converts from `Option<FlagSet<F>>` to `FlagSet<F>`. 406 /// 407 /// Most notably, this allows for the use of `None` in many places to 408 /// substitute for manually creating an empty `FlagSet<F>`. See below. 409 /// 410 /// ``` 411 /// use flagset::{FlagSet, flags}; 412 /// 413 /// flags! { 414 /// enum Flag: u8 { 415 /// Foo = 0b001, 416 /// Bar = 0b010, 417 /// Baz = 0b100 418 /// } 419 /// } 420 /// 421 /// fn convert(v: impl Into<FlagSet<Flag>>) -> u8 { 422 /// v.into().bits() 423 /// } 424 /// 425 /// assert_eq!(convert(Flag::Foo | Flag::Bar), 0b011); 426 /// assert_eq!(convert(Flag::Foo), 0b001); 427 /// assert_eq!(convert(None), 0b000); 428 /// ``` 429 #[inline] from(value: Option<FlagSet<F>>) -> FlagSet<F>430 fn from(value: Option<FlagSet<F>>) -> FlagSet<F> { 431 value.unwrap_or_default() 432 } 433 } 434 435 impl<F: Flags> Default for FlagSet<F> { 436 /// Creates a new, empty FlagSet. 437 /// 438 /// ``` 439 /// use flagset::{FlagSet, flags}; 440 /// 441 /// flags! { 442 /// enum Flag: u8 { 443 /// Foo = 0b001, 444 /// Bar = 0b010, 445 /// Baz = 0b100 446 /// } 447 /// } 448 /// 449 /// let set = FlagSet::<Flag>::default(); 450 /// assert!(set.is_empty()); 451 /// assert!(!set.is_full()); 452 /// assert!(!set.contains(Flag::Foo)); 453 /// assert!(!set.contains(Flag::Bar)); 454 /// assert!(!set.contains(Flag::Baz)); 455 /// ``` 456 #[inline] default() -> Self457 fn default() -> Self { 458 FlagSet(F::Type::default()) 459 } 460 } 461 462 impl<F: Flags> Not for FlagSet<F> { 463 type Output = Self; 464 465 /// Calculates the complement of the current set. 466 /// 467 /// In common parlance, this returns the set of all possible flags that are 468 /// not in the current set. 469 /// 470 /// ``` 471 /// use flagset::{FlagSet, flags}; 472 /// 473 /// flags! { 474 /// #[derive(PartialOrd, Ord)] 475 /// enum Flag: u8 { 476 /// Foo = 1 << 0, 477 /// Bar = 1 << 1, 478 /// Baz = 1 << 2 479 /// } 480 /// } 481 /// 482 /// let set = !FlagSet::from(Flag::Foo); 483 /// assert!(!set.is_empty()); 484 /// assert!(!set.is_full()); 485 /// assert!(!set.contains(Flag::Foo)); 486 /// assert!(set.contains(Flag::Bar)); 487 /// assert!(set.contains(Flag::Baz)); 488 /// ``` 489 #[inline] not(self) -> Self490 fn not(self) -> Self { 491 FlagSet(!self.0) 492 } 493 } 494 495 impl<F: Flags, R: Into<FlagSet<F>>> BitAnd<R> for FlagSet<F> { 496 type Output = Self; 497 498 /// Calculates the intersection of the current set and the specified flags. 499 /// 500 /// ``` 501 /// use flagset::{FlagSet, flags}; 502 /// 503 /// flags! { 504 /// #[derive(PartialOrd, Ord)] 505 /// pub enum Flag: u8 { 506 /// Foo = 0b001, 507 /// Bar = 0b010, 508 /// Baz = 0b100 509 /// } 510 /// } 511 /// 512 /// let set0 = Flag::Foo | Flag::Bar; 513 /// let set1 = Flag::Baz | Flag::Bar; 514 /// assert_eq!(set0 & set1, Flag::Bar); 515 /// assert_eq!(set0 & Flag::Foo, Flag::Foo); 516 /// assert_eq!(set1 & Flag::Baz, Flag::Baz); 517 /// ``` 518 #[inline] bitand(self, rhs: R) -> Self519 fn bitand(self, rhs: R) -> Self { 520 FlagSet(self.0 & rhs.into().0) 521 } 522 } 523 524 impl<F: Flags, R: Into<FlagSet<F>>> BitAndAssign<R> for FlagSet<F> { 525 /// Assigns the intersection of the current set and the specified flags. 526 /// 527 /// ``` 528 /// use flagset::{FlagSet, flags}; 529 /// 530 /// flags! { 531 /// enum Flag: u64 { 532 /// Foo = 0b001, 533 /// Bar = 0b010, 534 /// Baz = 0b100 535 /// } 536 /// } 537 /// 538 /// let mut set0 = Flag::Foo | Flag::Bar; 539 /// let mut set1 = Flag::Baz | Flag::Bar; 540 /// 541 /// set0 &= set1; 542 /// assert_eq!(set0, Flag::Bar); 543 /// 544 /// set1 &= Flag::Baz; 545 /// assert_eq!(set0, Flag::Bar); 546 /// ``` 547 #[inline] bitand_assign(&mut self, rhs: R)548 fn bitand_assign(&mut self, rhs: R) { 549 self.0 &= rhs.into().0 550 } 551 } 552 553 impl<F: Flags, R: Into<FlagSet<F>>> BitOr<R> for FlagSet<F> { 554 type Output = Self; 555 556 /// Calculates the union of the current set with the specified flags. 557 /// 558 /// ``` 559 /// use flagset::{FlagSet, flags}; 560 /// 561 /// flags! { 562 /// #[derive(PartialOrd, Ord)] 563 /// pub enum Flag: u8 { 564 /// Foo = 0b001, 565 /// Bar = 0b010, 566 /// Baz = 0b100 567 /// } 568 /// } 569 /// 570 /// let set0 = Flag::Foo | Flag::Bar; 571 /// let set1 = Flag::Baz | Flag::Bar; 572 /// assert_eq!(set0 | set1, FlagSet::full()); 573 /// ``` 574 #[inline] bitor(self, rhs: R) -> Self575 fn bitor(self, rhs: R) -> Self { 576 FlagSet(self.0 | rhs.into().0) 577 } 578 } 579 580 impl<F: Flags, R: Into<FlagSet<F>>> BitOrAssign<R> for FlagSet<F> { 581 /// Assigns the union of the current set with the specified flags. 582 /// 583 /// ``` 584 /// use flagset::{FlagSet, flags}; 585 /// 586 /// flags! { 587 /// enum Flag: u64 { 588 /// Foo = 0b001, 589 /// Bar = 0b010, 590 /// Baz = 0b100 591 /// } 592 /// } 593 /// 594 /// let mut set0 = Flag::Foo | Flag::Bar; 595 /// let mut set1 = Flag::Bar | Flag::Baz; 596 /// 597 /// set0 |= set1; 598 /// assert_eq!(set0, FlagSet::full()); 599 /// 600 /// set1 |= Flag::Baz; 601 /// assert_eq!(set1, Flag::Bar | Flag::Baz); 602 /// ``` 603 #[inline] bitor_assign(&mut self, rhs: R)604 fn bitor_assign(&mut self, rhs: R) { 605 self.0 |= rhs.into().0 606 } 607 } 608 609 impl<F: Flags, R: Into<FlagSet<F>>> BitXor<R> for FlagSet<F> { 610 type Output = Self; 611 612 /// Calculates the current set with the specified flags toggled. 613 /// 614 /// This is commonly known as toggling the presence 615 /// 616 /// ``` 617 /// use flagset::{FlagSet, flags}; 618 /// 619 /// flags! { 620 /// enum Flag: u32 { 621 /// Foo = 0b001, 622 /// Bar = 0b010, 623 /// Baz = 0b100 624 /// } 625 /// } 626 /// 627 /// let set0 = Flag::Foo | Flag::Bar; 628 /// let set1 = Flag::Baz | Flag::Bar; 629 /// assert_eq!(set0 ^ set1, Flag::Foo | Flag::Baz); 630 /// assert_eq!(set0 ^ Flag::Foo, Flag::Bar); 631 /// ``` 632 #[inline] bitxor(self, rhs: R) -> Self633 fn bitxor(self, rhs: R) -> Self { 634 FlagSet(self.0 ^ rhs.into().0) 635 } 636 } 637 638 impl<F: Flags, R: Into<FlagSet<F>>> BitXorAssign<R> for FlagSet<F> { 639 /// Assigns the current set with the specified flags toggled. 640 /// 641 /// ``` 642 /// use flagset::{FlagSet, flags}; 643 /// 644 /// flags! { 645 /// enum Flag: u16 { 646 /// Foo = 0b001, 647 /// Bar = 0b010, 648 /// Baz = 0b100 649 /// } 650 /// } 651 /// 652 /// let mut set0 = Flag::Foo | Flag::Bar; 653 /// let mut set1 = Flag::Baz | Flag::Bar; 654 /// 655 /// set0 ^= set1; 656 /// assert_eq!(set0, Flag::Foo | Flag::Baz); 657 /// 658 /// set1 ^= Flag::Baz; 659 /// assert_eq!(set1, Flag::Bar); 660 /// ``` 661 #[inline] bitxor_assign(&mut self, rhs: R)662 fn bitxor_assign(&mut self, rhs: R) { 663 self.0 ^= rhs.into().0 664 } 665 } 666 667 impl<F: Flags, R: Into<FlagSet<F>>> Sub<R> for FlagSet<F> { 668 type Output = Self; 669 670 /// Calculates set difference (the current set without the specified flags). 671 /// 672 /// ``` 673 /// use flagset::{FlagSet, flags}; 674 /// 675 /// flags! { 676 /// pub enum Flag: u8 { 677 /// Foo = 1, 678 /// Bar = 2, 679 /// Baz = 4 680 /// } 681 /// } 682 /// 683 /// let set0 = Flag::Foo | Flag::Bar; 684 /// let set1 = Flag::Baz | Flag::Bar; 685 /// assert_eq!(set0 - set1, Flag::Foo); 686 /// ``` 687 #[inline] sub(self, rhs: R) -> Self688 fn sub(self, rhs: R) -> Self { 689 self & !rhs.into() 690 } 691 } 692 693 impl<F: Flags, R: Into<FlagSet<F>>> SubAssign<R> for FlagSet<F> { 694 /// Assigns set difference (the current set without the specified flags). 695 /// 696 /// ``` 697 /// use flagset::{FlagSet, flags}; 698 /// 699 /// flags! { 700 /// pub enum Flag: u8 { 701 /// Foo = 1, 702 /// Bar = 2, 703 /// Baz = 4 704 /// } 705 /// } 706 /// 707 /// let mut set0 = Flag::Foo | Flag::Bar; 708 /// set0 -= Flag::Baz | Flag::Bar; 709 /// assert_eq!(set0, Flag::Foo); 710 /// ``` 711 #[inline] sub_assign(&mut self, rhs: R)712 fn sub_assign(&mut self, rhs: R) { 713 *self &= !rhs.into(); 714 } 715 } 716 717 impl<F: Flags, R: Into<FlagSet<F>>> Rem<R> for FlagSet<F> { 718 type Output = Self; 719 720 /// Calculates the symmetric difference between two sets. 721 /// 722 /// The symmetric difference between two sets is the set of all flags 723 /// that appear in one set or the other, but not both. 724 /// 725 /// ``` 726 /// use flagset::{FlagSet, flags}; 727 /// 728 /// flags! { 729 /// pub enum Flag: u8 { 730 /// Foo = 1, 731 /// Bar = 2, 732 /// Baz = 4 733 /// } 734 /// } 735 /// 736 /// let set0 = Flag::Foo | Flag::Bar; 737 /// let set1 = Flag::Baz | Flag::Bar; 738 /// assert_eq!(set0 % set1, Flag::Foo | Flag::Baz); 739 /// ``` 740 #[inline] rem(self, rhs: R) -> Self741 fn rem(self, rhs: R) -> Self { 742 let rhs = rhs.into(); 743 (self - rhs) | (rhs - self) 744 } 745 } 746 747 impl<F: Flags, R: Into<FlagSet<F>>> RemAssign<R> for FlagSet<F> { 748 /// Assigns the symmetric difference between two sets. 749 /// 750 /// The symmetric difference between two sets is the set of all flags 751 /// that appear in one set or the other, but not both. 752 /// 753 /// ``` 754 /// use flagset::{FlagSet, flags}; 755 /// 756 /// flags! { 757 /// pub enum Flag: u8 { 758 /// Foo = 1, 759 /// Bar = 2, 760 /// Baz = 4 761 /// } 762 /// } 763 /// 764 /// let mut set0 = Flag::Foo | Flag::Bar; 765 /// let set1 = Flag::Baz | Flag::Bar; 766 /// set0 %= set1; 767 /// assert_eq!(set0, Flag::Foo | Flag::Baz); 768 /// ``` 769 #[inline] rem_assign(&mut self, rhs: R)770 fn rem_assign(&mut self, rhs: R) { 771 *self = *self % rhs 772 } 773 } 774 775 impl<F: Flags> FlagSet<F> { 776 /// Creates a new set from bits; returning `Err(InvalidBits)` on invalid/unknown bits. 777 /// 778 /// ``` 779 /// use flagset::{FlagSet, flags}; 780 /// 781 /// flags! { 782 /// pub enum Flag: u16 { 783 /// Foo = 0b0001, 784 /// Bar = 0b0010, 785 /// Baz = 0b0100, 786 /// Qux = 0b1010, // Implies Bar 787 /// } 788 /// } 789 /// 790 /// assert_eq!(FlagSet::<Flag>::new(0b00101), Ok(Flag::Foo | Flag::Baz)); 791 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid 792 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown 793 /// ``` 794 #[inline] new(bits: F::Type) -> core::result::Result<Self, InvalidBits>795 pub fn new(bits: F::Type) -> core::result::Result<Self, InvalidBits> { 796 if Self::new_truncated(bits).0 == bits { 797 return Ok(FlagSet(bits)); 798 } 799 800 Err(InvalidBits) 801 } 802 803 /// Creates a new set from bits; truncating invalid/unknown bits. 804 /// 805 /// ``` 806 /// use flagset::{FlagSet, flags}; 807 /// 808 /// flags! { 809 /// pub enum Flag: u16 { 810 /// Foo = 0b0001, 811 /// Bar = 0b0010, 812 /// Baz = 0b0100, 813 /// Qux = 0b1010, // Implies Bar 814 /// } 815 /// } 816 /// 817 /// let set = FlagSet::new_truncated(0b11101); // Has invalid and unknown. 818 /// assert_eq!(set, Flag::Foo | Flag::Baz); 819 /// assert_eq!(set.bits(), 0b00101); // Has neither. 820 /// ``` 821 #[inline] new_truncated(bits: F::Type) -> Self822 pub fn new_truncated(bits: F::Type) -> Self { 823 let mut set = Self::default(); 824 825 for flag in FlagSet::<F>(bits) { 826 set |= flag; 827 } 828 829 set 830 } 831 832 /// Creates a new set from bits; use of invalid/unknown bits is undefined. 833 /// 834 /// ``` 835 /// use flagset::{FlagSet, flags}; 836 /// 837 /// flags! { 838 /// pub enum Flag: u16 { 839 /// Foo = 0b0001, 840 /// Bar = 0b0010, 841 /// Baz = 0b0100, 842 /// Qux = 0b1010, // Implies Bar 843 /// } 844 /// } 845 /// 846 /// // Unknown and invalid bits are retained. Behavior is undefined. 847 /// let set = unsafe { FlagSet::<Flag>::new_unchecked(0b11101) }; 848 /// assert_eq!(set.bits(), 0b11101); 849 /// ``` 850 /// 851 /// # Safety 852 /// 853 /// This constructor doesn't check that the bits are valid. If you pass 854 /// undefined flags, undefined behavior may result. 855 #[inline] new_unchecked(bits: F::Type) -> Self856 pub unsafe fn new_unchecked(bits: F::Type) -> Self { 857 FlagSet(bits) 858 } 859 860 /// Creates a new FlagSet containing all possible flags. 861 /// 862 /// ``` 863 /// use flagset::{FlagSet, flags}; 864 /// 865 /// flags! { 866 /// pub enum Flag: u8 { 867 /// Foo = 1, 868 /// Bar = 2, 869 /// Baz = 4 870 /// } 871 /// } 872 /// 873 /// let set = FlagSet::full(); 874 /// assert!(!set.is_empty()); 875 /// assert!(set.is_full()); 876 /// assert!(set.contains(Flag::Foo)); 877 /// assert!(set.contains(Flag::Bar)); 878 /// assert!(set.contains(Flag::Baz)); 879 /// ``` 880 #[inline] full() -> Self881 pub fn full() -> Self { 882 let mut set = Self::default(); 883 for f in F::LIST { 884 set |= *f 885 } 886 set 887 } 888 889 /// Returns the raw bits of the set. 890 /// 891 /// ``` 892 /// use flagset::{FlagSet, flags}; 893 /// 894 /// flags! { 895 /// pub enum Flag: u16 { 896 /// Foo = 0b0001, 897 /// Bar = 0b0010, 898 /// Baz = 0b0100, 899 /// } 900 /// } 901 /// 902 /// let set = Flag::Foo | Flag::Baz; 903 /// assert_eq!(set.bits(), 0b0101u16); 904 /// ``` 905 #[inline] bits(self) -> F::Type906 pub fn bits(self) -> F::Type { 907 self.0 908 } 909 910 /// Returns true if the FlagSet contains no flags. 911 /// 912 /// ``` 913 /// use flagset::{FlagSet, flags}; 914 /// 915 /// flags! { 916 /// pub enum Flag: u8 { 917 /// Foo = 1, 918 /// Bar = 2, 919 /// Baz = 4 920 /// } 921 /// } 922 /// 923 /// let mut set = Flag::Foo | Flag::Bar; 924 /// assert!(!set.is_empty()); 925 /// 926 /// set &= Flag::Baz; 927 /// assert!(set.is_empty()); 928 /// ``` 929 #[inline] is_empty(self) -> bool930 pub fn is_empty(self) -> bool { 931 self == Self::default() 932 } 933 934 /// Returns true if the FlagSet contains all possible flags. 935 /// 936 /// ``` 937 /// use flagset::{FlagSet, flags}; 938 /// 939 /// flags! { 940 /// pub enum Flag: u8 { 941 /// Foo = 1, 942 /// Bar = 2, 943 /// Baz = 4 944 /// } 945 /// } 946 /// 947 /// let mut set = Flag::Foo | Flag::Bar; 948 /// assert!(!set.is_full()); 949 /// 950 /// set |= Flag::Baz; 951 /// assert!(set.is_full()); 952 /// ``` 953 #[inline] is_full(self) -> bool954 pub fn is_full(self) -> bool { 955 self == Self::full() 956 } 957 958 /// Returns true if the two `FlagSet`s do not share any flags. 959 /// 960 /// ``` 961 /// use flagset::{FlagSet, flags}; 962 /// 963 /// flags! { 964 /// pub enum Flag: u8 { 965 /// Foo = 1, 966 /// Bar = 2, 967 /// Baz = 4 968 /// } 969 /// } 970 /// 971 /// let set = Flag::Foo | Flag::Bar; 972 /// assert!(!set.is_disjoint(Flag::Foo)); 973 /// assert!(!set.is_disjoint(Flag::Foo | Flag::Baz)); 974 /// assert!(set.is_disjoint(Flag::Baz)); 975 /// ``` 976 #[inline] is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool977 pub fn is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool { 978 self & rhs == Self::default() 979 } 980 981 /// Returns true if this FlagSet is a superset of the specified flags. 982 /// 983 /// ``` 984 /// use flagset::{FlagSet, flags}; 985 /// 986 /// flags! { 987 /// pub enum Flag: u8 { 988 /// Foo = 1, 989 /// Bar = 2, 990 /// Baz = 4 991 /// } 992 /// } 993 /// 994 /// let set = Flag::Foo | Flag::Bar; 995 /// assert!(set.contains(Flag::Foo)); 996 /// assert!(set.contains(Flag::Foo | Flag::Bar)); 997 /// assert!(!set.contains(Flag::Foo | Flag::Bar | Flag::Baz)); 998 /// ``` 999 #[inline] contains(self, rhs: impl Into<FlagSet<F>>) -> bool1000 pub fn contains(self, rhs: impl Into<FlagSet<F>>) -> bool { 1001 let rhs = rhs.into(); 1002 self & rhs == rhs 1003 } 1004 1005 /// Removes all flags from the FlagSet. 1006 /// 1007 /// ``` 1008 /// use flagset::{FlagSet, flags}; 1009 /// 1010 /// flags! { 1011 /// pub enum Flag: u8 { 1012 /// Foo = 1, 1013 /// Bar = 2, 1014 /// Baz = 4 1015 /// } 1016 /// } 1017 /// 1018 /// let mut set = Flag::Foo | Flag::Bar; 1019 /// assert!(!set.is_empty()); 1020 /// 1021 /// set.clear(); 1022 /// assert!(set.is_empty()); 1023 /// ``` 1024 #[inline] clear(&mut self)1025 pub fn clear(&mut self) { 1026 *self = Self::default(); 1027 } 1028 1029 /// Clears the current set and returns an iterator of all removed flags. 1030 /// 1031 /// ``` 1032 /// use flagset::{FlagSet, flags}; 1033 /// 1034 /// flags! { 1035 /// pub enum Flag: u8 { 1036 /// Foo = 1, 1037 /// Bar = 2, 1038 /// Baz = 4 1039 /// } 1040 /// } 1041 /// 1042 /// let mut set = Flag::Foo | Flag::Bar; 1043 /// let mut iter = set.drain(); 1044 /// assert!(set.is_empty()); 1045 /// assert_eq!(iter.next(), Some(Flag::Foo)); 1046 /// assert_eq!(iter.next(), Some(Flag::Bar)); 1047 /// assert_eq!(iter.next(), None); 1048 /// ``` 1049 #[inline] drain(&mut self) -> Iter<F>1050 pub fn drain(&mut self) -> Iter<F> { 1051 let iter = self.into_iter(); 1052 *self = Self::default(); 1053 iter 1054 } 1055 1056 /// Retain only the flags flags specified by the predicate. 1057 /// 1058 /// ``` 1059 /// use flagset::{FlagSet, flags}; 1060 /// 1061 /// flags! { 1062 /// pub enum Flag: u8 { 1063 /// Foo = 1, 1064 /// Bar = 2, 1065 /// Baz = 4 1066 /// } 1067 /// } 1068 /// 1069 /// let mut set0 = Flag::Foo | Flag::Bar; 1070 /// set0.retain(|f| f != Flag::Foo); 1071 /// assert_eq!(set0, Flag::Bar); 1072 /// ``` 1073 #[inline] retain(&mut self, func: impl Fn(F) -> bool)1074 pub fn retain(&mut self, func: impl Fn(F) -> bool) { 1075 for f in self.into_iter() { 1076 if !func(f) { 1077 *self -= f 1078 } 1079 } 1080 } 1081 } 1082 1083 #[cfg(feature = "serde")] 1084 impl<F: Flags> serde::Serialize for FlagSet<F> 1085 where 1086 F::Type: serde::ser::Serialize, 1087 { 1088 #[inline] serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> where S: serde::ser::Serializer,1089 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> 1090 where 1091 S: serde::ser::Serializer, 1092 { 1093 self.0.serialize(serializer) 1094 } 1095 } 1096 1097 #[cfg(feature = "serde")] 1098 impl<'de, F: Flags> serde::Deserialize<'de> for FlagSet<F> 1099 where 1100 F::Type: serde::de::Deserialize<'de>, 1101 { 1102 #[inline] deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> where D: serde::de::Deserializer<'de>,1103 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> 1104 where 1105 D: serde::de::Deserializer<'de>, 1106 { 1107 Ok(FlagSet(F::Type::deserialize(deserializer)?)) 1108 } 1109 } 1110 1111 /// Define flag value using the `enum` syntax. See below for details. 1112 /// 1113 /// Each enumeration value **MUST** have a specified value. 1114 /// 1115 /// The width of the bitfield **MUST** also be specified by its integer type. 1116 /// 1117 /// It is important to note that the size of the flag enumeration itself is 1118 /// unrelated to the size of the corresponding `FlagSet` instance. 1119 /// 1120 /// It is also worth noting that this macro automatically implements a variety 1121 /// of standard traits including: 1122 /// * Copy 1123 /// * Clone 1124 /// * Debug 1125 /// * PartialEq 1126 /// * Eq 1127 /// * From<$enum> for $integer 1128 /// * Not 1129 /// * BitAnd 1130 /// * BitOr 1131 /// * BitXor 1132 /// * Sub 1133 /// * Rem 1134 /// 1135 /// ``` 1136 /// use std::mem::{align_of, size_of}; 1137 /// use flagset::{FlagSet, flags}; 1138 /// 1139 /// flags! { 1140 /// enum FlagEmpty: u32 {} 1141 /// 1142 /// enum Flag8: u8 { 1143 /// Foo = 0b001, 1144 /// Bar = 0b010, 1145 /// Baz = 0b100 1146 /// } 1147 /// 1148 /// pub enum Flag16: u16 { 1149 /// Foo, 1150 /// Bar, 1151 /// #[deprecated] 1152 /// Baz, 1153 /// } 1154 /// 1155 /// #[derive(PartialOrd, Ord)] 1156 /// enum Flag32: u32 { 1157 /// Foo = 0b001, 1158 /// #[deprecated] 1159 /// Bar = 0b010, 1160 /// Baz = 0b100 1161 /// } 1162 /// 1163 /// #[repr(u64)] 1164 /// enum Flag64: u64 { 1165 /// Foo = 0b001, 1166 /// Bar = 0b010, 1167 /// Baz = 0b100 1168 /// } 1169 /// 1170 /// #[repr(u32)] 1171 /// enum Flag128: u128 { 1172 /// Foo = 0b001, 1173 /// Bar = 0b010, 1174 /// Baz = 0b100 1175 /// } 1176 /// } 1177 /// 1178 /// assert_eq!(size_of::<Flag8>(), 1); 1179 /// assert_eq!(size_of::<Flag16>(), 1); 1180 /// assert_eq!(size_of::<Flag32>(), 1); 1181 /// assert_eq!(size_of::<Flag64>(), 8); 1182 /// assert_eq!(size_of::<Flag128>(), 4); 1183 /// 1184 /// assert_eq!(align_of::<Flag8>(), 1); 1185 /// assert_eq!(align_of::<Flag16>(), 1); 1186 /// assert_eq!(align_of::<Flag32>(), 1); 1187 /// assert_eq!(align_of::<Flag64>(), align_of::<u64>()); 1188 /// assert_eq!(align_of::<Flag128>(), align_of::<u32>()); 1189 /// 1190 /// assert_eq!(size_of::<FlagSet<Flag8>>(), size_of::<u8>()); 1191 /// assert_eq!(size_of::<FlagSet<Flag16>>(), size_of::<u16>()); 1192 /// assert_eq!(size_of::<FlagSet<Flag32>>(), size_of::<u32>()); 1193 /// assert_eq!(size_of::<FlagSet<Flag64>>(), size_of::<u64>()); 1194 /// assert_eq!(size_of::<FlagSet<Flag128>>(), size_of::<u128>()); 1195 /// 1196 /// assert_eq!(align_of::<FlagSet<Flag8>>(), align_of::<u8>()); 1197 /// assert_eq!(align_of::<FlagSet<Flag16>>(), align_of::<u16>()); 1198 /// assert_eq!(align_of::<FlagSet<Flag32>>(), align_of::<u32>()); 1199 /// assert_eq!(align_of::<FlagSet<Flag64>>(), align_of::<u64>()); 1200 /// assert_eq!(align_of::<FlagSet<Flag128>>(), align_of::<u128>()); 1201 /// ``` 1202 #[macro_export] 1203 macro_rules! flags { 1204 () => {}; 1205 1206 // Entry point for enumerations without values. 1207 ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])* $k:ident),+ $(,)* } $($next:tt)*) => { 1208 $crate::flags! { $(#[$m])* $p enum $n: $t { $($(#[$a])* $k = (1 << $n::$k as $t)),+ } $($next)* } 1209 }; 1210 1211 // Entrypoint for enumerations with values. 1212 ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])*$k:ident = $v:expr),* $(,)* } $($next:tt)*) => { 1213 $(#[$m])* 1214 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 1215 $p enum $n { $($(#[$a])* $k),* } 1216 1217 impl $crate::Flags for $n { 1218 type Type = $t; 1219 1220 const LIST: &'static [Self] = &[$($n::$k),*]; 1221 } 1222 1223 impl core::convert::From<$n> for $crate::FlagSet<$n> { 1224 #[inline] 1225 fn from(value: $n) -> Self { 1226 unsafe { 1227 match value { 1228 $($n::$k => Self::new_unchecked($v)),* 1229 } 1230 } 1231 } 1232 } 1233 1234 impl core::ops::Not for $n { 1235 type Output = $crate::FlagSet<$n>; 1236 1237 #[inline] 1238 fn not(self) -> Self::Output { 1239 !$crate::FlagSet::from(self) 1240 } 1241 } 1242 1243 impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitAnd<R> for $n { 1244 type Output = $crate::FlagSet<$n>; 1245 1246 #[inline] 1247 fn bitand(self, rhs: R) -> Self::Output { 1248 $crate::FlagSet::from(self) & rhs 1249 } 1250 } 1251 1252 impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitOr<R> for $n { 1253 type Output = $crate::FlagSet<$n>; 1254 1255 #[inline] 1256 fn bitor(self, rhs: R) -> Self::Output { 1257 $crate::FlagSet::from(self) | rhs 1258 } 1259 } 1260 1261 impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::BitXor<R> for $n { 1262 type Output = $crate::FlagSet<$n>; 1263 1264 #[inline] 1265 fn bitxor(self, rhs: R) -> Self::Output { 1266 $crate::FlagSet::from(self) ^ rhs 1267 } 1268 } 1269 1270 impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::Sub<R> for $n { 1271 type Output = $crate::FlagSet<$n>; 1272 1273 #[inline] 1274 fn sub(self, rhs: R) -> Self::Output { 1275 $crate::FlagSet::from(self) - rhs 1276 } 1277 } 1278 1279 impl<R: core::convert::Into<$crate::FlagSet<$n>>> core::ops::Rem<R> for $n { 1280 type Output = $crate::FlagSet<$n>; 1281 1282 #[inline] 1283 fn rem(self, rhs: R) -> Self::Output { 1284 $crate::FlagSet::from(self) % rhs 1285 } 1286 } 1287 1288 $crate::flags! { $($next)* } 1289 }; 1290 } 1291