cyndikator_dispatch/dispatch/
mod.rs1use crate::Event;
2use parse::Parsable;
3use runtime::DispatchCase;
4use std::fmt;
5
6use token::Token;
7
8mod parse;
9mod token;
10
11pub(crate) mod runtime;
12
13#[cfg(test)]
14mod test;
15
16#[derive(Debug)]
18pub struct Dispatch {
19 cases: Vec<runtime::DispatchCase>,
20}
21
22#[derive(Debug, PartialEq)]
24pub enum Action {
25 Record,
27
28 Notify,
30
31 Exec(String),
33}
34
35impl Dispatch {
36 pub fn dispatch(&self, event: &Event) -> Vec<Action> {
38 let mut actions = Vec::with_capacity(self.cases.len());
39 for case in &self.cases {
40 if case.cond.satisfies(event) {
41 for gen in &case.actions {
42 if gen.is_drop() {
43 return actions;
44 }
45
46 let action = gen.generate(event);
47
48 if !actions.contains(&action) {
49 actions.push(action);
50 }
51 }
52 }
53 }
54
55 actions
56 }
57
58 pub fn parse(input: &str) -> Result<Dispatch, ParseError> {
60 let tokens = Token::tokenize_significant(input)?;
61
62 let mut tokens = &tokens[..];
63 let mut cases = Vec::new();
64
65 while !tokens.is_empty() {
66 let (t, case) = DispatchCase::parse(&tokens)?;
67 cases.push(case);
68
69 tokens = t;
70 }
71
72 Ok(Dispatch { cases })
73 }
74}
75
76#[derive(Debug)]
78#[non_exhaustive]
79pub enum ParseError {
80 Tokenize,
82
83 EndOfTokens,
85
86 InvalidExpectation {
88 expect: String,
90 reality: String,
92 },
93}
94
95impl std::error::Error for ParseError {}
96
97impl fmt::Display for ParseError {
98 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
99 match self {
100 ParseError::Tokenize => write!(fmt, "Issue with tokenization"),
101 ParseError::EndOfTokens => write!(fmt, "Ran out of tokens"),
102 ParseError::InvalidExpectation { expect, reality } => {
103 write!(fmt, "expected {} but received {}", expect, reality)
104 }
105 }
106 }
107}