derive_finite_automaton/
lib.rs1#![doc = include_str!("./README.md")]
2
3use std::fmt::{self, Display};
4
5pub use derive_finite_automaton_derive::FiniteAutomataConstructor;
6
7pub trait FiniteAutomata<T>: Sized {
8 type State;
10 type Item: std::fmt::Debug + PartialEq + Eq + 'static;
11
12 fn get_next(self, c: Self::Item) -> GetNextResult<T, Self>;
13}
14
15pub trait FiniteAutomataConstructor: Sized {
17 type FiniteAutomata: FiniteAutomata<Self>;
18
19 fn new_automaton() -> Self::FiniteAutomata;
20}
21
22#[derive(Debug, PartialEq, Eq)]
25pub enum GetNextResult<T, FA: FiniteAutomata<T>> {
26 Result {
27 result: T,
28 ate_item: bool,
30 },
31 NewState(FA),
32 InvalidItem(InvalidItem<FA::Item>),
33}
34
35pub type GetAutomataStateForValue<T> =
37 <<T as FiniteAutomataConstructor>::FiniteAutomata as FiniteAutomata<T>>::State;
38
39#[derive(Debug, PartialEq, Eq)]
41pub struct InvalidItem<T>
42where
43 T: std::fmt::Debug + PartialEq + Eq + 'static,
44{
45 pub received: T,
46 pub expected: &'static [T],
47}
48
49impl<T> Display for InvalidItem<T>
50where
51 T: std::fmt::Debug + PartialEq + Eq,
52{
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 f.write_str("Expected ")?;
55 match self.expected {
56 [] => unreachable!(),
57 [a] => f.write_fmt(format_args!("{a:?}")),
58 [head @ .., end] => f.write_fmt(format_args!(
59 "{head} or {end:?}",
60 head = head
61 .iter()
62 .map(|chr| format!("{chr:?}"))
63 .reduce(|mut a, b| {
64 a.push_str(", ");
65 a.push_str(&b);
66 a
67 })
68 .unwrap(),
69 )),
70 }?;
71 write!(f, " found {:?}", self.received)
72 }
73}
74
75impl<T> std::error::Error for InvalidItem<T> where T: std::fmt::Debug + PartialEq + Eq + 'static {}