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 trait KeyProvidingData<K> {
8 fn next_key(&mut self) -> Option<K>;
9}
10
11pub struct SimpleInterStateConnection<'a, K, Id, D, E> where Id: Copy + 'a, K: 'a, D: 'a, E: 'a {
22 matcher: Box<dyn Fn(&K) -> bool + 'a>,
23 exec_function: Box<dyn Fn(&mut D, &K) -> Result<(), E> + 'a>,
24 connected_state: SharedAutomatonState<'a, Id, D, E>,
25}
26
27impl <'a, K, Id, D, E> SimpleInterStateConnection<'a, K, Id, D, E> where Id: Copy {
28 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 {
30 Self { matcher: Box::new(matcher), exec_function: Box::new(exec_function), connected_state: convert_to_dyn_reference(Rc::clone(next_state)) }
31 }
32
33 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 {
35 Self::new(matcher, Self::do_nothing, next_state)
36 }
37
38 fn do_nothing(_:&mut D, _:&K) -> Result<(), E> {
40 Result::Ok(())
41 }
42}
43
44pub struct SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy{
49 _phantom: PhantomData<D>,
50 id: Id,
51 next_states: Vec<SimpleInterStateConnection<'a, K, Id, D, E>>,
52}
53
54impl <'a, K, Id, D, E> SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy {
55 pub fn new(id: Id) -> Self {
59 Self { _phantom: PhantomData{}, next_states: Vec::new(), id}
60 }
61
62 pub fn register_connection(&mut self, connection: SimpleInterStateConnection<'a, K, Id, D, E>) -> ()
64 {
65 self.next_states.push(connection);
66 }
67}
68
69impl<'a, K, Id, D, E> AutomatonState<'a, Id, D, E> for SimpleStateImplementation<'a, K, Id, D, E> where D: KeyProvidingData<K>, Id: Copy {
70 fn get_id_owned(&self) -> Id {
72 self.id
73 }
74
75 fn get_id(&self) -> &Id {
77 &self.id
78 }
79
80 fn execute_next_connection(&self, data: &mut D) -> Result<crate::automaton::NextState<'a, Id, D, E>, E> {
83 let next_key = data.next_key();
84 if let Option::Some(k) = next_key {
85 for c in &self.next_states {
86 if (c.matcher)(&k) {
87 (c.exec_function)(data, &k)?;
88 return Result::Ok(crate::automaton::NextState::Continue(Rc::clone(&c.connected_state)));
89 }
90 }
91 Result::Ok(crate::automaton::NextState::NotFound)
92 } else {
93 Result::Ok(crate::automaton::NextState::ProcessEnded)
94 }
95 }
96}
97
98#[cfg(test)]
99mod test {
100 use super::KeyProvidingData;
101
102 struct TestData {
103 buffer: String,
104 end: u8,
105 current: u8,
106 }
107
108 impl TestData {
109 pub fn new(start: u8, end: u8) -> Self {
110 Self { buffer: String::new(), end, current: start }
111 }
112
113 pub fn append_text(&mut self, text: &str) -> () {
114 self.buffer.push_str(text);
115 }
116
117 pub fn data(&self) -> &String {
118 &self.buffer
119 }
120 }
121
122 impl KeyProvidingData<u8> for TestData {
123 fn next_key(&mut self) -> Option<u8> {
124 if self.current >= self.end {
125 return Option::None
126 }
127 let res = Option::Some(self.current);
128 self.current += 1;
129 return res;
130 }
131 }
132
133 mod automaton_test {
134 use crate::{automaton::{Automaton, AutomatonResult}, automaton_state::new_shared_concrete_state, simple_impl::simple_state::{test::TestData, SimpleInterStateConnection, SimpleStateImplementation}};
135
136 #[test]
137 fn automaton_with_simple_states_works() -> () {
138 let mut data = TestData::new(1, 4);
139 let mut automaton = Automaton::new(|| {
140 let world_state = new_shared_concrete_state(SimpleStateImplementation::new(3));
141 let simple_state = new_shared_concrete_state(SimpleStateImplementation::new(2));
142 simple_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &2, |d: &mut TestData, _| {
143 d.append_text(" simple ");
144 let res: Result<(), String> = Result::Ok(());
145 res
146 }, &world_state));
147 let hello_state = new_shared_concrete_state(SimpleStateImplementation::new(1));
148 hello_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &1, |d: &mut TestData, _| {
149 d.append_text("Hello");
150 Result::Ok(())
151 }, &simple_state));
152 world_state.borrow_mut().register_connection(SimpleInterStateConnection::new(|k| k == &3, |d: &mut TestData, _| {
153 d.append_text("world!");
154 Result::Ok(())
155 }, &hello_state));
156 hello_state
157 });
158 let run_result = automaton.run(&mut data);
159 assert_eq!(data.data(), "Hello simple world!");
160 assert!(matches!(run_result, AutomatonResult::EmptyIter(1)));
161 }
162
163 #[test]
165 fn automaton_with_simple_states_works_no_next_state_found() -> () {
166 let mut data = TestData::new(2, 3);
167 let mut automaton = Automaton::new(|| {
168 new_shared_concrete_state(SimpleStateImplementation::new(1))
169 });
170 let run_result: AutomatonResult<u32, String> = automaton.run(&mut data);
171 assert_eq!(data.data(), "");
172 assert!(matches!(run_result, AutomatonResult::CouldNotFindNextState(1)));
173 }
174 }
175}