1use alloc::{boxed::Box, sync::Arc};
4use core::{
5 any::Any,
6 marker::{Send, Sync},
7};
8
9use crate::rtos::{Context, ContextWrapper, Mutex, Promise};
10
11pub trait StateMachine {
13 type State;
15
16 fn state(&self) -> Self::State;
18
19 fn transition(&self, state: Self::State) -> Context;
23}
24
25pub struct StateMachineData<S: Clone> {
28 state: S,
29 listener: ListenerBox,
30 ctxw: ContextWrapper,
31}
32
33impl<S: Clone> StateMachineData<S> {
34 pub fn new_wrapped(state: S) -> StateMachineHandle<S> {
36 Arc::new(Mutex::new(Self {
37 state,
38 listener: ListenerBox(None),
39 ctxw: ContextWrapper::new(),
40 }))
41 }
42
43 pub fn state(&self) -> &S {
45 &self.state
46 }
47
48 pub fn begin(&mut self) -> (S, Context) {
52 (
53 self.state.clone(),
54 if let Some(ctx) = self.ctxw.current() {
55 ctx.clone()
56 } else {
57 self.ctxw.replace()
58 },
59 )
60 }
61
62 pub fn transition(&mut self, state: S) -> Context {
66 self.state = state;
67 self.listener.clear();
68 self.ctxw.replace()
69 }
70
71 pub fn transition_ext(&mut self, ctx: Context, state: S) -> Context {
74 self.state = state;
75 self.listener.clear();
76 self.ctxw.replace_ext(ctx)
77 }
78
79 pub fn listen<T: Send + Sync>(&mut self) -> Promise<T> {
84 self.listener.listen::<T>()
85 }
86
87 pub fn resolve<T: 'static>(&mut self, result: T) {
89 self.listener.resolve::<T>(result);
90 }
91}
92
93pub type StateMachineHandle<S> = Arc<Mutex<StateMachineData<S>>>;
95
96struct ListenerBox(Option<Box<dyn Any + Send>>);
97
98impl ListenerBox {
99 fn clear(&mut self) {
100 self.0.take();
101 }
102
103 fn listen<T: Send + Sync>(&mut self) -> Promise<T> {
104 if self.0.is_some() {
105 panic!("cannot override listener")
106 }
107
108 let (promise, resolve) = Promise::new();
109 let mut resolve = Some(resolve);
110 let f = move |result| {
111 if let Some(resolve) = resolve.take() {
112 resolve(result);
113 }
114 };
115
116 let inner_box: Box<dyn FnMut(T) + Send> = Box::new(f);
117 let outer_box: Box<dyn Any + Send> = Box::new(inner_box);
118 self.0 = Some(outer_box);
119
120 promise
121 }
122
123 fn resolve<T: 'static>(&mut self, result: T) {
124 if let Some(mut boxed) = self.0.take() {
125 if let Some(resolve) = boxed.downcast_mut::<Box<dyn FnMut(T) + Send>>() {
126 resolve(result)
127 }
128 }
129 }
130}
131
132#[non_exhaustive]
137#[derive(Clone, Copy, Debug, PartialEq, Eq)]
138pub enum StateResult<T, S> {
139 Simple(T),
142 Transition(T, S),
145}
146
147impl<T, S> StateResult<T, S> {
148 pub fn into_tuple(self) -> (T, Option<S>) {
150 match self {
151 StateResult::Simple(result) => (result, None),
152 StateResult::Transition(result, next) => (result, Some(next)),
153 }
154 }
155}