bubbles/runtime/runner/session.rs
1use super::{Runner, State};
2use crate::error::Result;
3
4impl<S: crate::value::VariableStorage> Runner<S> {
5 /// Captures the current session state into a [`RunnerSnapshot`](crate::RunnerSnapshot).
6 ///
7 /// The snapshot records the active node title, visit counts, and the set of
8 /// exhausted `<<once>>` blocks. Variable storage is **not** included; persist
9 /// it via [`Runner::storage`] alongside the snapshot when saving.
10 ///
11 /// Restoring with [`Runner::restore`] will restart execution from the beginning
12 /// of the snapshotted node.
13 ///
14 /// Enable the `serde` feature on `bubbles-dialogue` if you need `Serialize` /
15 /// `Deserialize` on [`RunnerSnapshot`](crate::RunnerSnapshot).
16 #[must_use]
17 pub fn snapshot(&self) -> crate::runtime::RunnerSnapshot {
18 crate::runtime::RunnerSnapshot {
19 current_node: self.stack.last().map(|f| f.node.as_ref().to_owned()),
20 visits: self.visits.clone(),
21 once_seen: self.once_seen.clone(),
22 }
23 }
24
25 /// Applies a previously captured `RunnerSnapshot`, restoring visit counts
26 /// and the `<<once>>` exhaustion set, then re-enters the snapshotted node
27 /// from its beginning.
28 ///
29 /// # Errors
30 ///
31 /// Returns [`crate::DialogueError::UnknownNode`] if the snapshotted node no longer
32 /// exists in the program (e.g. after a script update).
33 pub fn restore(&mut self, snapshot: crate::runtime::RunnerSnapshot) -> Result<()> {
34 self.visits = snapshot.visits;
35 self.once_seen = snapshot.once_seen;
36 self.stack.clear();
37 self.clear_event_queues();
38 self.state = State::Idle;
39 if let Some(node) = snapshot.current_node {
40 self.start(&node)?;
41 }
42 Ok(())
43 }
44}