#![deny(missing_docs)]
use std::ops::Deref;
pub trait SimulationState {
type AccessData: ?Sized;
type Event: Copy + Ord;
type EventContainer<'a>: Iterator<Item = Self::Event>
where
Self: 'a;
fn data(&self) -> &Self::AccessData;
fn callables(&self) -> Self::EventContainer<'_>;
fn revertables(&self) -> Self::EventContainer<'_>;
fn callable(&self, event: Self::Event) -> bool;
fn revertable(&self, event: Self::Event) -> bool;
}
pub trait Simulation: SimulationState {
type LoadData;
type StateLoadingError;
fn reload(&mut self, data: Self::LoadData) -> Result<(), Self::StateLoadingError>;
unsafe fn call(&mut self, event: Self::Event);
unsafe fn revert(&mut self, event: Self::Event);
fn try_call(&mut self, event: Self::Event) -> bool {
if !self.callable(event) {
return false;
}
unsafe { self.call(event) }
true
}
fn try_revert(&mut self, event: Self::Event) -> bool {
if !self.revertable(event) {
return false;
}
unsafe { self.revert(event) }
true
}
fn prepare_call(&mut self) -> CallState<'_, Self, Call> {
let callables = self.callables().collect();
CallState {
simulation: self,
callables,
direction: Call,
}
}
fn prepare_revert(&mut self) -> CallState<'_, Self, Revert> {
let callables = self.revertables().collect();
CallState {
simulation: self,
callables,
direction: Revert,
}
}
}
pub trait PlayDirection {
unsafe fn call<S: Simulation>(&self, simulation: &mut S, event: S::Event);
}
pub struct Call;
impl PlayDirection for Call {
unsafe fn call<S: Simulation>(&self, simulation: &mut S, event: S::Event) {
unsafe { simulation.call(event) }
}
}
pub struct Revert;
impl PlayDirection for Revert {
unsafe fn call<S: Simulation>(&self, simulation: &mut S, event: S::Event) {
unsafe { simulation.revert(event) }
}
}
pub struct CallState<'a, S: Simulation + ?Sized, D: PlayDirection> {
simulation: &'a mut S,
pub callables: Box<[S::Event]>,
direction: D,
}
impl<S: Simulation, D: PlayDirection> CallState<'_, S, D> {
pub fn call(self, index: usize) {
let event = self.callables[index];
unsafe { self.direction.call(self.simulation, event) }
}
pub fn try_call(self, index: usize) -> bool {
let Some(&event) = self.callables.get(index) else {
return false;
};
unsafe { self.direction.call(self.simulation, event) }
true
}
}
pub trait SimulationInfo {
type State;
type StateLoadingError;
type AccessData: ?Sized;
type LoadData;
type Event: Copy + Ord;
type EventContainer<'a>: Iterator<Item = Self::Event>
where
Self: 'a;
fn default_state(&self) -> Self::State;
fn load_state(&self, data: Self::LoadData) -> Result<Self::State, Self::StateLoadingError>;
unsafe fn clone_state(&self, state: &Self::State) -> Self::State;
unsafe fn data<'a>(&self, state: &'a Self::State) -> &'a Self::AccessData;
fn callables(state: &Self::State) -> Self::EventContainer<'_>;
fn revertables(state: &Self::State) -> Self::EventContainer<'_>;
fn callable(state: &Self::State, event: Self::Event) -> bool;
fn revertable(state: &Self::State, event: Self::Event) -> bool;
unsafe fn call(&self, state: &mut Self::State, event: Self::Event);
unsafe fn revert(&self, state: &mut Self::State, event: Self::Event);
}
pub trait EditableSimulationInfo: SimulationInfo {
type Edit<'a>: Deref<Target = Self>
where
Self: 'a;
unsafe fn edit(&mut self) -> Self::Edit<'_>;
unsafe fn refresh_state(&self, state: &mut Self::State);
}
pub trait Editable {
type Edit<'a>
where
Self: 'a;
fn edit(&mut self) -> Self::Edit<'_>;
}
mod borrowed;
mod multi;
mod owned;
pub use borrowed::BorrowedSimulation;
pub use multi::{
MultiSimulation, MultiSimulationEdit, SimulationBorrow, SimulationBorrowMut,
SimulationBorrowRef,
};
pub use owned::{OwnedSimulation, OwnedSimulationEdit};
mod dynamic;
pub use dynamic::DynamicSimulation;