use std::ops::{Deref, DerefMut};
use event_simulation::{DynamicSimulation, Editable};
use pns::{Pid, Tid};
use crate::{EditNet, PetriNetInfo};
pub type DynamicNet<E> = DynamicSimulation<PetriNetInfo, E>;
macro_rules! dynamic {
($type:ident, $value:ident, $net:pat, $e:expr) => {
match $value {
$type::Default($net) => $e,
$type::Simulated($net) => $e,
}
};
}
pub enum DynamicNetEdit<'a, Edit: Deref<Target = EditNet<'a>> + 'a> {
Default(&'a mut PetriNetInfo),
Simulated(Edit),
}
impl<'a, Edit: Deref<Target = EditNet<'a>> + 'a> Deref for DynamicNetEdit<'a, Edit> {
type Target = PetriNetInfo;
fn deref(&self) -> &PetriNetInfo {
dynamic!(Self, self, net, net)
}
}
impl<'a, Edit: DerefMut<Target = EditNet<'a>> + 'a> DynamicNetEdit<'a, Edit> {
pub fn new<E: Editable<Edit<'a> = Edit>>(net: &'a mut DynamicNet<E>) -> Self {
use DynamicSimulation::*;
match net {
Default(net) => Self::Default(net),
Simulated(net) => Self::Simulated(net.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))
}
}