use std::{fmt, str::FromStr};
use crate::error::Error;
#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Logic {
False,
True,
X,
Z,
}
impl Logic {
pub fn unwrap(self) -> bool {
match self {
Logic::True => true,
Logic::False => false,
_ => panic!("Logic is not truthy"),
}
}
pub fn expect(self, msg: &str) -> bool {
match self {
Logic::True => true,
Logic::False => false,
_ => panic!("{}", msg),
}
}
pub fn is_dont_care(&self) -> bool {
matches!(self, Logic::X)
}
pub fn as_str(&self) -> &str {
match self {
Logic::True => "1'b1",
Logic::False => "1'b0",
Logic::X => "1'bx",
Logic::Z => "1'bz",
}
}
pub fn from_bool(b: bool) -> Logic {
if b { Logic::True } else { Logic::False }
}
}
impl std::ops::BitAnd for Logic {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Logic::False, _) | (_, Logic::False) => Logic::False,
(Logic::True, Logic::True) => Logic::True,
(Logic::True, Logic::Z) | (Logic::Z, Logic::True) => Logic::X,
(Logic::X, _) | (_, Logic::X) | (Logic::Z, Logic::Z) => Logic::X,
}
}
}
impl std::ops::BitOr for Logic {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Logic::True, _) | (_, Logic::True) => Logic::True,
(Logic::False, Logic::False) => Logic::False,
_ => Logic::X,
}
}
}
impl std::ops::Not for Logic {
type Output = Self;
fn not(self) -> Self::Output {
match self {
Logic::False => Logic::True,
Logic::True => Logic::False,
_ => Logic::X,
}
}
}
impl fmt::Display for Logic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Logic::True => write!(f, "1'b1"),
Logic::False => write!(f, "1'b0"),
Logic::X => write!(f, "1'bx"),
Logic::Z => write!(f, "1'bz"),
}
}
}
impl From<bool> for Logic {
fn from(value: bool) -> Self {
if value { Logic::True } else { Logic::False }
}
}
impl FromStr for Logic {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"1'b1" | "1'h1" => Ok(Logic::True),
"1'b0" | "1'h0" => Ok(Logic::False),
"1'bx" | "1'hx" => Ok(Logic::X),
"1'bz" | "1'hz" => Ok(Logic::Z),
_ => Err(Error::ParseError(s.to_string())),
}
}
}
pub fn r#true() -> Logic {
Logic::True
}
pub fn r#false() -> Logic {
Logic::False
}
pub fn dont_care() -> Logic {
Logic::X
}
pub fn high_z() -> Logic {
Logic::Z
}