#![no_std]
#[cfg(not(feature = "nostd"))]
extern crate std;
#[cfg(feature = "nostd")]
extern crate core as std;
use std::ops::{BitAnd, BitOr, BitXor, Not};
use std::cmp::PartialOrd;
use std::fmt::{self, Formatter};
use std::iter::FromIterator;
pub trait BitFlagNum
: Default
+ BitOr<Self, Output = Self>
+ BitAnd<Self, Output = Self>
+ BitXor<Self, Output = Self>
+ Not<Output = Self>
+ PartialOrd<Self>
+ Copy
+ Clone {
}
impl BitFlagNum for u8 {}
impl BitFlagNum for u16 {}
impl BitFlagNum for u32 {}
impl BitFlagNum for u64 {}
impl BitFlagNum for usize {}
pub trait BitFlagsFmt
where
Self: RawBitFlags,
{
fn fmt(flags: BitFlags<Self>, f: &mut Formatter) -> fmt::Result;
}
pub trait RawBitFlags: Copy + Clone {
type Type: BitFlagNum;
fn all() -> Self::Type;
fn bits(self) -> Self::Type;
}
#[derive(Copy, Clone)]
pub struct BitFlags<T: RawBitFlags> {
val: T::Type,
}
impl<T> ::std::fmt::Debug for BitFlags<T>
where
T: RawBitFlags + BitFlagsFmt,
{
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
T::fmt(self.clone(), fmt)
}
}
impl<T> BitFlags<T>
where
T: RawBitFlags,
{
pub unsafe fn new(val: T::Type) -> Self {
BitFlags { val }
}
}
impl<T: RawBitFlags> From<T> for BitFlags<T> {
fn from(t: T) -> BitFlags<T> {
BitFlags { val: t.bits() }
}
}
impl<T> BitFlags<T>
where
T: RawBitFlags,
{
pub fn empty() -> Self {
unsafe { BitFlags::new(T::Type::default()) }
}
pub fn all() -> Self {
unsafe { BitFlags::new(T::all()) }
}
pub fn is_all(self) -> bool {
self.val == T::all()
}
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 not(self) -> Self {
unsafe { BitFlags::new(!self.bits() & T::all()) }
}
pub fn from_bits(bits: T::Type) -> Option<Self> {
if bits & !Self::all().bits() == Self::empty().bits() {
unsafe { Some(BitFlags::new(bits)) }
} else {
None
}
}
pub fn from_bits_truncate(bits: T::Type) -> Self {
unsafe { BitFlags::new(bits & T::all()) }
}
pub fn toggle<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self = *self ^ other.into();
}
pub fn insert<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self = *self | other.into();
}
pub fn remove<B: Into<BitFlags<T>>>(&mut self, other: B) {
*self = *self & !other.into();
}
}
impl<T, B> std::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> std::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> std::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> std::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()) & T::all()) }
}
}
impl<T, B> std::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> std::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> std::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> std::ops::Not for BitFlags<T>
where
T: RawBitFlags,
{
type Output = BitFlags<T>;
fn not(self) -> BitFlags<T> {
self.not()
}
}
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>
{
let mut flags = BitFlags::empty();
for flag in it {
flags |= flag.into();
}
flags
}
}