use crate::completeness::Completeness;
use crate::{Label, Scope, ScopeGraph};
use std::cell::RefCell;
use std::{collections::HashSet, hash::Hash};
#[derive(Debug)]
pub(crate) struct CriticalEdgeSet<LABEL> {
open_edges: RefCell<Vec<HashSet<LABEL>>>,
}
impl<LABEL> Default for CriticalEdgeSet<LABEL> {
fn default() -> Self {
Self {
open_edges: Default::default(),
}
}
}
impl<LABEL> CriticalEdgeSet<LABEL> {
pub fn init_scope(&self, edges: HashSet<LABEL>) {
self.open_edges.borrow_mut().push(edges)
}
}
impl<LABEL: Hash + Eq> CriticalEdgeSet<LABEL> {
pub fn is_open(&self, scope: Scope, lbl: &LABEL) -> bool {
self.open_edges.borrow()[scope.0].contains(lbl)
}
pub fn close(&self, scope: Scope, lbl: &LABEL) -> bool {
self.open_edges.borrow_mut()[scope.0].remove(lbl)
}
}
pub trait CriticalEdgeBasedCompleteness<LABEL: Label, DATA>: Completeness<LABEL, DATA> {
fn init_scope_with(&self, open_edges: HashSet<LABEL>);
}
#[derive(Debug)]
pub struct EdgeClosedError<LABEL> {
pub scope: Scope,
pub label: LABEL,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Delay<LABEL> {
pub scope: Scope,
pub label: LABEL,
}
pub type EdgesOrDelay<EDGES, LABEL> = Result<EDGES, Delay<LABEL>>;
impl<LABEL: Hash + Label, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
CMPL: CriticalEdgeBasedCompleteness<LABEL, DATA>,
{
pub fn add_scope_with<I>(&self, data: DATA, open_edges: I) -> Scope
where
I: IntoIterator<Item = LABEL>,
{
let scope = self.inner_scope_graph.add_scope(data);
self.completeness
.init_scope_with(open_edges.into_iter().collect());
scope
}
pub fn add_scope_closed(&self, data: DATA) -> Scope {
let scope = self.inner_scope_graph.add_scope(data);
self.completeness.init_scope_with(HashSet::new());
scope
}
}
impl<LABEL: Hash + Label, DATA, CMPL> ScopeGraph<'_, LABEL, DATA, CMPL>
where
DATA: Default,
CMPL: CriticalEdgeBasedCompleteness<LABEL, DATA>,
{
pub fn add_scope_default_with<I>(&self, open_edges: I) -> Scope
where
I: IntoIterator<Item = LABEL>,
{
self.add_scope_with(DATA::default(), open_edges)
}
pub fn add_scope_default_closed(&self) -> Scope {
self.add_scope_with(DATA::default(), HashSet::new())
}
}