htmls/interpreter/
function.rs1use crate::{FunctionNode, parser::ast::Literal};
2
3use super::{Interpreter, InterpreterError, InterpreterResult};
4
5pub fn apply_function(it: &mut Interpreter, node: &FunctionNode) -> InterpreterResult<()> {
6 let texts = it.result.texts_mut()?;
7
8 match node.name.as_str() {
9 "trim" => trim(texts),
10 "replace" => {
11 if node.arguments.len() != 2 {
12 return Err(InterpreterError::MissingArgument(
13 "repalce must include 2 argument.".to_string(),
14 ));
15 };
16 let value0 = match &node.arguments[0] {
17 Literal::Str(v) => v,
18 _ => {
19 return Err(InterpreterError::InvalidArgument(
20 "The first parameter of replace expects a value of type str.".to_string(),
21 ));
22 }
23 };
24 let value1 = match &node.arguments[1] {
25 Literal::Str(v) => v,
26 _ => {
27 return Err(InterpreterError::InvalidArgument(
28 "The 2th parameter of replace expects a value of type str.".to_string(),
29 ));
30 }
31 };
32 replace(texts, value0, value1)
33 }
34 "lowercase" => lowercase(texts),
35 "uppercase" => uppercase(texts),
36 "join" => {
37 let value0 = if node.arguments.len() == 1 {
38 match &node.arguments[0] {
39 Literal::Str(v) => v,
40 _ => {
41 return Err(InterpreterError::InvalidArgument(
42 "join expects a value of type str".to_string(),
43 ));
44 }
45 }
46 } else if node.arguments.len() == 0 {
47 ""
48 } else {
49 return Err(InterpreterError::MissingArgument(
50 "join must include 0 or 1 argument.".to_string(),
51 ));
52 };
53 join(texts, value0)
54 }
55 "format" => {
56 let value0 = if node.arguments.len() == 1 {
57 match &node.arguments[0] {
58 Literal::Str(v) => v,
59 _ => {
60 return Err(InterpreterError::InvalidArgument(
61 "format expect a value of type str".to_string(),
62 ));
63 }
64 }
65 } else {
66 return Err(InterpreterError::MissingArgument(
67 "format must include 1 argument.".to_string(),
68 ));
69 };
70 format(texts, value0)
71 }
72 "contains" => {
73 let value0 = if node.arguments.len() == 1 {
74 match &node.arguments[0] {
75 Literal::Str(v) => v,
76 _ => {
77 return Err(InterpreterError::InvalidArgument(
78 "contains expect a value of type str".to_string(),
79 ));
80 }
81 }
82 } else {
83 return Err(InterpreterError::MissingArgument(
84 "contains must include 1 argument.".to_string(),
85 ));
86 };
87 contains(texts, value0);
88 }
89 "starts_with" => {
90 let value0 = if node.arguments.len() == 1 {
91 match &node.arguments[0] {
92 Literal::Str(v) => v,
93 _ => {
94 return Err(InterpreterError::InvalidArgument(
95 "starts_with expect a value of type str".to_string(),
96 ));
97 }
98 }
99 } else {
100 return Err(InterpreterError::MissingArgument(
101 "starts_with must include 1 argument.".to_string(),
102 ));
103 };
104 starts_with(texts, value0);
105 }
106 "ends_with" => {
107 let value0 = if node.arguments.len() == 1 {
108 match &node.arguments[0] {
109 Literal::Str(v) => v,
110 _ => {
111 return Err(InterpreterError::InvalidArgument(
112 "ends_with expect a value of type str".to_string(),
113 ));
114 }
115 }
116 } else {
117 return Err(InterpreterError::MissingArgument(
118 "ends_with must include 1 argument.".to_string(),
119 ));
120 };
121 ends_with(texts, value0);
122 }
123 "in" => {
124 let value0 = if node.arguments.len() == 1 {
125 match &node.arguments[0] {
126 Literal::List(list) => {
127 let mut values = Vec::new();
128 for item in list {
129 match item {
130 Literal::Str(v) => values.push(v.clone()),
131 _ => {
132 return Err(InterpreterError::InvalidArgument(
133 "in expect a value of type list<str>".to_string(),
134 ));
135 }
136 };
137 }
138 values
139 }
140 _ => {
141 return Err(InterpreterError::InvalidArgument(
142 "in expect a value of type list<str>".to_string(),
143 ));
144 }
145 }
146 } else {
147 return Err(InterpreterError::MissingArgument(
148 "in must include 1 argument.".to_string(),
149 ));
150 };
151
152 in_(texts, value0);
153 }
154 "slice" => {
155 if node.arguments.len() != 2 {
156 return Err(InterpreterError::MissingArgument(
157 "slice must include 2 argument.".to_string(),
158 ));
159 };
160
161 let st = match &node.arguments[0] {
162 Literal::Int(n) => {
163 if *n < 0 {
164 return Err(InterpreterError::InvalidArgument(
165 "slice's parameter must be greater than or equal to 0.".to_string(),
166 ));
167 };
168 Some(*n as usize)
169 }
170 Literal::Nil => None,
171 _ => {
172 return Err(InterpreterError::InvalidArgument(
173 "slice expect a value of type int".to_string(),
174 ));
175 }
176 };
177
178 let ed = match &node.arguments[1] {
179 Literal::Int(n) => {
180 if *n < 0 {
181 return Err(InterpreterError::InvalidArgument(
182 "slice's parameter must be greater than or equal to 0.".to_string(),
183 ));
184 };
185 Some(*n as usize)
186 }
187 Literal::Nil => None,
188 _ => {
189 return Err(InterpreterError::InvalidArgument(
190 "slice expect a value of type int".to_string(),
191 ));
192 }
193 };
194
195 slice(texts, st, ed);
196 }
197 _ => return Err(InterpreterError::UnknownFunction(node.name.clone())),
198 };
199
200 Ok(())
201}
202
203fn trim(texts: &mut Vec<String>) {
204 texts
205 .iter_mut()
206 .for_each(|text| *text = text.trim().to_string());
207}
208
209fn replace(texts: &mut Vec<String>, search: &str, replacement: &str) {
210 texts
211 .iter_mut()
212 .for_each(|text| *text = text.replace(search, replacement))
213}
214
215fn lowercase(texts: &mut Vec<String>) {
216 texts
217 .iter_mut()
218 .for_each(|text| *text = text.to_lowercase())
219}
220
221fn uppercase(texts: &mut Vec<String>) {
222 texts
223 .iter_mut()
224 .for_each(|text| *text = text.to_uppercase())
225}
226
227fn join(texts: &mut Vec<String>, separator: &str) {
228 *texts = vec![texts.join(separator)]
229}
230
231fn format(texts: &mut Vec<String>, format_str: &str) {
232 texts.iter_mut().for_each(|text| {
233 if format_str.contains("{}") {
234 *text = format!("{}", format_str.replacen("{}", &text, 1));
235 } else if format_str.starts_with("%") {
236 match format_str {
237 "%s" => { }
238 "%d" | "%i" => {
239 if let Ok(num) = text.trim().parse::<i64>() {
240 *text = num.to_string();
241 }
242 }
243 "%f" => {
244 if let Ok(num) = text.trim().parse::<f64>() {
245 *text = num.to_string();
246 }
247 }
248 "%x" => {
249 if let Ok(num) = text.trim().parse::<i64>() {
250 *text = format!("{:x}", num);
251 }
252 }
253 "%X" => {
254 if let Ok(num) = text.trim().parse::<i64>() {
255 *text = format!("{:X}", num);
256 }
257 }
258 _ => {
259 *text = format!("{}{}", format_str, text);
260 }
261 }
262 } else {
263 *text = format!("{}{}", format_str, text);
264 }
265 })
266}
267
268fn contains(texts: &mut Vec<String>, inner: &str) {
269 let mut result = Vec::new();
270
271 for text in texts.iter() {
272 if text.contains(inner) {
273 result.push(text.clone());
274 }
275 }
276
277 *texts = result;
278}
279
280fn starts_with(texts: &mut Vec<String>, st: &str) {
281 let mut result = Vec::new();
282
283 for text in texts.iter() {
284 if text.starts_with(st) {
285 result.push(text.clone());
286 }
287 }
288
289 *texts = result;
290}
291
292fn ends_with(texts: &mut Vec<String>, ed: &str) {
293 let mut result = Vec::new();
294
295 for text in texts.iter() {
296 if text.ends_with(ed) {
297 result.push(text.clone());
298 }
299 }
300
301 *texts = result;
302}
303
304fn in_(texts: &mut Vec<String>, list: Vec<String>) {
305 let mut result = Vec::new();
306 for text in texts.iter() {
307 if list.contains(text) {
308 result.push(text.clone());
309 }
310 }
311
312 *texts = result;
313}
314
315fn slice(tests: &mut Vec<String>, st: Option<usize>, ed: Option<usize>) {
316 tests.iter_mut().for_each(|text| {
317 let mut st = st.unwrap_or(0);
318 let mut ed = ed.unwrap_or(text.len());
319 if ed > text.len() {
320 ed = text.len();
321 };
322
323 if st > ed {
324 if st > text.len() {
325 st = text.len();
326 }
327 let temp = st;
328 st = ed;
329 ed = temp;
330 }
331
332 if let Some(t) = text.get(st..ed) {
333 *text = t.to_string();
334 }
335 });
336}