#![macro_use]
pub trait EnumFlags<TFlag: ::std::ops::BitOr<TFlag> + ::std::ops::BitAnd<TFlag> + ::std::ops::BitXor<TFlag>> {
fn has_flag<T: Into<TFlag>>(self, flag: T) -> bool;
fn raw_value(self) -> i32;
}
#[macro_export]
macro_rules! enum_flags {
($name:ident : $flagsName:ident => $($flag:ident = $value:expr),+) => {
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash)]
pub enum $flagsName {
$(
$flag = $value
),+
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash)]
pub struct $name(i32);
impl $name {
#[inline]
fn none() -> $name {
$name(0)
}
}
impl Into<$name> for $flagsName {
#[inline]
fn into(self) -> $name {
$name(self as i32)
}
}
impl $crate::util::EnumFlags<$name> for $name {
fn has_flag<T: Into<$name>>(self, flag: T) -> bool {
let rhs: $name = flag.into();
(self.0 & rhs.0) == rhs.0
}
fn raw_value(self) -> i32 {
self.0
}
}
impl<T: Into<$name>> ::std::ops::BitOr<T> for $name {
type Output = $name;
#[inline]
fn bitor(self, rhs: T) -> $name {
$name(self.0 | rhs.into().0)
}
}
impl<T: Into<$name>> ::std::ops::BitOr<T> for $flagsName {
type Output = $name;
#[inline]
fn bitor(self, rhs: T) -> $name {
$name(Into::<$name>::into(self).0 | rhs.into().0)
}
}
impl<T: Into<$name>> ::std::ops::BitXor<T> for $name {
type Output = $name;
#[inline]
fn bitxor(self, rhs: T) -> $name {
$name(self.0 ^ rhs.into().0)
}
}
impl<T: Into<$name>> ::std::ops::BitXor<T> for $flagsName {
type Output = $name;
#[inline]
fn bitxor(self, rhs: T) -> $name {
$name(Into::<$name>::into(self).0 ^ rhs.into().0)
}
}
impl<T: Into<$name>> ::std::ops::BitAnd<T> for $name {
type Output = $name;
#[inline]
fn bitand(self, rhs: T) -> $name {
$name(self.0 & rhs.into().0)
}
}
impl<T: Into<$name>> ::std::ops::BitAnd<T> for $flagsName {
type Output = $name;
#[inline]
fn bitand(self, rhs: T) -> $name {
$name(Into::<$name>::into(self).0 & rhs.into().0)
}
}
impl<T: Into<$name> + Copy> ::std::cmp::PartialEq<T> for $name {
#[inline]
fn eq(&self, other: &T) -> bool {
Into::<$name>::into(*self).0 == Into::<$name>::into(*other).0
}
#[inline]
fn ne(&self, other: &T) -> bool {
Into::<$name>::into(*self).0 != Into::<$name>::into(*other).0
}
}
impl ::std::cmp::Eq for $name {}
impl<T: Into<$name> + Copy> ::std::cmp::PartialEq<T> for $flagsName {
#[inline]
fn eq(&self, other: &T) -> bool {
Into::<$name>::into(*self).0 == Into::<$name>::into(*other).0
}
#[inline]
fn ne(&self, other: &T) -> bool {
Into::<$name>::into(*self).0 != Into::<$name>::into(*other).0
}
}
impl ::std::cmp::Eq for $flagsName {}
}
}