use core::fmt;
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
pub struct Status(u32);
impl Status {
pub const INVALID_OP: Self = Self(1 << 0);
pub const DIVIDE_ZERO: Self = Self(1 << 1);
pub const OVERFLOW: Self = Self(1 << 2);
pub const UNDERFLOW: Self = Self(1 << 3);
pub const INEXACT: Self = Self(1 << 4);
pub const fn empty() -> Self {
Self(0)
}
pub const fn from_bits_retain(bits: u32) -> Self {
Self(bits)
}
pub const fn bits(self) -> u32 {
self.0
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
}
impl fmt::Debug for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
let items = [
(Self::INVALID_OP, "INVALID_OP"),
(Self::DIVIDE_ZERO, "DIVIDE_ZERO"),
(Self::OVERFLOW, "OVERFLOW"),
(Self::UNDERFLOW, "UNDERFLOW"),
(Self::INEXACT, "INEXACT"),
];
f.write_str("Status(")?;
for (flag, name) in items {
if self.contains(flag) {
if !first {
f.write_str(" | ")?;
}
first = false;
f.write_str(name)?;
}
}
if first {
f.write_str("empty")?;
}
f.write_str(")")
}
}
impl BitOr for Status {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl BitOrAssign for Status {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
impl BitAnd for Status {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}
impl BitAndAssign for Status {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
impl Not for Status {
type Output = Self;
fn not(self) -> Self::Output {
Self(!self.0)
}
}