1 // 2 // Copyright 2019 Red Hat, Inc. 3 // 4 // Author: Nathaniel McCallum <[email protected]> 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 #![cfg_attr(not(feature = "std"), no_std)] 249 #![cfg_attr(docsrs, feature(doc_auto_cfg))] 250 251 /// Local Android change: Use std to allow building as a dylib. 252 #[cfg(android_dylib)] 253 extern crate std; 254 255 use core::fmt::{Debug, Formatter, Result}; 256 use core::ops::*; 257 258 /// Error type returned when creating a new flagset from bits is invalid or undefined. 259 /// ``` 260 /// use flagset::{FlagSet, flags}; 261 /// 262 /// flags! { 263 /// pub enum Flag: u16 { 264 /// Foo = 0b0001, 265 /// Bar = 0b0010, 266 /// Baz = 0b0100, 267 /// Qux = 0b1010, // Implies Bar 268 /// } 269 /// } 270 /// 271 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid 272 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown 273 /// ``` 274 #[derive(Clone, Copy, Debug, Eq, PartialEq)] 275 pub struct InvalidBits; 276 277 impl core::fmt::Display for InvalidBits { 278 #[inline] fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result279 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 280 write!(f, "invalid bits") 281 } 282 } 283 284 #[cfg(feature = "std")] 285 impl std::error::Error for InvalidBits {} 286 287 #[doc(hidden)] 288 pub trait Flags: 289 Copy 290 + Clone 291 + Debug 292 + PartialEq 293 + Eq 294 + BitAnd<Self, Output = FlagSet<Self>> 295 + BitOr<Self, Output = FlagSet<Self>> 296 + BitXor<Self, Output = FlagSet<Self>> 297 + Sub<Self, Output = FlagSet<Self>> 298 + Rem<Self, Output = FlagSet<Self>> 299 + Not<Output = FlagSet<Self>> 300 + Into<FlagSet<Self>> 301 + 'static 302 { 303 type Type: Copy 304 + Clone 305 + Debug 306 + PartialEq 307 + Eq 308 + Default 309 + BitAnd<Self::Type, Output = Self::Type> 310 + BitAndAssign<Self::Type> 311 + BitOr<Self::Type, Output = Self::Type> 312 + BitOrAssign<Self::Type> 313 + BitXor<Self::Type, Output = Self::Type> 314 + BitXorAssign<Self::Type> 315 + Not<Output = Self::Type>; 316 317 /// A slice containing all the possible flag values. 318 const LIST: &'static [Self]; 319 320 /// Creates an empty `FlagSet` of this type 321 #[inline] none() -> FlagSet<Self>322 fn none() -> FlagSet<Self> { 323 FlagSet::default() 324 } 325 } 326 327 #[repr(C)] 328 #[derive(Copy, Clone, Eq, Hash)] 329 pub struct FlagSet<F: Flags>(F::Type); 330 331 #[doc(hidden)] 332 #[derive(Copy, Clone)] 333 pub struct Iter<F: Flags>(FlagSet<F>, usize); 334 335 impl<F: Flags> Iterator for Iter<F> { 336 type Item = F; 337 338 #[inline] next(&mut self) -> Option<Self::Item>339 fn next(&mut self) -> Option<Self::Item> { 340 while self.1 < F::LIST.len() { 341 let next = F::LIST[self.1]; 342 self.1 += 1; 343 344 if self.0.contains(next) { 345 return Some(next); 346 } 347 } 348 349 None 350 } 351 } 352 353 impl<F: Flags> IntoIterator for FlagSet<F> { 354 type Item = F; 355 type IntoIter = Iter<F>; 356 357 /// Iterate over the flags in the set. 358 /// 359 /// **NOTE**: The order in which the flags are iterated is undefined. 360 /// 361 /// ``` 362 /// use flagset::{FlagSet, flags}; 363 /// 364 /// flags! { 365 /// enum Flag: u8 { 366 /// Foo = 0b001, 367 /// Bar = 0b010, 368 /// Baz = 0b100 369 /// } 370 /// } 371 /// 372 /// let set = Flag::Foo | Flag::Bar; 373 /// let mut iter = set.into_iter(); 374 /// assert_eq!(iter.next(), Some(Flag::Foo)); 375 /// assert_eq!(iter.next(), Some(Flag::Bar)); 376 /// assert_eq!(iter.next(), None); 377 /// ``` 378 #[inline] into_iter(self) -> Self::IntoIter379 fn into_iter(self) -> Self::IntoIter { 380 Iter(self, 0) 381 } 382 } 383 384 impl<F: Flags> Debug for FlagSet<F> { 385 #[inline] fmt(&self, f: &mut Formatter) -> Result386 fn fmt(&self, f: &mut Formatter) -> Result { 387 write!(f, "FlagSet(")?; 388 for (i, flag) in self.into_iter().enumerate() { 389 write!(f, "{}{:?}", if i > 0 { " | " } else { "" }, flag)?; 390 } 391 write!(f, ")") 392 } 393 } 394 395 impl<F: Flags, R: Copy + Into<FlagSet<F>>> PartialEq<R> for FlagSet<F> { 396 #[inline] eq(&self, rhs: &R) -> bool397 fn eq(&self, rhs: &R) -> bool { 398 self.0 == (*rhs).into().0 399 } 400 } 401 402 impl<F: Flags> AsRef<F::Type> for FlagSet<F> { 403 #[inline] as_ref(&self) -> &F::Type404 fn as_ref(&self) -> &F::Type { 405 &self.0 406 } 407 } 408 409 impl<F: Flags> From<Option<FlagSet<F>>> for FlagSet<F> { 410 /// Converts from `Option<FlagSet<F>>` to `FlagSet<F>`. 411 /// 412 /// Most notably, this allows for the use of `None` in many places to 413 /// substitute for manually creating an empty `FlagSet<F>`. See below. 414 /// 415 /// ``` 416 /// use flagset::{FlagSet, flags}; 417 /// 418 /// flags! { 419 /// enum Flag: u8 { 420 /// Foo = 0b001, 421 /// Bar = 0b010, 422 /// Baz = 0b100 423 /// } 424 /// } 425 /// 426 /// fn convert(v: impl Into<FlagSet<Flag>>) -> u8 { 427 /// v.into().bits() 428 /// } 429 /// 430 /// assert_eq!(convert(Flag::Foo | Flag::Bar), 0b011); 431 /// assert_eq!(convert(Flag::Foo), 0b001); 432 /// assert_eq!(convert(None), 0b000); 433 /// ``` 434 #[inline] from(value: Option<FlagSet<F>>) -> FlagSet<F>435 fn from(value: Option<FlagSet<F>>) -> FlagSet<F> { 436 value.unwrap_or_default() 437 } 438 } 439 440 impl<F: Flags> Default for FlagSet<F> { 441 /// Creates a new, empty FlagSet. 442 /// 443 /// ``` 444 /// use flagset::{FlagSet, flags}; 445 /// 446 /// flags! { 447 /// enum Flag: u8 { 448 /// Foo = 0b001, 449 /// Bar = 0b010, 450 /// Baz = 0b100 451 /// } 452 /// } 453 /// 454 /// let set = FlagSet::<Flag>::default(); 455 /// assert!(set.is_empty()); 456 /// assert!(!set.is_full()); 457 /// assert!(!set.contains(Flag::Foo)); 458 /// assert!(!set.contains(Flag::Bar)); 459 /// assert!(!set.contains(Flag::Baz)); 460 /// ``` 461 #[inline] default() -> Self462 fn default() -> Self { 463 FlagSet(F::Type::default()) 464 } 465 } 466 467 impl<F: Flags> Not for FlagSet<F> { 468 type Output = Self; 469 470 /// Calculates the complement of the current set. 471 /// 472 /// In common parlance, this returns the set of all possible flags that are 473 /// not in the current set. 474 /// 475 /// ``` 476 /// use flagset::{FlagSet, flags}; 477 /// 478 /// flags! { 479 /// #[derive(PartialOrd, Ord)] 480 /// enum Flag: u8 { 481 /// Foo = 1 << 0, 482 /// Bar = 1 << 1, 483 /// Baz = 1 << 2 484 /// } 485 /// } 486 /// 487 /// let set = !FlagSet::from(Flag::Foo); 488 /// assert!(!set.is_empty()); 489 /// assert!(!set.is_full()); 490 /// assert!(!set.contains(Flag::Foo)); 491 /// assert!(set.contains(Flag::Bar)); 492 /// assert!(set.contains(Flag::Baz)); 493 /// ``` 494 #[inline] not(self) -> Self495 fn not(self) -> Self { 496 FlagSet(!self.0) 497 } 498 } 499 500 impl<F: Flags, R: Into<FlagSet<F>>> BitAnd<R> for FlagSet<F> { 501 type Output = Self; 502 503 /// Calculates the intersection of the current set and the specified flags. 504 /// 505 /// ``` 506 /// use flagset::{FlagSet, flags}; 507 /// 508 /// flags! { 509 /// #[derive(PartialOrd, Ord)] 510 /// pub enum Flag: u8 { 511 /// Foo = 0b001, 512 /// Bar = 0b010, 513 /// Baz = 0b100 514 /// } 515 /// } 516 /// 517 /// let set0 = Flag::Foo | Flag::Bar; 518 /// let set1 = Flag::Baz | Flag::Bar; 519 /// assert_eq!(set0 & set1, Flag::Bar); 520 /// assert_eq!(set0 & Flag::Foo, Flag::Foo); 521 /// assert_eq!(set1 & Flag::Baz, Flag::Baz); 522 /// ``` 523 #[inline] bitand(self, rhs: R) -> Self524 fn bitand(self, rhs: R) -> Self { 525 FlagSet(self.0 & rhs.into().0) 526 } 527 } 528 529 impl<F: Flags, R: Into<FlagSet<F>>> BitAndAssign<R> for FlagSet<F> { 530 /// Assigns the intersection of the current set and the specified flags. 531 /// 532 /// ``` 533 /// use flagset::{FlagSet, flags}; 534 /// 535 /// flags! { 536 /// enum Flag: u64 { 537 /// Foo = 0b001, 538 /// Bar = 0b010, 539 /// Baz = 0b100 540 /// } 541 /// } 542 /// 543 /// let mut set0 = Flag::Foo | Flag::Bar; 544 /// let mut set1 = Flag::Baz | Flag::Bar; 545 /// 546 /// set0 &= set1; 547 /// assert_eq!(set0, Flag::Bar); 548 /// 549 /// set1 &= Flag::Baz; 550 /// assert_eq!(set0, Flag::Bar); 551 /// ``` 552 #[inline] bitand_assign(&mut self, rhs: R)553 fn bitand_assign(&mut self, rhs: R) { 554 self.0 &= rhs.into().0 555 } 556 } 557 558 impl<F: Flags, R: Into<FlagSet<F>>> BitOr<R> for FlagSet<F> { 559 type Output = Self; 560 561 /// Calculates the union of the current set with the specified flags. 562 /// 563 /// ``` 564 /// use flagset::{FlagSet, flags}; 565 /// 566 /// flags! { 567 /// #[derive(PartialOrd, Ord)] 568 /// pub enum Flag: u8 { 569 /// Foo = 0b001, 570 /// Bar = 0b010, 571 /// Baz = 0b100 572 /// } 573 /// } 574 /// 575 /// let set0 = Flag::Foo | Flag::Bar; 576 /// let set1 = Flag::Baz | Flag::Bar; 577 /// assert_eq!(set0 | set1, FlagSet::full()); 578 /// ``` 579 #[inline] bitor(self, rhs: R) -> Self580 fn bitor(self, rhs: R) -> Self { 581 FlagSet(self.0 | rhs.into().0) 582 } 583 } 584 585 impl<F: Flags, R: Into<FlagSet<F>>> BitOrAssign<R> for FlagSet<F> { 586 /// Assigns the union of the current set with the specified flags. 587 /// 588 /// ``` 589 /// use flagset::{FlagSet, flags}; 590 /// 591 /// flags! { 592 /// enum Flag: u64 { 593 /// Foo = 0b001, 594 /// Bar = 0b010, 595 /// Baz = 0b100 596 /// } 597 /// } 598 /// 599 /// let mut set0 = Flag::Foo | Flag::Bar; 600 /// let mut set1 = Flag::Bar | Flag::Baz; 601 /// 602 /// set0 |= set1; 603 /// assert_eq!(set0, FlagSet::full()); 604 /// 605 /// set1 |= Flag::Baz; 606 /// assert_eq!(set1, Flag::Bar | Flag::Baz); 607 /// ``` 608 #[inline] bitor_assign(&mut self, rhs: R)609 fn bitor_assign(&mut self, rhs: R) { 610 self.0 |= rhs.into().0 611 } 612 } 613 614 impl<F: Flags, R: Into<FlagSet<F>>> BitXor<R> for FlagSet<F> { 615 type Output = Self; 616 617 /// Calculates the current set with the specified flags toggled. 618 /// 619 /// This is commonly known as toggling the presence 620 /// 621 /// ``` 622 /// use flagset::{FlagSet, flags}; 623 /// 624 /// flags! { 625 /// enum Flag: u32 { 626 /// Foo = 0b001, 627 /// Bar = 0b010, 628 /// Baz = 0b100 629 /// } 630 /// } 631 /// 632 /// let set0 = Flag::Foo | Flag::Bar; 633 /// let set1 = Flag::Baz | Flag::Bar; 634 /// assert_eq!(set0 ^ set1, Flag::Foo | Flag::Baz); 635 /// assert_eq!(set0 ^ Flag::Foo, Flag::Bar); 636 /// ``` 637 #[inline] bitxor(self, rhs: R) -> Self638 fn bitxor(self, rhs: R) -> Self { 639 FlagSet(self.0 ^ rhs.into().0) 640 } 641 } 642 643 impl<F: Flags, R: Into<FlagSet<F>>> BitXorAssign<R> for FlagSet<F> { 644 /// Assigns the current set with the specified flags toggled. 645 /// 646 /// ``` 647 /// use flagset::{FlagSet, flags}; 648 /// 649 /// flags! { 650 /// enum Flag: u16 { 651 /// Foo = 0b001, 652 /// Bar = 0b010, 653 /// Baz = 0b100 654 /// } 655 /// } 656 /// 657 /// let mut set0 = Flag::Foo | Flag::Bar; 658 /// let mut set1 = Flag::Baz | Flag::Bar; 659 /// 660 /// set0 ^= set1; 661 /// assert_eq!(set0, Flag::Foo | Flag::Baz); 662 /// 663 /// set1 ^= Flag::Baz; 664 /// assert_eq!(set1, Flag::Bar); 665 /// ``` 666 #[inline] bitxor_assign(&mut self, rhs: R)667 fn bitxor_assign(&mut self, rhs: R) { 668 self.0 ^= rhs.into().0 669 } 670 } 671 672 impl<F: Flags, R: Into<FlagSet<F>>> Sub<R> for FlagSet<F> { 673 type Output = Self; 674 675 /// Calculates set difference (the current set without the specified flags). 676 /// 677 /// ``` 678 /// use flagset::{FlagSet, flags}; 679 /// 680 /// flags! { 681 /// pub enum Flag: u8 { 682 /// Foo = 1, 683 /// Bar = 2, 684 /// Baz = 4 685 /// } 686 /// } 687 /// 688 /// let set0 = Flag::Foo | Flag::Bar; 689 /// let set1 = Flag::Baz | Flag::Bar; 690 /// assert_eq!(set0 - set1, Flag::Foo); 691 /// ``` 692 #[inline] sub(self, rhs: R) -> Self693 fn sub(self, rhs: R) -> Self { 694 self & !rhs.into() 695 } 696 } 697 698 impl<F: Flags, R: Into<FlagSet<F>>> SubAssign<R> for FlagSet<F> { 699 /// Assigns set difference (the current set without the specified flags). 700 /// 701 /// ``` 702 /// use flagset::{FlagSet, flags}; 703 /// 704 /// flags! { 705 /// pub enum Flag: u8 { 706 /// Foo = 1, 707 /// Bar = 2, 708 /// Baz = 4 709 /// } 710 /// } 711 /// 712 /// let mut set0 = Flag::Foo | Flag::Bar; 713 /// set0 -= Flag::Baz | Flag::Bar; 714 /// assert_eq!(set0, Flag::Foo); 715 /// ``` 716 #[inline] sub_assign(&mut self, rhs: R)717 fn sub_assign(&mut self, rhs: R) { 718 *self &= !rhs.into(); 719 } 720 } 721 722 impl<F: Flags, R: Into<FlagSet<F>>> Rem<R> for FlagSet<F> { 723 type Output = Self; 724 725 /// Calculates the symmetric difference between two sets. 726 /// 727 /// The symmetric difference between two sets is the set of all flags 728 /// that appear in one set or the other, but not both. 729 /// 730 /// ``` 731 /// use flagset::{FlagSet, flags}; 732 /// 733 /// flags! { 734 /// pub enum Flag: u8 { 735 /// Foo = 1, 736 /// Bar = 2, 737 /// Baz = 4 738 /// } 739 /// } 740 /// 741 /// let set0 = Flag::Foo | Flag::Bar; 742 /// let set1 = Flag::Baz | Flag::Bar; 743 /// assert_eq!(set0 % set1, Flag::Foo | Flag::Baz); 744 /// ``` 745 #[inline] rem(self, rhs: R) -> Self746 fn rem(self, rhs: R) -> Self { 747 let rhs = rhs.into(); 748 (self - rhs) | (rhs - self) 749 } 750 } 751 752 impl<F: Flags, R: Into<FlagSet<F>>> RemAssign<R> for FlagSet<F> { 753 /// Assigns the symmetric difference between two sets. 754 /// 755 /// The symmetric difference between two sets is the set of all flags 756 /// that appear in one set or the other, but not both. 757 /// 758 /// ``` 759 /// use flagset::{FlagSet, flags}; 760 /// 761 /// flags! { 762 /// pub enum Flag: u8 { 763 /// Foo = 1, 764 /// Bar = 2, 765 /// Baz = 4 766 /// } 767 /// } 768 /// 769 /// let mut set0 = Flag::Foo | Flag::Bar; 770 /// let set1 = Flag::Baz | Flag::Bar; 771 /// set0 %= set1; 772 /// assert_eq!(set0, Flag::Foo | Flag::Baz); 773 /// ``` 774 #[inline] rem_assign(&mut self, rhs: R)775 fn rem_assign(&mut self, rhs: R) { 776 *self = *self % rhs 777 } 778 } 779 780 impl<F: Flags, R: Into<FlagSet<F>>> Extend<R> for FlagSet<F> { 781 /// Add values by iterating over some collection. 782 /// 783 /// ``` 784 /// use flagset::{FlagSet, flags}; 785 /// 786 /// flags! { 787 /// pub enum Flag: u8 { 788 /// Foo = 1, 789 /// Bar = 2, 790 /// Baz = 4 791 /// } 792 /// } 793 /// 794 /// let flag_vec = vec![Flag::Bar, Flag::Baz]; 795 /// let mut some_extended_flags = FlagSet::from(Flag::Foo); 796 /// some_extended_flags.extend(flag_vec); 797 /// assert_eq!(some_extended_flags, Flag::Foo | Flag::Bar | Flag::Baz); 798 /// ``` extend<T>(&mut self, iter: T) where T: IntoIterator<Item = R>,799 fn extend<T>(&mut self, iter: T) 800 where 801 T: IntoIterator<Item = R>, 802 { 803 for item in iter { 804 *self |= item; 805 } 806 } 807 } 808 809 impl<F: Flags> FlagSet<F> { 810 /// Creates a new set from bits; returning `Err(InvalidBits)` on invalid/unknown bits. 811 /// 812 /// ``` 813 /// use flagset::{FlagSet, flags}; 814 /// 815 /// flags! { 816 /// pub enum Flag: u16 { 817 /// Foo = 0b0001, 818 /// Bar = 0b0010, 819 /// Baz = 0b0100, 820 /// Qux = 0b1010, // Implies Bar 821 /// } 822 /// } 823 /// 824 /// assert_eq!(FlagSet::<Flag>::new(0b00101), Ok(Flag::Foo | Flag::Baz)); 825 /// assert_eq!(FlagSet::<Flag>::new(0b01101), Err(flagset::InvalidBits)); // Invalid 826 /// assert_eq!(FlagSet::<Flag>::new(0b10101), Err(flagset::InvalidBits)); // Unknown 827 /// ``` 828 #[inline] new(bits: F::Type) -> core::result::Result<Self, InvalidBits>829 pub fn new(bits: F::Type) -> core::result::Result<Self, InvalidBits> { 830 if Self::new_truncated(bits).0 == bits { 831 return Ok(FlagSet(bits)); 832 } 833 834 Err(InvalidBits) 835 } 836 837 /// Creates a new set from bits; truncating invalid/unknown bits. 838 /// 839 /// ``` 840 /// use flagset::{FlagSet, flags}; 841 /// 842 /// flags! { 843 /// pub enum Flag: u16 { 844 /// Foo = 0b0001, 845 /// Bar = 0b0010, 846 /// Baz = 0b0100, 847 /// Qux = 0b1010, // Implies Bar 848 /// } 849 /// } 850 /// 851 /// let set = FlagSet::new_truncated(0b11101); // Has invalid and unknown. 852 /// assert_eq!(set, Flag::Foo | Flag::Baz); 853 /// assert_eq!(set.bits(), 0b00101); // Has neither. 854 /// ``` 855 #[inline] new_truncated(bits: F::Type) -> Self856 pub fn new_truncated(bits: F::Type) -> Self { 857 let mut set = Self::default(); 858 859 for flag in FlagSet::<F>(bits) { 860 set |= flag; 861 } 862 863 set 864 } 865 866 /// Creates a new set from bits; use of invalid/unknown bits is undefined. 867 /// 868 /// ``` 869 /// use flagset::{FlagSet, flags}; 870 /// 871 /// flags! { 872 /// pub enum Flag: u16 { 873 /// Foo = 0b0001, 874 /// Bar = 0b0010, 875 /// Baz = 0b0100, 876 /// Qux = 0b1010, // Implies Bar 877 /// } 878 /// } 879 /// 880 /// // Unknown and invalid bits are retained. Behavior is undefined. 881 /// const set: FlagSet<Flag> = unsafe { FlagSet::<Flag>::new_unchecked(0b11101) }; 882 /// assert_eq!(set.bits(), 0b11101); 883 /// ``` 884 /// 885 /// # Safety 886 /// 887 /// This constructor doesn't check that the bits are valid. If you pass 888 /// undefined flags, undefined behavior may result. 889 #[inline] new_unchecked(bits: F::Type) -> Self890 pub const unsafe fn new_unchecked(bits: F::Type) -> Self { 891 FlagSet(bits) 892 } 893 894 /// Creates a new FlagSet containing all possible flags. 895 /// 896 /// ``` 897 /// use flagset::{FlagSet, flags}; 898 /// 899 /// flags! { 900 /// pub enum Flag: u8 { 901 /// Foo = 1, 902 /// Bar = 2, 903 /// Baz = 4 904 /// } 905 /// } 906 /// 907 /// let set = FlagSet::full(); 908 /// assert!(!set.is_empty()); 909 /// assert!(set.is_full()); 910 /// assert!(set.contains(Flag::Foo)); 911 /// assert!(set.contains(Flag::Bar)); 912 /// assert!(set.contains(Flag::Baz)); 913 /// ``` 914 #[inline] full() -> Self915 pub fn full() -> Self { 916 let mut set = Self::default(); 917 for f in F::LIST { 918 set |= *f 919 } 920 set 921 } 922 923 /// Returns the raw bits of the set. 924 /// 925 /// ``` 926 /// use flagset::{FlagSet, flags}; 927 /// 928 /// flags! { 929 /// pub enum Flag: u16 { 930 /// Foo = 0b0001, 931 /// Bar = 0b0010, 932 /// Baz = 0b0100, 933 /// } 934 /// } 935 /// 936 /// let set = Flag::Foo | Flag::Baz; 937 /// assert_eq!(set.bits(), 0b0101u16); 938 /// ``` 939 #[inline] bits(self) -> F::Type940 pub fn bits(self) -> F::Type { 941 self.0 942 } 943 944 /// Returns true if the FlagSet contains no flags. 945 /// 946 /// ``` 947 /// use flagset::{FlagSet, flags}; 948 /// 949 /// flags! { 950 /// pub enum Flag: u8 { 951 /// Foo = 1, 952 /// Bar = 2, 953 /// Baz = 4 954 /// } 955 /// } 956 /// 957 /// let mut set = Flag::Foo | Flag::Bar; 958 /// assert!(!set.is_empty()); 959 /// 960 /// set &= Flag::Baz; 961 /// assert!(set.is_empty()); 962 /// ``` 963 #[inline] is_empty(self) -> bool964 pub fn is_empty(self) -> bool { 965 self == Self::default() 966 } 967 968 /// Returns true if the FlagSet contains all possible flags. 969 /// 970 /// ``` 971 /// use flagset::{FlagSet, flags}; 972 /// 973 /// flags! { 974 /// pub enum Flag: u8 { 975 /// Foo = 1, 976 /// Bar = 2, 977 /// Baz = 4 978 /// } 979 /// } 980 /// 981 /// let mut set = Flag::Foo | Flag::Bar; 982 /// assert!(!set.is_full()); 983 /// 984 /// set |= Flag::Baz; 985 /// assert!(set.is_full()); 986 /// ``` 987 #[inline] is_full(self) -> bool988 pub fn is_full(self) -> bool { 989 self == Self::full() 990 } 991 992 /// Returns true if the two `FlagSet`s do not share any flags. 993 /// 994 /// ``` 995 /// use flagset::{FlagSet, flags}; 996 /// 997 /// flags! { 998 /// pub enum Flag: u8 { 999 /// Foo = 1, 1000 /// Bar = 2, 1001 /// Baz = 4 1002 /// } 1003 /// } 1004 /// 1005 /// let set = Flag::Foo | Flag::Bar; 1006 /// assert!(!set.is_disjoint(Flag::Foo)); 1007 /// assert!(!set.is_disjoint(Flag::Foo | Flag::Baz)); 1008 /// assert!(set.is_disjoint(Flag::Baz)); 1009 /// ``` 1010 #[inline] is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool1011 pub fn is_disjoint(self, rhs: impl Into<FlagSet<F>>) -> bool { 1012 self & rhs == Self::default() 1013 } 1014 1015 /// Returns true if this FlagSet is a superset of the specified flags. 1016 /// 1017 /// ``` 1018 /// use flagset::{FlagSet, flags}; 1019 /// 1020 /// flags! { 1021 /// pub enum Flag: u8 { 1022 /// Foo = 1, 1023 /// Bar = 2, 1024 /// Baz = 4 1025 /// } 1026 /// } 1027 /// 1028 /// let set = Flag::Foo | Flag::Bar; 1029 /// assert!(set.contains(Flag::Foo)); 1030 /// assert!(set.contains(Flag::Foo | Flag::Bar)); 1031 /// assert!(!set.contains(Flag::Foo | Flag::Bar | Flag::Baz)); 1032 /// ``` 1033 #[inline] contains(self, rhs: impl Into<FlagSet<F>>) -> bool1034 pub fn contains(self, rhs: impl Into<FlagSet<F>>) -> bool { 1035 let rhs = rhs.into(); 1036 self & rhs == rhs 1037 } 1038 1039 /// Removes all flags from the FlagSet. 1040 /// 1041 /// ``` 1042 /// use flagset::{FlagSet, flags}; 1043 /// 1044 /// flags! { 1045 /// pub enum Flag: u8 { 1046 /// Foo = 1, 1047 /// Bar = 2, 1048 /// Baz = 4 1049 /// } 1050 /// } 1051 /// 1052 /// let mut set = Flag::Foo | Flag::Bar; 1053 /// assert!(!set.is_empty()); 1054 /// 1055 /// set.clear(); 1056 /// assert!(set.is_empty()); 1057 /// ``` 1058 #[inline] clear(&mut self)1059 pub fn clear(&mut self) { 1060 *self = Self::default(); 1061 } 1062 1063 /// Clears the current set and returns an iterator of all removed flags. 1064 /// 1065 /// ``` 1066 /// use flagset::{FlagSet, flags}; 1067 /// 1068 /// flags! { 1069 /// pub enum Flag: u8 { 1070 /// Foo = 1, 1071 /// Bar = 2, 1072 /// Baz = 4 1073 /// } 1074 /// } 1075 /// 1076 /// let mut set = Flag::Foo | Flag::Bar; 1077 /// let mut iter = set.drain(); 1078 /// assert!(set.is_empty()); 1079 /// assert_eq!(iter.next(), Some(Flag::Foo)); 1080 /// assert_eq!(iter.next(), Some(Flag::Bar)); 1081 /// assert_eq!(iter.next(), None); 1082 /// ``` 1083 #[inline] drain(&mut self) -> Iter<F>1084 pub fn drain(&mut self) -> Iter<F> { 1085 let iter = self.into_iter(); 1086 *self = Self::default(); 1087 iter 1088 } 1089 1090 /// Retain only the flags flags specified by the predicate. 1091 /// 1092 /// ``` 1093 /// use flagset::{FlagSet, flags}; 1094 /// 1095 /// flags! { 1096 /// pub enum Flag: u8 { 1097 /// Foo = 1, 1098 /// Bar = 2, 1099 /// Baz = 4 1100 /// } 1101 /// } 1102 /// 1103 /// let mut set0 = Flag::Foo | Flag::Bar; 1104 /// set0.retain(|f| f != Flag::Foo); 1105 /// assert_eq!(set0, Flag::Bar); 1106 /// ``` 1107 #[inline] retain(&mut self, func: impl Fn(F) -> bool)1108 pub fn retain(&mut self, func: impl Fn(F) -> bool) { 1109 for f in self.into_iter() { 1110 if !func(f) { 1111 *self -= f 1112 } 1113 } 1114 } 1115 } 1116 1117 #[cfg(feature = "serde")] 1118 impl<F: Flags> serde::Serialize for FlagSet<F> 1119 where 1120 F::Type: serde::ser::Serialize, 1121 { 1122 #[inline] serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> where S: serde::ser::Serializer,1123 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error> 1124 where 1125 S: serde::ser::Serializer, 1126 { 1127 self.0.serialize(serializer) 1128 } 1129 } 1130 1131 #[cfg(feature = "serde")] 1132 impl<'de, F: Flags> serde::Deserialize<'de> for FlagSet<F> 1133 where 1134 F::Type: serde::de::Deserialize<'de>, 1135 { 1136 #[inline] deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> where D: serde::de::Deserializer<'de>,1137 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error> 1138 where 1139 D: serde::de::Deserializer<'de>, 1140 { 1141 Ok(FlagSet(F::Type::deserialize(deserializer)?)) 1142 } 1143 } 1144 1145 /// Define flag value using the `enum` syntax. See below for details. 1146 /// 1147 /// Each enumeration value **MUST** have a specified value. 1148 /// 1149 /// The width of the bitfield **MUST** also be specified by its integer type. 1150 /// 1151 /// It is important to note that the size of the flag enumeration itself is 1152 /// unrelated to the size of the corresponding `FlagSet` instance. 1153 /// 1154 /// It is also worth noting that this macro automatically implements a variety 1155 /// of standard traits including: 1156 /// * Copy 1157 /// * Clone 1158 /// * Debug 1159 /// * PartialEq 1160 /// * Eq 1161 /// * From<$enum> for $integer 1162 /// * Not 1163 /// * BitAnd 1164 /// * BitOr 1165 /// * BitXor 1166 /// * Sub 1167 /// * Rem 1168 /// 1169 /// ``` 1170 /// use std::mem::{align_of, size_of}; 1171 /// use flagset::{FlagSet, flags}; 1172 /// 1173 /// flags! { 1174 /// enum FlagEmpty: u32 {} 1175 /// 1176 /// enum Flag8: u8 { 1177 /// Foo = 0b001, 1178 /// Bar = 0b010, 1179 /// Baz = 0b100 1180 /// } 1181 /// 1182 /// pub enum Flag16: u16 { 1183 /// Foo, 1184 /// Bar, 1185 /// #[deprecated] 1186 /// Baz, 1187 /// } 1188 /// 1189 /// #[derive(PartialOrd, Ord)] 1190 /// enum Flag32: u32 { 1191 /// Foo = 0b001, 1192 /// #[deprecated] 1193 /// Bar = 0b010, 1194 /// Baz = 0b100 1195 /// } 1196 /// 1197 /// #[repr(u64)] 1198 /// enum Flag64: u64 { 1199 /// Foo = 0b001, 1200 /// Bar = 0b010, 1201 /// Baz = 0b100 1202 /// } 1203 /// 1204 /// #[repr(u32)] 1205 /// enum Flag128: u128 { 1206 /// Foo = 0b001, 1207 /// Bar = 0b010, 1208 /// Baz = 0b100 1209 /// } 1210 /// } 1211 /// 1212 /// assert_eq!(size_of::<Flag8>(), 1); 1213 /// assert_eq!(size_of::<Flag16>(), 1); 1214 /// assert_eq!(size_of::<Flag32>(), 1); 1215 /// assert_eq!(size_of::<Flag64>(), 8); 1216 /// assert_eq!(size_of::<Flag128>(), 4); 1217 /// 1218 /// assert_eq!(align_of::<Flag8>(), 1); 1219 /// assert_eq!(align_of::<Flag16>(), 1); 1220 /// assert_eq!(align_of::<Flag32>(), 1); 1221 /// assert_eq!(align_of::<Flag64>(), align_of::<u64>()); 1222 /// assert_eq!(align_of::<Flag128>(), align_of::<u32>()); 1223 /// 1224 /// assert_eq!(size_of::<FlagSet<Flag8>>(), size_of::<u8>()); 1225 /// assert_eq!(size_of::<FlagSet<Flag16>>(), size_of::<u16>()); 1226 /// assert_eq!(size_of::<FlagSet<Flag32>>(), size_of::<u32>()); 1227 /// assert_eq!(size_of::<FlagSet<Flag64>>(), size_of::<u64>()); 1228 /// assert_eq!(size_of::<FlagSet<Flag128>>(), size_of::<u128>()); 1229 /// 1230 /// assert_eq!(align_of::<FlagSet<Flag8>>(), align_of::<u8>()); 1231 /// assert_eq!(align_of::<FlagSet<Flag16>>(), align_of::<u16>()); 1232 /// assert_eq!(align_of::<FlagSet<Flag32>>(), align_of::<u32>()); 1233 /// assert_eq!(align_of::<FlagSet<Flag64>>(), align_of::<u64>()); 1234 /// assert_eq!(align_of::<FlagSet<Flag128>>(), align_of::<u128>()); 1235 /// ``` 1236 #[macro_export] 1237 macro_rules! flags { 1238 () => {}; 1239 1240 // Entry point for enumerations without values. 1241 ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])* $k:ident),+ $(,)* } $($next:tt)*) => { 1242 $crate::flags! { $(#[$m])* $p enum $n: $t { $($(#[$a])* $k = (1 << $n::$k as $t)),+ } $($next)* } 1243 }; 1244 1245 // Entrypoint for enumerations with values. 1246 ($(#[$m:meta])* $p:vis enum $n:ident: $t:ty { $($(#[$a:meta])*$k:ident = $v:expr),* $(,)* } $($next:tt)*) => { 1247 $(#[$m])* 1248 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 1249 $p enum $n { $($(#[$a])* $k),* } 1250 1251 impl $crate::Flags for $n { 1252 type Type = $t; 1253 1254 const LIST: &'static [Self] = &[$($n::$k),*]; 1255 } 1256 1257 impl ::core::convert::From<$n> for $crate::FlagSet<$n> { 1258 #[inline] 1259 fn from(value: $n) -> Self { 1260 unsafe { 1261 match value { 1262 $($n::$k => Self::new_unchecked($v)),* 1263 } 1264 } 1265 } 1266 } 1267 1268 impl ::core::ops::Not for $n { 1269 type Output = $crate::FlagSet<$n>; 1270 1271 #[inline] 1272 fn not(self) -> Self::Output { 1273 !$crate::FlagSet::from(self) 1274 } 1275 } 1276 1277 impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitAnd<R> for $n { 1278 type Output = $crate::FlagSet<$n>; 1279 1280 #[inline] 1281 fn bitand(self, rhs: R) -> Self::Output { 1282 $crate::FlagSet::from(self) & rhs 1283 } 1284 } 1285 1286 impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitOr<R> for $n { 1287 type Output = $crate::FlagSet<$n>; 1288 1289 #[inline] 1290 fn bitor(self, rhs: R) -> Self::Output { 1291 $crate::FlagSet::from(self) | rhs 1292 } 1293 } 1294 1295 impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::BitXor<R> for $n { 1296 type Output = $crate::FlagSet<$n>; 1297 1298 #[inline] 1299 fn bitxor(self, rhs: R) -> Self::Output { 1300 $crate::FlagSet::from(self) ^ rhs 1301 } 1302 } 1303 1304 impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::Sub<R> for $n { 1305 type Output = $crate::FlagSet<$n>; 1306 1307 #[inline] 1308 fn sub(self, rhs: R) -> Self::Output { 1309 $crate::FlagSet::from(self) - rhs 1310 } 1311 } 1312 1313 impl<R: ::core::convert::Into<$crate::FlagSet<$n>>> ::core::ops::Rem<R> for $n { 1314 type Output = $crate::FlagSet<$n>; 1315 1316 #[inline] 1317 fn rem(self, rhs: R) -> Self::Output { 1318 $crate::FlagSet::from(self) % rhs 1319 } 1320 } 1321 1322 $crate::flags! { $($next)* } 1323 }; 1324 } 1325