clt_database/
state_machine.rs1use crate::{
2 types::{IOCompletions, IOResult},
3 Result,
4};
5
6pub enum TransitionResult<Result> {
7 Io(IOCompletions),
8 Continue,
9 Done(Result),
10}
11
12pub trait StateTransition {
14 type Context;
15 type SMResult;
16
17 fn step(&mut self, context: &Self::Context) -> Result<TransitionResult<Self::SMResult>>;
23
24 fn finalize(&mut self, context: &Self::Context) -> Result<()>;
28
29 fn is_finalized(&self) -> bool;
31}
32
33#[derive(Debug)]
34pub struct StateMachine<State: StateTransition> {
35 state: State,
36 is_finalized: bool,
37}
38
39impl<State: StateTransition> StateTransition for Box<State> {
40 type Context = State::Context;
41 type SMResult = State::SMResult;
42
43 fn step(&mut self, context: &Self::Context) -> Result<TransitionResult<Self::SMResult>> {
44 self.as_mut().step(context)
45 }
46
47 fn finalize(&mut self, context: &Self::Context) -> Result<()> {
48 self.as_mut().finalize(context)
49 }
50
51 fn is_finalized(&self) -> bool {
52 self.as_ref().is_finalized()
53 }
54}
55
56impl<State: StateTransition> StateMachine<State> {
58 pub fn new(state: State) -> Self {
59 Self {
60 state,
61 is_finalized: false,
62 }
63 }
64
65 pub fn step(&mut self, context: &State::Context) -> Result<IOResult<State::SMResult>> {
66 loop {
67 if self.is_finalized {
68 unreachable!("StateMachine::transition: state machine is finalized");
69 }
70 match self.state.step(context)? {
71 TransitionResult::Io(io) => {
72 return Ok(IOResult::IO(io));
73 }
74 TransitionResult::Continue => {
75 continue;
76 }
77 TransitionResult::Done(result) => {
78 assert!(self.state.is_finalized());
79 self.is_finalized = true;
80 return Ok(IOResult::Done(result));
81 }
82 }
83 }
84 }
85
86 pub fn finalize(&mut self, context: &State::Context) -> Result<()> {
87 self.state.finalize(context)?;
88 self.is_finalized = true;
89 Ok(())
90 }
91
92 pub(crate) fn inner_mut(&mut self) -> &mut State {
93 &mut self.state
94 }
95
96 pub fn is_finalized(&self) -> bool {
97 self.is_finalized
98 }
99}