1use std::fmt::Debug;
9use std::fmt::Display;
10
11use anyhow::Result;
12use serde::Serialize;
13use serde::ser::SerializeMap;
14
15use crate::escaping::Escaper;
16
17pub trait Rule: RuleClone + Debug + Send {
19 fn kind(&self) -> &'static str;
21
22 fn matches(&self, line: &[u8]) -> bool;
24
25 fn unmake(&self) -> (String, Vec<u8>);
27
28 fn to_expression_string(&self, optional: bool, multiline: bool, escaper: &Escaper) -> String {
31 let (quantifier, equal_quantifier) = if optional {
32 if multiline {
33 ("*", " (*)")
34 } else {
35 ("?", " (?)")
36 }
37 } else if multiline {
38 ("+", " (+)")
39 } else {
40 ("", "")
41 };
42 let (kind, expression) = self.unmake();
43 let rendered = escaper.escaped_printable(&expression);
44 if kind == "equal" {
45 if escaper.has_unprintable(&expression) {
46 format!("{rendered} (escaped{quantifier})")
47 } else {
48 format!("{rendered}{equal_quantifier}")
49 }
50 } else {
51 format!("{rendered} ({kind}{quantifier})")
52 }
53 }
54}
55
56impl Display for Box<dyn Rule> {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 let (kind, expression) = self.unmake();
59 let expression = Escaper::Unicode.escaped_printable(&expression);
60 write!(f, "{kind}::{expression}")
61 }
62}
63
64impl PartialEq<Box<dyn Rule>> for Box<dyn Rule> {
65 fn eq(&self, other: &Box<dyn Rule>) -> bool {
66 format!("{self}") == format!("{other}")
67 }
68}
69
70impl Clone for Box<dyn Rule> {
71 fn clone(&self) -> Self {
72 self.clone_box()
73 }
74}
75
76impl Serialize for Box<dyn Rule> {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: serde::Serializer,
80 {
81 let (kind, expression) = self.unmake();
82 let expression = Escaper::Unicode.escaped_printable(&expression);
83 let mut map = serializer.serialize_map(Some(2))?;
84 map.serialize_entry("kind", &kind)?;
85 map.serialize_entry("expression", &expression)?;
86 map.end()
87 }
88}
89
90pub trait RuleClone {
93 fn clone_box(&self) -> Box<dyn Rule>;
94}
95
96impl<T: 'static + Rule + Clone> RuleClone for T {
97 fn clone_box(&self) -> Box<dyn Rule> {
98 Box::new(self.clone())
99 }
100}
101
102pub trait RuleMaker {
104 fn make(expression: &str) -> Result<Box<dyn Rule>>;
105}
106
107pub type MakeRule = fn(&str) -> Result<Box<dyn Rule>>;