use std::{fmt, ops};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Features(u64);
impl Features {
pub const NONE: Features = Features(0b00000000);
pub const SEED: Features = Features(0b00000001);
#[must_use]
pub fn with(self, other: Features) -> Features {
Self(self.0 | other.0)
}
#[must_use]
pub fn without(self, other: Features) -> Features {
Self(self.0 ^ other.0)
}
pub fn has(self, flags: Features) -> bool {
(self.0 | flags.0) == self.0
}
}
impl Default for Features {
fn default() -> Self {
Self::NONE
}
}
impl ops::Deref for Features {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::LowerHex for Features {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}
impl fmt::UpperHex for Features {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::UpperHex::fmt(&self.0, f)
}
}
impl fmt::Display for Features {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if *self == Features::NONE {
write!(f, "Features(NONE)")
} else {
write!(f, "Features(0x{:x})", self.0)
}
}
}
impl From<u64> for Features {
fn from(f: u64) -> Self {
Features(f)
}
}
impl From<Features> for u64 {
fn from(flags: Features) -> Self {
flags.0
}
}
impl ops::BitOr for Features {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
self.with(rhs)
}
}
impl ops::BitOrAssign for Features {
fn bitor_assign(&mut self, rhs: Self) {
*self = self.with(rhs);
}
}
impl ops::BitXor for Features {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
self.without(rhs)
}
}
impl ops::BitXorAssign for Features {
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.without(rhs);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_operations() {
assert_eq!(Features::NONE.with(Features::SEED), Features::SEED);
assert!(!Features::from(u64::MAX)
.without(Features::SEED)
.has(Features::SEED));
assert!(Features::from(u64::MIN)
.with(Features::SEED)
.has(Features::SEED));
assert_eq!(
Features::NONE.with(Features::SEED).without(Features::SEED),
Features::NONE
);
}
}