use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Status {
Live,
Dead,
Unknown,
Open,
}
impl Default for Status {
fn default() -> Self {
Status::Open
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum Transaction {
Add(usize, usize),
Close(usize),
Live(usize),
}
pub trait StateGraph {
fn new() -> Self
where
Self: Sized;
fn add_transition_unchecked(&mut self, v1: usize, v2: usize);
fn mark_closed_unchecked(&mut self, v: usize);
fn mark_live_unchecked(&mut self, v: usize);
fn get_status(&self, v: usize) -> Option<Status>;
fn get_space(&self) -> usize;
fn get_time(&self) -> usize;
fn add_transition(&mut self, v1: usize, v2: usize) {
debug_assert!(self.is_open(v1) || self.is_live(v1));
if self.is_open(v1) && v1 != v2 {
self.add_transition_unchecked(v1, v2);
}
}
fn mark_closed(&mut self, v: usize) {
debug_assert!(self.is_open(v) || self.is_live(v));
if self.is_open(v) {
self.mark_closed_unchecked(v);
}
}
fn mark_live(&mut self, v: usize) {
debug_assert!(self.is_open(v) || self.is_live(v));
if self.is_open(v) {
self.mark_live_unchecked(v);
}
}
fn is_seen(&self, v: usize) -> bool {
self.get_status(v).is_some()
}
fn is_live(&self, v: usize) -> bool {
self.get_status(v) == Some(Status::Live)
}
fn is_dead(&self, v: usize) -> bool {
self.get_status(v) == Some(Status::Dead)
}
fn is_unknown(&self, v: usize) -> bool {
self.get_status(v) == Some(Status::Unknown)
}
fn is_open(&self, v: usize) -> bool {
self.get_status(v).map_or(true, |st| st == Status::Open)
}
fn is_closed(&self, v: usize) -> bool {
!self.is_open(v)
}
fn is_live_bck(&self, v: usize) -> bool {
debug_assert!(self.is_seen(v));
debug_assert!(!self.is_dead(v));
self.is_live(v)
}
fn is_u_or_d(&self, v: usize) -> bool {
self.is_dead(v) || self.is_unknown(v)
}
fn process(&mut self, t: Transaction) {
match t {
Transaction::Add(v1, v2) => self.add_transition(v1, v2),
Transaction::Close(v1) => self.mark_closed(v1),
Transaction::Live(v1) => self.mark_live(v1),
}
}
}