use std::{fmt::Display, ops::BitOr};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(u8)]
pub(crate) enum StateAttribute {
Accepting = 0x01,
Rejecting = 0x02,
Unitary = 0x04,
TransitionsToAccepting = 0x08,
HasArrayTransition = 0x10,
HasArrayTransitionToAccepting = 0x20,
}
pub(crate) struct StateAttributesBuilder {
attrs: StateAttributes,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub struct StateAttributes(u8);
impl StateAttributesBuilder {
pub(crate) fn new() -> Self {
Self {
attrs: StateAttributes(0),
}
}
pub(crate) fn accepting(self) -> Self {
self.set(StateAttribute::Accepting)
}
pub(crate) fn rejecting(self) -> Self {
self.set(StateAttribute::Rejecting)
}
pub(crate) fn unitary(self) -> Self {
self.set(StateAttribute::Unitary)
}
pub(crate) fn transitions_to_accepting(self) -> Self {
self.set(StateAttribute::TransitionsToAccepting)
}
pub(crate) fn has_array_transition(self) -> Self {
self.set(StateAttribute::HasArrayTransition)
}
pub(crate) fn has_array_transition_to_accepting(self) -> Self {
self.set(StateAttribute::HasArrayTransitionToAccepting)
}
pub(crate) fn build(self) -> StateAttributes {
self.attrs
}
fn set(self, attr: StateAttribute) -> Self {
Self {
attrs: StateAttributes(self.attrs.0 | attr as u8),
}
}
}
impl From<StateAttributesBuilder> for StateAttributes {
#[inline(always)]
fn from(value: StateAttributesBuilder) -> Self {
value.build()
}
}
impl BitOr for StateAttributes {
type Output = Self;
#[inline(always)]
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl StateAttributes {
pub const ACCEPTING: Self = Self(StateAttribute::Accepting as u8);
pub const EMPTY: Self = Self(0);
pub const REJECTING: Self = Self(StateAttribute::Rejecting as u8);
pub const TRANSITIONS_TO_ACCEPTING: Self = Self(StateAttribute::TransitionsToAccepting as u8);
pub const UNITARY: Self = Self(StateAttribute::Unitary as u8);
pub const HAS_ARRAY_TRANSITION: Self = Self(StateAttribute::HasArrayTransition as u8);
pub const HAS_ARRAY_TRANSITION_TO_ACCEPTING: Self = Self(StateAttribute::HasArrayTransitionToAccepting as u8);
#[inline(always)]
#[must_use]
pub fn is_accepting(&self) -> bool {
self.is_set(StateAttribute::Accepting)
}
#[inline(always)]
#[must_use]
pub fn is_rejecting(&self) -> bool {
self.is_set(StateAttribute::Rejecting)
}
#[inline(always)]
#[must_use]
pub fn has_transition_to_accepting(&self) -> bool {
self.is_set(StateAttribute::TransitionsToAccepting)
}
#[inline(always)]
#[must_use]
pub fn is_unitary(&self) -> bool {
self.is_set(StateAttribute::Unitary)
}
#[inline(always)]
#[must_use]
pub fn has_array_transition(&self) -> bool {
self.is_set(StateAttribute::HasArrayTransition)
}
#[inline(always)]
#[must_use]
pub fn has_array_transition_to_accepting(&self) -> bool {
self.is_set(StateAttribute::HasArrayTransitionToAccepting)
}
#[inline(always)]
#[must_use]
fn is_set(&self, attr: StateAttribute) -> bool {
(self.0 & attr as u8) != 0
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct State(
pub(super) u8,
);
impl Display for State {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "DFA({})", self.0)
}
}