use std::{rc::Rc, sync::Arc};
use crate::simple_impl::simple_state::{KeyProvidingData, SharedSimpleState, SimpleInterStateConnection};
pub struct SeriesDefiner<'a, K, Id: Copy, D: KeyProvidingData<K>, E> {
default_state: SharedSimpleState<'a, K, Id, D, E>,
default_execution: Arc<dyn Fn(&mut D, &K) -> Result<(), E> + 'a>,
state: SharedSimpleState<'a, K, Id, D, E>,
}
impl <'a, K, Id: Copy, D: KeyProvidingData<K>, E> SeriesDefiner<'a, K, Id, D, E> {
pub fn new_without_default_action(starting_state: &SharedSimpleState<'a, K, Id, D, E>) -> SeriesDefiner<'a, K, Id, D, E> {
Self::new(starting_state, |_, _| {Result::Ok(())})
}
pub fn new<FDExec: Fn(&mut D, &K) -> Result<(), E> + 'a>(starting_state: &SharedSimpleState<'a, K, Id, D, E>, default_execution_function: FDExec) -> SeriesDefiner<'a, K, Id, D, E> {
Self::new_different_default_state(starting_state, starting_state, default_execution_function)
}
pub fn new_different_default_state<FDExec: Fn(&mut D, &K) -> Result<(), E> + 'a>(starting_state: &SharedSimpleState<'a, K, Id, D, E>, default_state: &SharedSimpleState<'a, K, Id, D, E>, default_execution_function: FDExec) -> SeriesDefiner<'a, K, Id, D, E> {
SeriesDefiner {
state: Rc::clone(&starting_state),
default_state: Rc::clone(&default_state),
default_execution: Arc::new(default_execution_function),
}
}
pub fn next_state<M>(mut self, matcher: M, next_state: &SharedSimpleState<'a, K, Id, D, E>) -> SeriesDefiner<'a, K, Id, D, E>
where M: 'a + Fn(&K) -> bool
{
self.state.borrow_mut().register_connection(SimpleInterStateConnection::new_no_action(matcher, next_state));
let default_exec_function = Arc::clone(&self.default_execution);
self.state.borrow_mut().register_connection(SimpleInterStateConnection::new_always_matched(move |k,d| (default_exec_function)(k, d), &self.default_state));
self.state = Rc::clone(next_state);
self
}
pub fn next_state_exec<M, FExec>(mut self, matcher: M, next_state: &SharedSimpleState<'a, K, Id, D, E>, execution_function: FExec) -> SeriesDefiner<'a, K, Id, D, E>
where
M: 'a + Fn(&K) -> bool,
FExec: 'a + Fn(&mut D, &K) -> Result<(), E>
{
self.state.borrow_mut().register_connection(SimpleInterStateConnection::new(matcher, execution_function, next_state));
let default_exec_function = Arc::clone(&self.default_execution);
self.state.borrow_mut().register_connection(SimpleInterStateConnection::new_always_matched(move |k,d| (default_exec_function)(k, d), &self.default_state));
self.state = Rc::clone(next_state);
self
}
}
#[cfg(test)]
mod test {
use std::{cell::RefCell, rc::Rc};
use crate::{automaton::{Automaton, AutomatonResult}, automaton_state::{new_shared_concrete_state, AutomatonState}, simple_impl::simple_state::SimpleStateImplementation, test_commons::{char_matcher, unwrap_result, CopiedTestData}};
use super::SeriesDefiner;
fn create_abc_series_state_tree() -> Rc<RefCell<dyn AutomatonState<'static, char, CopiedTestData<char>, String>>> {
let root_state = new_shared_concrete_state(SimpleStateImplementation::new('x'));
SeriesDefiner::new(&root_state, |_, _| {Result::Ok(())})
.next_state(char_matcher('a'), &new_shared_concrete_state(SimpleStateImplementation::new('a')))
.next_state(char_matcher('b'), &new_shared_concrete_state(SimpleStateImplementation::new('b')))
.next_state(char_matcher('c'), &new_shared_concrete_state(SimpleStateImplementation::new('c')));
root_state
}
#[test]
fn series_full_match() -> () {
let mut automaton = Automaton::new(create_abc_series_state_tree());
let mut data = CopiedTestData::new(vec!['a', 'b', 'c']);
let automaton_result: AutomatonResult<char, String> = automaton.run(&mut data);
assert_eq!(unwrap_result!(automaton_result.expect_empty_iter()), 'c');
}
#[test]
fn series_back_to_default() -> () {
let mut automaton = Automaton::new(create_abc_series_state_tree());
let mut data = CopiedTestData::new(vec!['a', 'b', 'd']);
let automaton_result: AutomatonResult<char, String> = automaton.run(&mut data);
assert_eq!(unwrap_result!(automaton_result.expect_empty_iter()), 'x');
}
#[test]
fn series_no_more_sates() -> () {
let mut automaton = Automaton::new(create_abc_series_state_tree());
let mut data = CopiedTestData::new(vec!['a', 'b', 'c', 'd']);
let automaton_result = automaton.run(&mut data).expect_could_not_find_next_state();
assert_eq!(unwrap_result!(automaton_result), 'c');
}
}