#![warn(missing_docs)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::{cmp, ops};
#[allow(unused_imports)]
#[macro_use]
extern crate enumflags2_derive;
#[doc(hidden)]
pub use enumflags2_derive::bitflags_internal as bitflags;
macro_rules! for_each_uint {
( $d:tt $tyvar:ident $dd:tt $docattr:ident => $($input:tt)* ) => {
macro_rules! implement {
( $d $tyvar:ty => $d($d $docattr:meta)? ) => {
$($input)*
}
}
implement! { u8 => }
implement! { u16 => doc(hidden) }
implement! { u32 => doc(hidden) }
implement! { u64 => doc(hidden) }
implement! { u128 => doc(hidden) }
}
}
pub trait BitFlag: Copy + Clone + 'static + _internal::RawBitFlags {
#[inline]
fn empty() -> BitFlags<Self> {
BitFlags::empty()
}
#[inline]
fn all() -> BitFlags<Self> {
BitFlags::all()
}
#[inline]
fn from_bits(bits: Self::Numeric) -> Result<BitFlags<Self>, FromBitsError<Self>> {
BitFlags::from_bits(bits)
}
#[inline]
fn from_bits_truncate(bits: Self::Numeric) -> BitFlags<Self> {
BitFlags::from_bits_truncate(bits)
}
#[inline]
unsafe fn from_bits_unchecked(bits: Self::Numeric) -> BitFlags<Self> {
BitFlags::from_bits_unchecked(bits)
}
}
#[doc(hidden)]
pub mod _internal {
pub unsafe trait RawBitFlags: Copy + Clone + 'static {
type Numeric: BitFlagNum;
const EMPTY: Self::Numeric;
const DEFAULT: Self::Numeric;
const ALL_BITS: Self::Numeric;
const BITFLAGS_TYPE_NAME: &'static str;
fn bits(self) -> Self::Numeric;
}
use ::core::fmt;
use ::core::ops::{BitAnd, BitOr, BitXor, Not, Sub};
use ::core::hash::Hash;
pub trait BitFlagNum:
Default
+ BitOr<Self, Output = Self>
+ BitAnd<Self, Output = Self>
+ BitXor<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Not<Output = Self>
+ PartialOrd<Self>
+ Ord
+ Hash
+ fmt::Debug
+ fmt::Binary
+ Copy
+ Clone
{
const ONE: Self;
fn is_power_of_two(self) -> bool;
fn count_ones(self) -> u32;
fn wrapping_neg(self) -> Self;
}
for_each_uint! { $ty $hide_docs =>
impl BitFlagNum for $ty {
const ONE: Self = 1;
fn is_power_of_two(self) -> bool {
<$ty>::is_power_of_two(self)
}
fn count_ones(self) -> u32 {
<$ty>::count_ones(self)
}
fn wrapping_neg(self) -> Self {
<$ty>::wrapping_neg(self)
}
}
}
pub mod core {
pub use core::{convert, ops, option};
}
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;
}
pub const fn next_bit(x: u128) -> u128 {
1 << x.trailing_ones()
}
}
use _internal::BitFlagNum;
mod formatting;
mod fallible;
pub use crate::fallible::FromBitsError;
mod iter;
pub use crate::iter::Iter;
mod const_api;
pub use crate::const_api::ConstToken;
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct BitFlags<T, N = <T as _internal::RawBitFlags>::Numeric> {
val: N,
marker: PhantomData<T>,
}
#[macro_export]
macro_rules! make_bitflags {
( $enum:ident ::{ $($variant:ident)|* } ) => {
{
let mut n = 0;
$(
{
let flag: $enum = $enum::$variant;
n |= flag as <$enum as $crate::_internal::RawBitFlags>::Numeric;
}
)*
unsafe { $crate::BitFlags::<$enum>::from_bits_unchecked_c(
n, $crate::BitFlags::CONST_TOKEN) }
}
};
( $enum:ident :: $variant:ident ) => {
{
let flag: $enum = $enum::$variant;
let n = flag as <$enum as $crate::_internal::RawBitFlags>::Numeric;
unsafe { $crate::BitFlags::<$enum>::from_bits_unchecked_c(
n, $crate::BitFlags::CONST_TOKEN) }
}
};
}
impl<T> Default for BitFlags<T>
where
T: BitFlag,
{
#[inline(always)]
fn default() -> Self {
BitFlags {
val: T::DEFAULT,
marker: PhantomData,
}
}
}
impl<T: BitFlag> From<T> for BitFlags<T> {
#[inline(always)]
fn from(t: T) -> BitFlags<T> {
Self::from_flag(t)
}
}
impl<T> BitFlags<T>
where
T: BitFlag,
{
#[inline]
pub fn from_bits(bits: T::Numeric) -> 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(),
})
}
}
#[must_use]
#[inline(always)]
pub fn from_bits_truncate(bits: T::Numeric) -> Self {
unsafe { BitFlags::from_bits_unchecked(bits & T::ALL_BITS) }
}
#[must_use]
#[inline(always)]
pub unsafe fn from_bits_unchecked(val: T::Numeric) -> Self {
BitFlags {
val,
marker: PhantomData,
}
}
#[must_use]
#[inline(always)]
pub fn from_flag(flag: T) -> Self {
unsafe { Self::from_bits_unchecked(flag.bits()) }
}
#[inline(always)]
pub fn empty() -> Self {
Self::EMPTY
}
#[inline(always)]
pub fn all() -> Self {
Self::ALL
}
#[inline(always)]
pub fn is_all(self) -> bool {
self.val == T::ALL_BITS
}
#[inline(always)]
pub fn is_empty(self) -> bool {
self.val == T::EMPTY
}
#[inline(always)]
pub fn len(self) -> usize {
self.val.count_ones() as usize
}
#[inline(always)]
pub fn exactly_one(self) -> Option<T> {
if self.val.is_power_of_two() {
Some(unsafe { core::mem::transmute_copy(&self.val) })
} else {
None
}
}
#[inline(always)]
pub fn bits(self) -> T::Numeric {
self.val
}
#[inline(always)]
pub fn intersects<B: Into<BitFlags<T>>>(self, other: B) -> bool {
(self.bits() & other.into().bits()) != Self::EMPTY.val
}
#[inline(always)]
pub fn contains<B: Into<BitFlags<T>>>(self, other: B) -> bool {
let other = other.into();
(self.bits() & other.bits()) == other.bits()
}
#[inline(always)]
pub fn toggle<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self ^= other.into();
}
#[inline(always)]
pub fn insert<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self |= other.into();
}
#[inline(always)]
pub fn remove<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self &= !other.into();
}
#[inline(always)]
pub fn set<B: Into<BitFlags<T>>>(&mut self, other: B, cond: bool) {
if cond {
self.insert(other);
} else {
self.remove(other);
}
}
}
impl<T, N: PartialEq> PartialEq for BitFlags<T, N> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.val == other.val
}
}
impl<T, N: Eq> Eq for BitFlags<T, N> {}
impl<T, N: PartialOrd> PartialOrd for BitFlags<T, N> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.val.partial_cmp(&other.val)
}
}
impl<T, N: Ord> Ord for BitFlags<T, N> {
#[inline(always)]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.val.cmp(&other.val)
}
}
impl<T, N: Hash> Hash for BitFlags<T, N> {
#[inline(always)]
fn hash<H: Hasher>(&self, state: &mut H) {
self.val.hash(state)
}
}
impl<T> cmp::PartialEq<T> for BitFlags<T>
where
T: BitFlag,
{
#[inline(always)]
fn eq(&self, other: &T) -> bool {
self.bits() == Into::<Self>::into(*other).bits()
}
}
impl<T, B> ops::BitOr<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
#[inline(always)]
fn bitor(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::from_bits_unchecked(self.bits() | other.into().bits()) }
}
}
impl<T, B> ops::BitAnd<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
#[inline(always)]
fn bitand(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::from_bits_unchecked(self.bits() & other.into().bits()) }
}
}
impl<T, B> ops::BitXor<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
type Output = BitFlags<T>;
#[inline(always)]
fn bitxor(self, other: B) -> BitFlags<T> {
unsafe { BitFlags::from_bits_unchecked(self.bits() ^ other.into().bits()) }
}
}
impl<T, B> ops::BitOrAssign<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
#[inline(always)]
fn bitor_assign(&mut self, other: B) {
*self = *self | other;
}
}
impl<T, B> ops::BitAndAssign<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
#[inline(always)]
fn bitand_assign(&mut self, other: B) {
*self = *self & other;
}
}
impl<T, B> ops::BitXorAssign<B> for BitFlags<T>
where
T: BitFlag,
B: Into<BitFlags<T>>,
{
#[inline(always)]
fn bitxor_assign(&mut self, other: B) {
*self = *self ^ other;
}
}
impl<T> ops::Not for BitFlags<T>
where
T: BitFlag,
{
type Output = BitFlags<T>;
#[inline(always)]
fn not(self) -> BitFlags<T> {
BitFlags::from_bits_truncate(!self.bits())
}
}
#[cfg(feature = "serde")]
mod impl_serde {
use super::{BitFlag, BitFlags};
use serde::de::{Error, Unexpected};
use serde::{Deserialize, Serialize};
impl<'a, T> Deserialize<'a> for BitFlags<T>
where
T: BitFlag,
T::Numeric: Deserialize<'a> + Into<u64>,
{
fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
let val = T::Numeric::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: BitFlag,
T::Numeric: Serialize,
{
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
T::Numeric::serialize(&self.val, s)
}
}
}