event-simulation 0.2.0

A library for event based simulation of application state
Documentation
use std::{
    borrow::{Borrow, BorrowMut},
    ops::{Deref, DerefMut},
};

use crate::{Editable, EditableSimulationInfo, Simulation, SimulationInfo, SimulationState};

/// A simulation with support for multiple states.
pub struct MultiSimulation<Info: SimulationInfo> {
    info: Info,
    states: Vec<Info::State>,
}

impl<Info: SimulationInfo> MultiSimulation<Info> {
    /// Creates a new `MultiSimulation` from the provided `info` with no states.
    pub fn new<T: Into<Info>>(info: T) -> Self {
        Self {
            info: info.into(),
            states: Vec::new(),
        }
    }

    /// Adds a new simulation state to the simulation and returns its index.
    pub fn add_simulation(&mut self) -> usize {
        let index = self.states.len();
        self.states.push(Info::default_state(&self.info));
        index
    }

    /// Adds a new simulation state loaded from the provided `data` to the simulation and returns its index.
    pub fn add_simulation_from_data(
        &mut self,
        data: Info::LoadData,
    ) -> Result<usize, Info::StateLoadingError> {
        let index = self.states.len();
        self.states.push(Info::load_state(&self.info, data)?);
        Ok(index)
    }

    /// Retrieves an immutable borrow of the simulation at the specified index.
    pub fn get(&self, index: usize) -> Option<SimulationBorrowRef<'_, Info>> {
        let state = self.states.get(index)?;
        Some(SimulationBorrowRef {
            info: &self.info,
            state,
        })
    }

    /// Retrieves a mutable borrow of the simulation at the specified index.
    pub fn get_mut(&mut self, index: usize) -> Option<SimulationBorrowMut<'_, Info>> {
        let state = self.states.get_mut(index)?;
        Some(SimulationBorrowMut {
            info: &self.info,
            state,
        })
    }

    /// Get access to all simulation states.
    pub fn states(&self) -> &[Info::State] {
        &self.states
    }

    /// Get mutable access to all simulation states.
    pub fn states_mut(&mut self) -> &mut [Info::State] {
        &mut self.states
    }

    /// Returns an iterator over the simulation states.
    pub fn iter(&self) -> Iter<'_, Info> {
        self.into_iter()
    }

    /// Returns a mutable iterator over the simulation states.
    pub fn iter_mut(&mut self) -> IterMut<'_, Info> {
        self.into_iter()
    }

    /// Release the info from the simulation again and destroys all states.
    pub fn release(self) -> Info {
        self.info
    }
}

impl<Info: SimulationInfo + Clone> Clone for MultiSimulation<Info> {
    fn clone(&self) -> Self {
        let info = self.info.clone();
        let states = self
            .states
            .iter()
            .map(|state| unsafe { info.clone_state(state) })
            .collect();
        Self { info, states }
    }
}

impl<Info: SimulationInfo> Deref for MultiSimulation<Info> {
    type Target = Info;

    fn deref(&self) -> &Info {
        &self.info
    }
}

/// A generic struct representing a borrowed simulation with an immutable or mutable reference to the state.
pub struct SimulationBorrow<'a, Info: SimulationInfo, StateRef> {
    info: &'a Info,
    /// The referenced simulation state.
    pub state: StateRef,
}

impl<Info: SimulationInfo, S> Deref for SimulationBorrow<'_, Info, S> {
    type Target = Info;

    fn deref(&self) -> &Info {
        self.info
    }
}

impl<Info: SimulationInfo, S: Borrow<Info::State>> SimulationState
    for SimulationBorrow<'_, Info, S>
{
    type AccessData = Info::AccessData;
    type Event = Info::Event;
    type EventContainer<'a>
        = Info::EventContainer<'a>
    where
        Self: 'a;

    #[inline]
    fn data(&self) -> &Info::AccessData {
        unsafe { self.info.data(self.state.borrow()) }
    }

    #[inline]
    fn callables(&self) -> Info::EventContainer<'_> {
        Info::callables(self.state.borrow())
    }

    #[inline]
    fn callable(&self, event: Info::Event) -> bool {
        Info::callable(self.state.borrow(), event)
    }

    #[inline]
    fn revertables(&self) -> Info::EventContainer<'_> {
        Info::revertables(self.state.borrow())
    }

    #[inline]
    fn revertable(&self, event: Info::Event) -> bool {
        Info::revertable(self.state.borrow(), event)
    }
}

impl<Info: SimulationInfo, S: BorrowMut<Info::State>> Simulation for SimulationBorrow<'_, Info, S> {
    type StateLoadingError = Info::StateLoadingError;
    type LoadData = Info::LoadData;

    #[inline]
    fn reload(&mut self, data: Info::LoadData) -> Result<(), Info::StateLoadingError> {
        *self.state.borrow_mut() = self.info.load_state(data)?;
        Ok(())
    }

    #[inline]
    unsafe fn call(&mut self, event: Info::Event) {
        unsafe { self.info.call(self.state.borrow_mut(), event) }
    }

    #[inline]
    unsafe fn revert(&mut self, event: Info::Event) {
        unsafe { self.info.revert(self.state.borrow_mut(), event) }
    }
}

/// Represents a single immutable simulation.
pub type SimulationBorrowRef<'a, Info> =
    SimulationBorrow<'a, Info, &'a <Info as SimulationInfo>::State>;

/// Represents a single mutable simulation.
pub type SimulationBorrowMut<'a, Info> =
    SimulationBorrow<'a, Info, &'a mut <Info as SimulationInfo>::State>;

/// An iterator over the simulation states.
pub struct Iter<'a, Info: SimulationInfo> {
    info: &'a Info,
    states: std::slice::Iter<'a, Info::State>,
}

/// A mutable iterator over the simulation states.
pub struct IterMut<'a, Info: SimulationInfo> {
    info: &'a Info,
    states: std::slice::IterMut<'a, Info::State>,
}

impl<'a, Info: SimulationInfo> IntoIterator for &'a MultiSimulation<Info> {
    type Item = SimulationBorrowRef<'a, Info>;
    type IntoIter = Iter<'a, Info>;

    fn into_iter(self) -> Self::IntoIter {
        Iter {
            info: &self.info,
            states: self.states.iter(),
        }
    }
}

impl<'a, Info: SimulationInfo> IntoIterator for &'a mut MultiSimulation<Info> {
    type Item = SimulationBorrowMut<'a, Info>;
    type IntoIter = IterMut<'a, Info>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            info: &self.info,
            states: self.states.iter_mut(),
        }
    }
}

impl<'a, Info: SimulationInfo> Iterator for Iter<'a, Info> {
    type Item = SimulationBorrowRef<'a, Info>;

    fn next(&mut self) -> Option<Self::Item> {
        let state = self.states.next()?;
        Some(SimulationBorrowRef {
            info: self.info,
            state,
        })
    }
}

impl<'a, Info: SimulationInfo> Iterator for IterMut<'a, Info> {
    type Item = SimulationBorrowMut<'a, Info>;

    fn next(&mut self) -> Option<Self::Item> {
        let state = self.states.next()?;
        Some(SimulationBorrowMut {
            info: self.info,
            state,
        })
    }
}

impl<Info: EditableSimulationInfo> Editable for MultiSimulation<Info> {
    type Edit<'a>
        = MultiSimulationEdit<'a, Info>
    where
        Self: 'a;

    fn edit(&mut self) -> MultiSimulationEdit<'_, Info> {
        let edit = unsafe { self.info.edit() };
        MultiSimulationEdit {
            edit,
            states: &mut self.states,
        }
    }
}

/// Helper type for safely editing the info of a multi simulation without invalidating the state.
pub struct MultiSimulationEdit<'a, Info: EditableSimulationInfo + 'a> {
    edit: Info::Edit<'a>,
    states: &'a mut [Info::State],
}

impl<Info: EditableSimulationInfo> Drop for MultiSimulationEdit<'_, Info> {
    fn drop(&mut self) {
        for state in self.states.iter_mut() {
            unsafe { self.edit.refresh_state(state) }
        }
    }
}

impl<'a, Info: EditableSimulationInfo> Deref for MultiSimulationEdit<'a, Info> {
    type Target = Info::Edit<'a>;
    fn deref(&self) -> &Info::Edit<'a> {
        &self.edit
    }
}

impl<'a, Info: EditableSimulationInfo> DerefMut for MultiSimulationEdit<'a, Info> {
    fn deref_mut(&mut self) -> &mut Info::Edit<'a> {
        &mut self.edit
    }
}