derive_finite_automaton/
lib.rs

1use std::fmt::{self, Display};
2
3pub use derive_finite_automaton_derive::FiniteAutomataConstructor;
4
5pub trait FiniteAutomata<T>: Sized {
6    /// A data type which holds state under the trie
7    type State;
8    fn get_next(self, c: char) -> GetNextResult<T, Self>;
9}
10
11/// A type for which a stateful trie can be built
12pub trait FiniteAutomataConstructor: Sized {
13    type FiniteAutomata: FiniteAutomata<Self>;
14    fn new_automaton() -> Self::FiniteAutomata;
15}
16
17/// Where 'T' is the type the stateful trie returns
18/// TODO the result should be only on the first result not the second ...
19#[derive(Debug, PartialEq, Eq)]
20pub enum GetNextResult<T, FA: FiniteAutomata<T>> {
21    Result {
22        result: T,
23        /// Whether the character was consumed by the action
24        ate_character: bool,
25    },
26    NewState(FA),
27    InvalidCharacter(InvalidCharacter),
28}
29
30pub type GetAutomataStateForValue<T> =
31    <<T as FiniteAutomataConstructor>::FiniteAutomata as FiniteAutomata<T>>::State;
32
33/// Character found initially which does that have transition
34#[derive(Debug, PartialEq, Eq)]
35pub struct InvalidCharacter {
36    pub received: char,
37    pub expected: &'static [char],
38}
39
40impl Display for InvalidCharacter {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        f.write_str("Expected ")?;
43        match self.expected {
44            [] => unreachable!(),
45            [a] => f.write_fmt(format_args!("{:?}", a)),
46            [a, b] => f.write_fmt(format_args!("{:?} or {:?}", a, b)),
47            [head @ .., end] => f.write_fmt(format_args!(
48                "{} or {:?}",
49                head.iter()
50                    .map(|chr| format!("{:?}", chr))
51                    .reduce(|mut a, b| {
52                        a.push_str(", ");
53                        a.push_str(&b);
54                        a
55                    })
56                    .unwrap(),
57                end
58            )),
59        }?;
60        write!(f, " found {:?}", self.received)
61    }
62}
63
64impl std::error::Error for InvalidCharacter {}