automata_like_programming/simple_impl/
simple_state.rs1use std::{cell::RefCell, marker::PhantomData, rc::Rc};
2
3use crate::automaton_state::{convert_to_dyn_reference, AutomatonState, SharedAutomatonState};
4
5pub type SharedSimpleState<'a, K, Id, D, E> = Rc<RefCell<SimpleStateImplementation<'a, K, Id, D, E>>>;
6
7pub trait KeyProvidingData<K> {
10 fn next_key(&mut self) -> Option<K>;
11}
12
13pub struct SimpleInterStateConnection<'a, K, Id, D, E> where Id: Copy + 'a, K: 'a, D: 'a, E: 'a {
24 matcher: Box<dyn Fn(&K) -> bool + 'a>,
25 exec_function: Box<dyn Fn(&mut D, &K) -> Result<(), E> + 'a>,
26 connected_state: SharedAutomatonState<'a, Id, D, E>,
27}
28
29impl <'a, K, Id, D, E> SimpleInterStateConnection<'a, K, Id, D, E> where Id: Copy {
30 pub fn new<M: Fn(&K) -> bool + 'a, FExec: Fn(&mut D, &K) -> Result<(), E> + 'a, S: AutomatonState<'a, Id, D, E> + 'a>(matcher: M, exec_function: FExec, next_state: &Rc<RefCell<S>>) -> Self {
32 Self { matcher: Box::new(matcher), exec_function: Box::new(exec_function), connected_state: convert_to_dyn_reference(Rc::clone(next_state)) }
33 }
34
35 pub fn new_no_action<M: Fn(&K) -> bool + 'a, S: AutomatonState<'a, Id, D, E> + 'a>(matcher: M, next_state: &Rc<RefCell<S>>) -> Self {
37 Self::new(matcher, Self::do_nothing, next_state)
38 }
39
40 pub fn new_always_matched<S: AutomatonState<'a, Id, D, E> + 'a, FExec: Fn(&mut D, &K) -> Result<(), E> + 'a>(exec_function: FExec, next_state: &Rc<RefCell<S>>) -> Self {
42 Self::new(Self::always_match, exec_function, next_state)
43 }
44
45 pub fn new_no_action_always_matched<S: AutomatonState<'a, Id, D, E> + 'a>(next_state: &Rc<RefCell<S>>) -> Self {
47 Self::new_always_matched(Self::do_nothing,next_state)
48 }
49
50 fn always_match(_: &K) -> bool {
52 true
53 }
54
55 fn do_nothing(_:&mut D, _:&K) -> Result<(), E> {
57 Result::Ok(())
58 }
59}
60
61pub struct SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy{
66 _phantom: PhantomData<D>,
67 id: Id,
68 next_states: Vec<SimpleInterStateConnection<'a, K, Id, D, E>>,
69}
70
71impl <'a, K, Id, D, E> SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy {
72 pub fn new(id: Id) -> Self {
76 Self { _phantom: PhantomData{}, next_states: Vec::new(), id}
77 }
78
79 pub fn register_connection(&mut self, connection: SimpleInterStateConnection<'a, K, Id, D, E>) -> ()
81 {
82 self.next_states.push(connection);
83 }
84}
85
86impl<'a, K, Id, D, E> AutomatonState<'a, Id, D, E> for SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy {
87 fn get_id_owned(&self) -> Id {
89 self.id
90 }
91
92 fn get_id(&self) -> &Id {
94 &self.id
95 }
96
97 fn execute_next_connection(&self, data: &mut D) -> Result<crate::automaton::NextState<'a, Id, D, E>, E> {
100 let next_key = data.next_key();
101 if let Option::Some(k) = next_key {
102 for c in &self.next_states {
103 if (c.matcher)(&k) {
104 (c.exec_function)(data, &k)?;
105 return Result::Ok(crate::automaton::NextState::Continue(Rc::clone(&c.connected_state)));
106 }
107 }
108 Result::Ok(crate::automaton::NextState::NotFound)
109 } else {
110 Result::Ok(crate::automaton::NextState::ProcessEnded)
111 }
112 }
113}
114
115#[cfg(test)]
116mod test {
117 use super::KeyProvidingData;
118
119 struct TestData {
120 buffer: String,
121 end: u8,
122 current: u8,
123 }
124
125 impl TestData {
126 pub fn new(start: u8, end: u8) -> Self {
127 Self { buffer: String::new(), end, current: start }
128 }
129
130 pub fn append_text(&mut self, text: &str) -> () {
131 self.buffer.push_str(text);
132 }
133
134 pub fn data(&self) -> &String {
135 &self.buffer
136 }
137 }
138
139 impl KeyProvidingData<u8> for TestData {
140 fn next_key(&mut self) -> Option<u8> {
141 if self.current >= self.end {
142 return Option::None
143 }
144 let res = Option::Some(self.current);
145 self.current += 1;
146 return res;
147 }
148 }
149
150 mod automaton_test {
151 use crate::{automaton::{Automaton, AutomatonResult}, automaton_state::new_shared_concrete_state, simple_impl::simple_state::{test::TestData, SimpleInterStateConnection, SimpleStateImplementation}};
152
153 #[test]
154 fn automaton_with_simple_states_works() -> () {
155 let mut data = TestData::new(1, 4);
156 let mut automaton = Automaton::new({
157 let world_state = new_shared_concrete_state(SimpleStateImplementation::new(3));
158 let simple_state = new_shared_concrete_state(SimpleStateImplementation::new(2));
159 simple_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &2, |d: &mut TestData, _| {
160 d.append_text(" simple ");
161 let res: Result<(), String> = Result::Ok(());
162 res
163 }, &world_state));
164 let hello_state = new_shared_concrete_state(SimpleStateImplementation::new(1));
165 hello_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &1, |d: &mut TestData, _| {
166 d.append_text("Hello");
167 Result::Ok(())
168 }, &simple_state));
169 world_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &3, |d: &mut TestData, _| {
170 d.append_text("world!");
171 Result::Ok(())
172 }, &hello_state));
173 hello_state
174 });
175 let run_result = automaton.run(&mut data);
176 assert_eq!(data.data(), "Hello simple world!");
177 assert!(matches!(run_result, AutomatonResult::EmptyIter(1)));
178 }
179
180 #[test]
182 fn automaton_with_simple_states_works_no_next_state_found() -> () {
183 let mut data = TestData::new(2, 3);
184 let mut automaton = Automaton::new(new_shared_concrete_state(SimpleStateImplementation::new(1)));
185 let run_result: AutomatonResult<u32, String> = automaton.run(&mut data);
186 assert_eq!(data.data(), "");
187 assert!(matches!(run_result, AutomatonResult::CouldNotFindNextState(1)));
188 }
189 }
190}