use std::ops::{Deref, DerefMut};
use event_simulation::Editable;
use pns::{Net, Pid, Tid};
use crate::{EditNet, PetriNetInfo};
pub enum DynamicNet<E: Editable> {
Default(PetriNetInfo),
Simulated(E),
}
macro_rules! dynamic {
($type:ident, $value:ident, $net:pat, $e:expr) => {
match $value {
$type::Default($net) => $e,
$type::Simulated($net) => $e,
}
};
}
impl<E: Editable> DynamicNet<E> {
pub fn default(&self) -> Option<&Net> {
if let Self::Default(net) = self {
Some(net)
} else {
None
}
}
pub fn default_mut(&mut self) -> Option<&mut Net> {
if let Self::Default(net) = self {
Some(net)
} else {
None
}
}
pub fn simulated(&self) -> Option<&E> {
if let Self::Simulated(net) = self {
Some(net)
} else {
None
}
}
pub fn simulated_mut(&mut self) -> Option<&mut E> {
if let Self::Simulated(net) = self {
Some(net)
} else {
None
}
}
}
impl<'a, E: Editable + 'a> DynamicNet<E>
where
E::Edit<'a>: Deref<Target = EditNet<'a>> + 'a,
{
pub fn edit(&'a mut self) -> DynamicNetEdit<E::Edit<'a>> {
match self {
Self::Default(net) => DynamicNetEdit::Default(net),
Self::Simulated(net) => DynamicNetEdit::Simulated(net.edit()),
}
}
}
impl<E: Editable + Deref<Target = PetriNetInfo>> Deref for DynamicNet<E> {
type Target = PetriNetInfo;
fn deref(&self) -> &PetriNetInfo {
dynamic!(Self, self, net, net)
}
}
impl<E: Editable> From<Net> for DynamicNet<E> {
fn from(net: Net) -> Self {
Self::Default(net.into())
}
}
pub enum DynamicNetEdit<'a, Edit: Deref<Target = EditNet<'a>> + 'a> {
Default(&'a mut Net),
Simulated(Edit),
}
impl<'a, Edit: Deref<Target = EditNet<'a>> + 'a> Deref for DynamicNetEdit<'a, Edit> {
type Target = Net;
fn deref(&self) -> &Net {
dynamic!(Self, self, net, net)
}
}
impl<'a, Edit: DerefMut<Target = EditNet<'a>> + 'a> DynamicNetEdit<'a, Edit> {
#[inline]
pub fn add_place(&mut self) -> Pid {
dynamic!(Self, self, net, net.add_place())
}
#[inline]
pub fn add_transition(&mut self) -> Tid {
dynamic!(Self, self, net, net.add_transition())
}
#[inline]
pub fn add_connected_transition(&mut self, in_pids: &[Pid], out_pids: &[Pid]) -> Tid {
dynamic!(
Self,
self,
net,
net.add_connected_transition(in_pids, out_pids)
)
}
#[inline]
pub fn remove_place(&mut self, pid: Pid) {
dynamic!(Self, self, net, net.remove_place(pid));
}
#[inline]
pub fn connect_place_to_transition(&mut self, pid: Pid, tid: Tid) -> bool {
dynamic!(Self, self, net, net.connect_place_to_transition(pid, tid))
}
#[inline]
pub fn connect_transition_to_place(&mut self, tid: Tid, pid: Pid) -> bool {
dynamic!(Self, self, net, net.connect_transition_to_place(tid, pid))
}
#[inline]
pub fn duplicate_transition(&mut self, tid: Tid) -> Tid {
dynamic!(Self, self, net, net.duplicate_transition(tid))
}
#[inline]
pub fn duplicate_place(&mut self, pid: Pid) -> Pid {
dynamic!(Self, self, net, net.duplicate_place(pid))
}
#[inline]
pub fn add_initial_tokens(&mut self, pid: Pid, count: usize) -> usize {
dynamic!(Self, self, net, net.add_initial_tokens(pid, count))
}
}