Skip to main content

event_simulation/
multi.rs

1use std::{
2    borrow::{Borrow, BorrowMut},
3    ops::{Deref, DerefMut},
4};
5
6use crate::{Editable, EditableSimulationInfo, Simulation, SimulationInfo, SimulationState};
7
8/// A simulation with support for multiple states.
9pub struct MultiSimulation<Info: SimulationInfo> {
10    info: Info,
11    states: Vec<Info::State>,
12}
13
14impl<Info: SimulationInfo> MultiSimulation<Info> {
15    /// Creates a new `MultiSimulation` from the provided `info` with no states.
16    pub fn new<T: Into<Info>>(info: T) -> Self {
17        Self {
18            info: info.into(),
19            states: Vec::new(),
20        }
21    }
22
23    /// Adds a new simulation state to the simulation and returns its index.
24    pub fn add_simulation(&mut self) -> usize {
25        let index = self.states.len();
26        self.states.push(Info::default_state(&self.info));
27        index
28    }
29
30    /// Adds a new simulation state loaded from the provided `data` to the simulation and returns its index.
31    ///
32    /// # Errors
33    /// Returns an error if a valid state cannot be loaded from `data`.
34    pub fn add_simulation_from_data(
35        &mut self,
36        data: Info::LoadData,
37    ) -> Result<usize, Info::StateLoadingError> {
38        let index = self.states.len();
39        self.states.push(Info::load_state(&self.info, data)?);
40        Ok(index)
41    }
42
43    /// Removes the simulation state at the specified index and returns it.
44    ///
45    /// All states after `index` shift down by one position, so their indices
46    /// decrease by one. Returns `None` if `index` is out of bounds, leaving the
47    /// simulation unchanged.
48    pub fn remove_simulation(&mut self, index: usize) -> Option<Info::State> {
49        (index < self.states.len()).then(|| self.states.remove(index))
50    }
51
52    /// Retrieves an immutable borrow of the simulation at the specified index.
53    pub fn get(&self, index: usize) -> Option<SimulationBorrowRef<'_, Info>> {
54        let state = self.states.get(index)?;
55        Some(SimulationBorrowRef {
56            info: &self.info,
57            state,
58        })
59    }
60
61    /// Retrieves a mutable borrow of the simulation at the specified index.
62    pub fn get_mut(&mut self, index: usize) -> Option<SimulationBorrowMut<'_, Info>> {
63        let state = self.states.get_mut(index)?;
64        Some(SimulationBorrowMut {
65            info: &self.info,
66            state,
67        })
68    }
69
70    /// Get access to all simulation states.
71    pub fn states(&self) -> &[Info::State] {
72        &self.states
73    }
74
75    /// Get mutable access to all simulation states.
76    pub fn states_mut(&mut self) -> &mut [Info::State] {
77        &mut self.states
78    }
79
80    /// Returns an iterator over the simulation states.
81    pub fn iter(&self) -> Iter<'_, Info> {
82        self.into_iter()
83    }
84
85    /// Returns a mutable iterator over the simulation states.
86    pub fn iter_mut(&mut self) -> IterMut<'_, Info> {
87        self.into_iter()
88    }
89
90    /// Release the info from the simulation again and destroys all states.
91    pub fn release(self) -> Info {
92        self.info
93    }
94}
95
96impl<Info: SimulationInfo + Clone> Clone for MultiSimulation<Info> {
97    fn clone(&self) -> Self {
98        let info = self.info.clone();
99        let states = self
100            .states
101            .iter()
102            .map(|state| unsafe { info.clone_state(state) })
103            .collect();
104        Self { info, states }
105    }
106}
107
108impl<Info: SimulationInfo> Deref for MultiSimulation<Info> {
109    type Target = Info;
110
111    fn deref(&self) -> &Info {
112        &self.info
113    }
114}
115
116/// A generic struct representing a borrowed simulation with an immutable or mutable reference to the state.
117pub struct SimulationBorrow<'a, Info: SimulationInfo, StateRef> {
118    info: &'a Info,
119    /// The referenced simulation state.
120    pub state: StateRef,
121}
122
123impl<Info: SimulationInfo, S> Deref for SimulationBorrow<'_, Info, S> {
124    type Target = Info;
125
126    fn deref(&self) -> &Info {
127        self.info
128    }
129}
130
131impl<Info: SimulationInfo, S: Borrow<Info::State>> SimulationState
132    for SimulationBorrow<'_, Info, S>
133{
134    type AccessData = Info::AccessData;
135    type Event = Info::Event;
136    type EventContainer<'a>
137        = Info::EventContainer<'a>
138    where
139        Self: 'a;
140
141    #[inline]
142    fn data(&self) -> &Info::AccessData {
143        unsafe { self.info.data(self.state.borrow()) }
144    }
145
146    #[inline]
147    fn callables(&self) -> Info::EventContainer<'_> {
148        Info::callables(self.state.borrow())
149    }
150
151    #[inline]
152    fn callable(&self, event: Info::Event) -> bool {
153        Info::callable(self.state.borrow(), event)
154    }
155
156    #[inline]
157    fn revertables(&self) -> Info::EventContainer<'_> {
158        Info::revertables(self.state.borrow())
159    }
160
161    #[inline]
162    fn revertable(&self, event: Info::Event) -> bool {
163        Info::revertable(self.state.borrow(), event)
164    }
165}
166
167impl<Info: SimulationInfo, S: BorrowMut<Info::State>> Simulation for SimulationBorrow<'_, Info, S> {
168    type StateLoadingError = Info::StateLoadingError;
169    type LoadData = Info::LoadData;
170
171    #[inline]
172    fn reload(&mut self, data: Info::LoadData) -> Result<(), Info::StateLoadingError> {
173        *self.state.borrow_mut() = self.info.load_state(data)?;
174        Ok(())
175    }
176
177    #[inline]
178    unsafe fn call(&mut self, event: Info::Event) {
179        unsafe { self.info.call(self.state.borrow_mut(), event) }
180    }
181
182    #[inline]
183    unsafe fn revert(&mut self, event: Info::Event) {
184        unsafe { self.info.revert(self.state.borrow_mut(), event) }
185    }
186}
187
188/// Represents a single immutable simulation.
189pub type SimulationBorrowRef<'a, Info> =
190    SimulationBorrow<'a, Info, &'a <Info as SimulationInfo>::State>;
191
192/// Represents a single mutable simulation.
193pub type SimulationBorrowMut<'a, Info> =
194    SimulationBorrow<'a, Info, &'a mut <Info as SimulationInfo>::State>;
195
196/// An iterator over the simulation states.
197pub struct Iter<'a, Info: SimulationInfo> {
198    info: &'a Info,
199    states: std::slice::Iter<'a, Info::State>,
200}
201
202/// A mutable iterator over the simulation states.
203pub struct IterMut<'a, Info: SimulationInfo> {
204    info: &'a Info,
205    states: std::slice::IterMut<'a, Info::State>,
206}
207
208impl<'a, Info: SimulationInfo> IntoIterator for &'a MultiSimulation<Info> {
209    type Item = SimulationBorrowRef<'a, Info>;
210    type IntoIter = Iter<'a, Info>;
211
212    fn into_iter(self) -> Self::IntoIter {
213        Iter {
214            info: &self.info,
215            states: self.states.iter(),
216        }
217    }
218}
219
220impl<'a, Info: SimulationInfo> IntoIterator for &'a mut MultiSimulation<Info> {
221    type Item = SimulationBorrowMut<'a, Info>;
222    type IntoIter = IterMut<'a, Info>;
223
224    fn into_iter(self) -> Self::IntoIter {
225        IterMut {
226            info: &self.info,
227            states: self.states.iter_mut(),
228        }
229    }
230}
231
232impl<'a, Info: SimulationInfo> Iterator for Iter<'a, Info> {
233    type Item = SimulationBorrowRef<'a, Info>;
234
235    fn next(&mut self) -> Option<Self::Item> {
236        let state = self.states.next()?;
237        Some(SimulationBorrowRef {
238            info: self.info,
239            state,
240        })
241    }
242
243    fn size_hint(&self) -> (usize, Option<usize>) {
244        self.states.size_hint()
245    }
246}
247
248impl<Info: SimulationInfo> ExactSizeIterator for Iter<'_, Info> {}
249
250impl<'a, Info: SimulationInfo> Iterator for IterMut<'a, Info> {
251    type Item = SimulationBorrowMut<'a, Info>;
252
253    fn next(&mut self) -> Option<Self::Item> {
254        let state = self.states.next()?;
255        Some(SimulationBorrowMut {
256            info: self.info,
257            state,
258        })
259    }
260
261    fn size_hint(&self) -> (usize, Option<usize>) {
262        self.states.size_hint()
263    }
264}
265
266impl<Info: SimulationInfo> ExactSizeIterator for IterMut<'_, Info> {}
267
268impl<Info: EditableSimulationInfo> Editable for MultiSimulation<Info> {
269    type Edit<'a>
270        = MultiSimulationEdit<'a, Info>
271    where
272        Self: 'a;
273
274    fn edit(&mut self) -> MultiSimulationEdit<'_, Info> {
275        let edit = unsafe { self.info.edit() };
276        MultiSimulationEdit {
277            edit,
278            states: &mut self.states,
279        }
280    }
281}
282
283/// Helper type for safely editing the info of a multi simulation without invalidating the state.
284pub struct MultiSimulationEdit<'a, Info: EditableSimulationInfo + 'a> {
285    edit: Info::Edit<'a>,
286    states: &'a mut [Info::State],
287}
288
289impl<Info: EditableSimulationInfo> Drop for MultiSimulationEdit<'_, Info> {
290    fn drop(&mut self) {
291        for state in self.states.iter_mut() {
292            unsafe { self.edit.refresh_state(state) }
293        }
294    }
295}
296
297impl<'a, Info: EditableSimulationInfo> Deref for MultiSimulationEdit<'a, Info> {
298    type Target = Info::Edit<'a>;
299    fn deref(&self) -> &Info::Edit<'a> {
300        &self.edit
301    }
302}
303
304impl<'a, Info: EditableSimulationInfo> DerefMut for MultiSimulationEdit<'a, Info> {
305    fn deref_mut(&mut self) -> &mut Info::Edit<'a> {
306        &mut self.edit
307    }
308}