alith_client/components/grammar/
integer.rs1use super::{Grammar, GrammarError, GrammarSetterTrait};
2use std::cell::RefCell;
3
4#[derive(Clone, Default, PartialEq)]
5pub struct IntegerGrammar {
6 pub stop_word_done: Option<String>,
7 pub stop_word_no_result: Option<String>,
8 pub lower_bound: u32,
9 pub upper_bound: u32,
10 grammar_string: RefCell<Option<String>>,
11}
12
13impl IntegerGrammar {
14 pub fn new() -> Self {
15 Self {
16 stop_word_done: None,
17 stop_word_no_result: None,
18 lower_bound: 1,
19 upper_bound: 9,
20 grammar_string: RefCell::new(None),
21 }
22 }
23
24 pub fn wrap(self) -> Grammar {
25 Grammar::Integer(self)
26 }
27
28 pub fn lower_bound(mut self, lower_bound: u32) -> Self {
29 self.lower_bound = lower_bound;
30
31 self
32 }
33
34 pub fn upper_bound(mut self, upper_bound: u32) -> Self {
35 self.upper_bound = upper_bound;
36
37 self
38 }
39
40 pub fn grammar_string(&self) -> String {
41 let mut grammar_string = self.grammar_string.borrow_mut();
42 if grammar_string.is_none() {
43 *grammar_string = Some(integer_grammar(
44 self.lower_bound,
45 self.upper_bound,
46 &self.stop_word_done,
47 &self.stop_word_no_result,
48 ));
49 }
50 grammar_string.as_ref().unwrap().clone()
51 }
52
53 pub fn validate_clean(&self, content: &str) -> Result<String, GrammarError> {
54 integer_validate_clean(content)
55 }
56
57 pub fn grammar_parse(&self, content: &str) -> Result<u32, GrammarError> {
58 integer_parse(content)
59 }
60}
61
62impl GrammarSetterTrait for IntegerGrammar {
63 fn stop_word_done_mut(&mut self) -> &mut Option<String> {
64 &mut self.stop_word_done
65 }
66
67 fn stop_word_no_result_mut(&mut self) -> &mut Option<String> {
68 &mut self.stop_word_no_result
69 }
70}
71
72pub fn integer_grammar<T: AsRef<str>>(
73 lower_bound: u32,
74 upper_bound: u32,
75 stop_word_done: &Option<T>,
76 stop_word_no_result: &Option<T>,
77) -> String {
78 match upper_bound.cmp(&lower_bound) {
79 std::cmp::Ordering::Less => {
80 panic!("Upper bound must be greater than or equal to lower bound.")
81 }
82 std::cmp::Ordering::Equal => panic!("Bounds must not be the same."),
83 _ => (),
84 }
85 let range = create_range(lower_bound, upper_bound, stop_word_done);
87 match (stop_word_done, stop_word_no_result) {
88 (Some(stop_word_done), Some(stop_word_no_result)) => format!(
89 "root ::= \" \" ( {range} | \"{}\" ) \" {}\"",
90 stop_word_no_result.as_ref(),
91 stop_word_done.as_ref()
92 ),
93 (None, Some(stop_word_no_result)) => {
94 format!(
95 "root ::= \" \" ( {range} | \"{}\" )",
96 stop_word_no_result.as_ref()
97 )
98 }
99 (Some(stop_word_done), None) => {
100 format!("root ::= \" \" {range} \" {}\"", stop_word_done.as_ref())
101 }
102 (None, None) => format!("root ::= \" \" {range}"),
103 }
104}
105
106fn create_range<T: AsRef<str>>(
107 lower_bound: u32,
108 upper_bound: u32,
109 stop_word_done: &Option<T>,
110) -> String {
111 let digits = (upper_bound as f64).log10().floor() as u32 + 1;
112 let mut range = String::new();
113 if digits == 1 {
114 range.push_str(&format!("[{}-{}]", lower_bound, upper_bound));
115 return range;
116 }
117
118 for i in 1..=digits {
120 if i > 1 && 10_u32.pow(i - 1) > lower_bound {
121 if let Some(stop_word_done) = stop_word_done {
122 range.push_str(&format!("([0-9] | \" {}\")", stop_word_done.as_ref()));
123 } else {
124 range.push_str("[0-9]?");
125 }
126 } else {
127 range.push_str("[0-9]");
128 }
129 }
130 range
131}
132
133pub fn integer_validate_clean(content: &str) -> Result<String, GrammarError> {
134 let content: &str = content.trim();
135 if integer_parse(content).is_ok() {
136 Ok(content.to_string())
137 } else {
138 Err(GrammarError::ParseValueError {
139 content: content.to_string(),
140 parse_type: "u32".to_string(),
141 })
142 }
143}
144
145pub fn integer_parse(content: &str) -> Result<u32, GrammarError> {
146 content
147 .trim()
148 .parse::<u32>()
149 .map_err(|_| GrammarError::ParseValueError {
150 content: content.to_string(),
151 parse_type: "u32".to_string(),
152 })
153}