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