#![warn(missing_docs)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
use core::{cmp, ops};
use core::iter::FromIterator;
#[allow(unused_imports)]
#[macro_use]
extern crate enumflags2_derive;
#[doc(hidden)]
pub use enumflags2_derive::BitFlags_internal as BitFlags;
pub trait RawBitFlags: Copy + Clone + 'static + _internal::RawBitFlags {
fn empty() -> BitFlags<Self> {
BitFlags::empty()
}
fn all() -> BitFlags<Self> {
BitFlags::all()
}
}
#[doc(hidden)]
pub mod _internal {
pub trait RawBitFlags: Copy + Clone + 'static {
type Type: BitFlagNum;
fn all_bits() -> Self::Type;
fn bits(self) -> Self::Type;
fn flag_list() -> &'static [Self];
fn bitflags_type_name() -> &'static str {
"BitFlags"
}
}
use ::core::ops::{BitAnd, BitOr, BitXor, Not};
use ::core::cmp::PartialOrd;
use ::core::fmt;
pub trait BitFlagNum
: Default
+ BitOr<Self, Output = Self>
+ BitAnd<Self, Output = Self>
+ BitXor<Self, Output = Self>
+ Not<Output = Self>
+ PartialOrd<Self>
+ fmt::Debug
+ fmt::Binary
+ Copy
+ Clone {
}
impl BitFlagNum for u8 {}
impl BitFlagNum for u16 {}
impl BitFlagNum for u32 {}
impl BitFlagNum for u64 {}
impl BitFlagNum for usize {}
pub mod core {
pub use core::{convert, option, ops};
}
pub struct AssertionSucceeded;
pub struct AssertionFailed;
pub trait ExactlyOneBitSet {
type X;
}
impl ExactlyOneBitSet for AssertionSucceeded {
type X = ();
}
pub trait AssertionHelper {
type Status;
}
impl AssertionHelper for [(); 1] {
type Status = AssertionSucceeded;
}
impl AssertionHelper for [(); 0] {
type Status = AssertionFailed;
}
}
mod formatting;
mod fallible;
pub use crate::fallible::FromBitsError;
#[derive(Copy, Clone, Eq, Hash)]
#[repr(transparent)]
pub struct BitFlags<T: RawBitFlags> {
val: T::Type,
}
impl<T> Default for BitFlags<T>
where
T: RawBitFlags,
{
fn default() -> Self {
Self::empty()
}
}
impl<T: RawBitFlags> From<T> for BitFlags<T> {
fn from(t: T) -> BitFlags<T> {
Self::from_flag(t)
}
}
impl<T> BitFlags<T>
where
T: RawBitFlags,
{
pub unsafe fn new(val: T::Type) -> Self {
BitFlags { val }
}
pub fn empty() -> Self {
unsafe { BitFlags::new(T::Type::default()) }
}
pub fn all() -> Self {
unsafe { BitFlags::new(T::all_bits()) }
}
pub fn is_all(self) -> bool {
self.val == T::all_bits()
}
pub fn is_empty(self) -> bool {
self.val == Self::empty().bits()
}
pub fn bits(self) -> T::Type {
self.val
}
pub fn intersects<B: Into<BitFlags<T>>>(self, other: B) -> bool {
(self.bits() & other.into().bits()) > Self::empty().bits()
}
pub fn contains<B: Into<BitFlags<T>>>(self, other: B) -> bool {
let other = other.into();
(self.bits() & other.bits()) == other.bits()
}
pub fn from_bits(bits: T::Type) -> Result<Self, FromBitsError<T>> {
let flags = Self::from_bits_truncate(bits);
if flags.bits() == bits {
Ok(flags)
} else {
Err(FromBitsError {
flags,
invalid: bits & !flags.bits(),
})
}
}
pub fn from_flag(flag: T) -> Self {
BitFlags { val: flag.bits() }
}
pub fn from_bits_truncate(bits: T::Type) -> Self {
unsafe { BitFlags::new(bits & T::all_bits()) }
}
pub fn toggle<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self ^= other.into();
}
pub fn insert<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self |= other.into();
}
pub fn remove<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self &= !other.into();
}
pub fn iter(self) -> impl Iterator<Item = T> {
T::flag_list().iter().cloned().filter(move |&flag| self.contains(flag))
}
}
impl<T, B> cmp::PartialEq<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>> + Copy,
{
fn eq(&self, other: &B) -> bool {
self.bits() == Into::<Self>::into(*other).bits()
}
}
impl<T, B> ops::BitOr<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
fn bitor(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::new(self.bits() | other.into().bits()) }
}
}
impl<T, B> ops::BitAnd<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
fn bitand(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::new(self.bits() & other.into().bits()) }
}
}
impl<T, B> ops::BitXor<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
fn bitxor(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::new(self.bits() ^ other.into().bits()) }
}
}
impl<T, B> ops::BitOrAssign<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
fn bitor_assign(&mut self, other: B) {
*self = *self | other;
}
}
impl<T, B> ops::BitAndAssign<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
fn bitand_assign(&mut self, other: B) {
*self = *self & other;
}
}
impl<T, B> ops::BitXorAssign<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>,
{
fn bitxor_assign(&mut self, other: B) {
*self = *self ^ other;
}
}
impl<T> ops::Not for BitFlags<T>
where
T: RawBitFlags,
{
type Output = BitFlags<T>;
fn not(self) -> BitFlags<T> {
unsafe { BitFlags::new(!self.bits() & T::all_bits()) }
}
}
impl<T, B> FromIterator<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>
{
fn from_iter<I>(it: I) -> BitFlags<T>
where
I: IntoIterator<Item = B>
{
it.into_iter().fold(BitFlags::empty(), |acc, flag| acc | flag)
}
}
impl<T, B> Extend<B> for BitFlags<T>
where
T: RawBitFlags,
B: Into<BitFlags<T>>
{
fn extend<I>(&mut self, it: I)
where
I: IntoIterator<Item = B>
{
*self = it.into_iter().fold(*self, |acc, flag| acc | flag)
}
}
#[cfg(feature = "serde")]
mod impl_serde {
use serde::{Serialize, Deserialize};
use serde::de::{Error, Unexpected};
use super::{BitFlags, RawBitFlags};
impl<'a, T> Deserialize<'a> for BitFlags<T>
where
T: RawBitFlags,
T::Type: Deserialize<'a> + Into<u64>,
{
fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
let val = T::Type::deserialize(d)?;
Self::from_bits(val)
.map_err(|_| D::Error::invalid_value(
Unexpected::Unsigned(val.into()),
&"valid bit representation"
))
}
}
impl<T> Serialize for BitFlags<T>
where
T: RawBitFlags,
T::Type: Serialize,
{
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
T::Type::serialize(&self.val, s)
}
}
}