1use crate::data::error_info::ErrorInfo;
2use crate::data::position::Position;
3use crate::data::primitive::array::PrimitiveArray;
4use crate::data::primitive::boolean::PrimitiveBoolean;
5use crate::data::primitive::float::PrimitiveFloat;
6use crate::data::primitive::int::PrimitiveInt;
7use crate::data::primitive::null::PrimitiveNull;
8use crate::data::primitive::object::PrimitiveObject;
9use crate::data::primitive::tools::*;
10use crate::data::primitive::Right;
11use crate::data::primitive::{Primitive, PrimitiveType};
12use crate::data::{ast::Interval, message::Message, Data, Literal, MemoryType, MessageData, MSG};
13use crate::data::{literal, literal::ContentType};
14use crate::error_format::*;
15use crate::interpreter::json_to_literal;
16use phf::phf_map;
18use regex::Regex;
19use serde::{Deserialize, Serialize};
20use std::cmp::Ordering;
21use std::{collections::HashMap, sync::mpsc};
22use url::form_urlencoded;
23use url::form_urlencoded::Parse;
24use url::Url;
25
26type PrimitiveMethod = fn(
31 string: &mut PrimitiveString,
32 args: &HashMap<String, Literal>,
33 additional_info: &Option<HashMap<String, Literal>>,
34 interval: Interval,
35 data: &mut Data,
36 msg_data: &mut MessageData,
37 sender: &Option<mpsc::Sender<MSG>>,
38) -> Result<Literal, ErrorInfo>;
39
40const FUNCTIONS: phf::Map<&'static str, (PrimitiveMethod, Right)> = phf_map! {
41 "is_number" => (PrimitiveString::is_number as PrimitiveMethod, Right::Read),
42 "is_int" => (PrimitiveString::is_int as PrimitiveMethod, Right::Read),
43 "is_float" => (PrimitiveString::is_float as PrimitiveMethod, Right::Read),
44 "type_of" => (PrimitiveString::type_of as PrimitiveMethod, Right::Read),
45 "get_info" => (PrimitiveString::get_info as PrimitiveMethod, Right::Read),
46 "is_error" => (PrimitiveString::is_error as PrimitiveMethod, Right::Read),
47 "to_string" => (PrimitiveString::to_string as PrimitiveMethod, Right::Read),
48 "to_json" => (PrimitiveString::to_csml_json as PrimitiveMethod, Right::Read),
49
50 "encode_uri" => (PrimitiveString::encode_uri as PrimitiveMethod, Right::Read),
51 "decode_uri" => (PrimitiveString::decode_uri as PrimitiveMethod, Right::Read),
52 "encode_uri_component" => (PrimitiveString::encode_uri_component as PrimitiveMethod, Right::Read),
53 "decode_uri_component" => (PrimitiveString::decode_uri_component as PrimitiveMethod, Right::Read),
54 "encode_html_entities" => (PrimitiveString::encode_html_entities as PrimitiveMethod, Right::Read),
55 "decode_html_entities" => (PrimitiveString::decode_html_entities as PrimitiveMethod, Right::Read),
56
57 "is_email" => (PrimitiveString::is_email as PrimitiveMethod, Right::Read),
58 "append" => (PrimitiveString::append as PrimitiveMethod, Right::Read),
59 "contains" => (PrimitiveString::contains as PrimitiveMethod, Right::Read),
60 "contains_regex" => (PrimitiveString::contains_regex as PrimitiveMethod, Right::Read),
61 "replace_regex" => (PrimitiveString::replace_regex as PrimitiveMethod, Right::Read),
62 "replace_all" => (PrimitiveString::replace_all as PrimitiveMethod, Right::Read),
63 "replace" => (PrimitiveString::replace as PrimitiveMethod, Right::Read),
64
65 "ends_with" => (PrimitiveString::ends_with as PrimitiveMethod, Right::Read),
66 "ends_with_regex" => (PrimitiveString::ends_with_regex as PrimitiveMethod, Right::Read),
67 "from_json" => (PrimitiveString::from_json as PrimitiveMethod, Right::Read),
68 "is_empty" => (PrimitiveString::is_empty as PrimitiveMethod, Right::Read),
69 "length" => (PrimitiveString::length as PrimitiveMethod, Right::Read),
70 "match" => (PrimitiveString::do_match as PrimitiveMethod, Right::Read),
71 "match_regex" => (PrimitiveString::do_match_regex as PrimitiveMethod, Right::Read),
72 "starts_with" => (PrimitiveString::starts_with as PrimitiveMethod, Right::Read),
73 "starts_with_regex" => (PrimitiveString::starts_with_regex as PrimitiveMethod, Right::Read),
74 "to_lowercase" => (PrimitiveString::to_lowercase as PrimitiveMethod, Right::Read),
75 "to_uppercase" => (PrimitiveString::to_uppercase as PrimitiveMethod, Right::Read),
76 "capitalize" => (PrimitiveString::capitalize as PrimitiveMethod, Right::Read),
77 "slice" => (PrimitiveString::slice as PrimitiveMethod, Right::Read),
78 "split" => (PrimitiveString::split as PrimitiveMethod, Right::Read),
79
80 "trim" => (PrimitiveString::trim as PrimitiveMethod, Right::Read),
81 "trim_left" => (PrimitiveString::trim_left as PrimitiveMethod, Right::Read),
82 "trim_right" => (PrimitiveString::trim_right as PrimitiveMethod, Right::Read),
83
84 "abs" => (PrimitiveString::abs as PrimitiveMethod, Right::Read),
85 "cos" => (PrimitiveString::cos as PrimitiveMethod, Right::Read),
86 "ceil" =>(PrimitiveString::ceil as PrimitiveMethod, Right::Read),
87 "floor" => (PrimitiveString::floor as PrimitiveMethod, Right::Read),
88 "pow" => (PrimitiveString::pow as PrimitiveMethod, Right::Read),
89 "round" => (PrimitiveString::round as PrimitiveMethod, Right::Read),
90 "sin" => (PrimitiveString::sin as PrimitiveMethod, Right::Read),
91 "sqrt" => (PrimitiveString::sqrt as PrimitiveMethod, Right::Read),
92 "tan" => (PrimitiveString::tan as PrimitiveMethod, Right::Read),
93 "to_int" => (PrimitiveString::to_int as PrimitiveMethod, Right::Read),
94 "to_float" =>(PrimitiveString::to_float as PrimitiveMethod, Right::Read),
95};
96
97#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
98pub struct PrimitiveString {
99 pub value: String,
100}
101
102fn encode_value(pairs: &Parse) -> String {
107 let mut vec = vec![];
108
109 for (index, (key, val)) in pairs.enumerate() {
110 let encoded_value: String = if val.contains(",") {
111 let split: Vec<&str> = val.split(',').collect();
112
113 let value =
114 split
115 .into_iter()
116 .enumerate()
117 .fold(String::new(), |mut acc, (index, val)| {
118 if index > 0 {
119 acc.push_str(",");
120 }
121
122 let encoded = urlencoding::encode(val);
123 acc.push_str(&encoded);
124
125 acc
126 });
127 value
128 } else {
129 urlencoding::encode(&val).into_owned()
130 };
131
132 let and = if index == 0 { "" } else { "&" };
133 let equal = if encoded_value.len() == 0 { "" } else { "=" };
134
135 vec.push(format!("{and}{}{equal}{}", key, encoded_value));
136 }
137
138 vec.concat()
139}
140
141fn decode_value(pairs: &Parse) -> String {
142 let mut vec = vec![];
143
144 for (index, (key, val)) in pairs.enumerate() {
145 let encoded_value: String = if val.contains(",") {
146 let split: Vec<&str> = val.split(',').collect();
147
148 let value =
149 split
150 .into_iter()
151 .enumerate()
152 .fold(String::new(), |mut acc, (index, val)| {
153 if index > 0 {
154 acc.push_str(",");
155 }
156
157 match urlencoding::decode(val) {
158 Ok(decoded) => acc.push_str(&decoded),
159 Err(_) => acc.push_str(&val),
160 };
161
162 acc
163 });
164 value
165 } else {
166 match urlencoding::decode(&val) {
167 Ok(decoded) => decoded.into_owned(),
168 Err(_) => val.into_owned(),
169 }
170 };
171
172 let and = if index == 0 { "" } else { "&" };
173 let equal = if encoded_value.len() == 0 { "" } else { "=" };
174
175 vec.push(format!("{and}{}{equal}{}", key, encoded_value));
176 }
177
178 vec.concat()
179}
180
181impl PrimitiveString {
186 fn is_number(
187 string: &mut PrimitiveString,
188 args: &HashMap<String, Literal>,
189 _additional_info: &Option<HashMap<String, Literal>>,
190 interval: Interval,
191 data: &mut Data,
192 _msg_data: &mut MessageData,
193 _sender: &Option<mpsc::Sender<MSG>>,
194 ) -> Result<Literal, ErrorInfo> {
195 let usage = "is_number() => boolean";
196
197 if !args.is_empty() {
198 return Err(gen_error_info(
199 Position::new(interval, &data.context.flow),
200 format!("usage: {}", usage),
201 ));
202 }
203
204 let result = string.value.parse::<f64>().is_ok();
205
206 Ok(PrimitiveBoolean::get_literal(result, interval))
207 }
208
209 fn is_int(
210 string: &mut PrimitiveString,
211 args: &HashMap<String, Literal>,
212 _additional_info: &Option<HashMap<String, Literal>>,
213 interval: Interval,
214 data: &mut Data,
215 _msg_data: &mut MessageData,
216 _sender: &Option<mpsc::Sender<MSG>>,
217 ) -> Result<Literal, ErrorInfo> {
218 let usage = "is_int() => boolean";
219
220 if !args.is_empty() {
221 return Err(gen_error_info(
222 Position::new(interval, &data.context.flow),
223 format!("usage: {}", usage),
224 ));
225 }
226
227 let result = string.value.parse::<i64>().is_ok();
228
229 Ok(PrimitiveBoolean::get_literal(result, interval))
230 }
231
232 fn is_float(
233 string: &mut PrimitiveString,
234 args: &HashMap<String, Literal>,
235 _additional_info: &Option<HashMap<String, Literal>>,
236 interval: Interval,
237 data: &mut Data,
238 _msg_data: &mut MessageData,
239 _sender: &Option<mpsc::Sender<MSG>>,
240 ) -> Result<Literal, ErrorInfo> {
241 let usage = "is_float() => boolean";
242
243 if !args.is_empty() {
244 return Err(gen_error_info(
245 Position::new(interval, &data.context.flow),
246 format!("usage: {}", usage),
247 ));
248 }
249
250 let result = string.value.parse::<f64>();
251
252 match result {
253 Ok(_float) if string.value.find('.').is_some() => {
254 Ok(PrimitiveBoolean::get_literal(true, interval))
255 }
256 _ => Ok(PrimitiveBoolean::get_literal(false, interval)),
257 }
258 }
259
260 fn is_email(
261 string: &mut PrimitiveString,
262 args: &HashMap<String, Literal>,
263 _additional_info: &Option<HashMap<String, Literal>>,
264 interval: Interval,
265 data: &mut Data,
266 _msg_data: &mut MessageData,
267 _sender: &Option<mpsc::Sender<MSG>>,
268 ) -> Result<Literal, ErrorInfo> {
269 let usage = "is_email() => boolean";
270
271 if !args.is_empty() {
272 return Err(gen_error_info(
273 Position::new(interval, &data.context.flow),
274 format!("usage: {}", usage),
275 ));
276 }
277
278 let email_regex = Regex::new(r"^[^@]+@[^@]+\.[^@]+$").unwrap();
279
280 let result = email_regex.is_match(&string.value);
281
282 Ok(PrimitiveBoolean::get_literal(result, interval))
283 }
284
285 fn type_of(
286 _string: &mut PrimitiveString,
287 args: &HashMap<String, Literal>,
288 _additional_info: &Option<HashMap<String, Literal>>,
289 interval: Interval,
290 data: &mut Data,
291 _msg_data: &mut MessageData,
292 _sender: &Option<mpsc::Sender<MSG>>,
293 ) -> Result<Literal, ErrorInfo> {
294 let usage = "type_of() => string";
295
296 if !args.is_empty() {
297 return Err(gen_error_info(
298 Position::new(interval, &data.context.flow),
299 format!("usage: {}", usage),
300 ));
301 }
302
303 Ok(PrimitiveString::get_literal("string", interval))
304 }
305
306 fn get_info(
307 _string: &mut PrimitiveString,
308 args: &HashMap<String, Literal>,
309 additional_info: &Option<HashMap<String, Literal>>,
310 interval: Interval,
311 data: &mut Data,
312 _msg_data: &mut MessageData,
313 _sender: &Option<mpsc::Sender<MSG>>,
314 ) -> Result<Literal, ErrorInfo> {
315 literal::get_info(args, additional_info, interval, data)
316 }
317
318 fn is_error(
319 _string: &mut PrimitiveString,
320 _args: &HashMap<String, Literal>,
321 additional_info: &Option<HashMap<String, Literal>>,
322 interval: Interval,
323 _data: &mut Data,
324 _msg_data: &mut MessageData,
325 _sender: &Option<mpsc::Sender<MSG>>,
326 ) -> Result<Literal, ErrorInfo> {
327 match additional_info {
328 Some(map) if map.contains_key("error") => {
329 Ok(PrimitiveBoolean::get_literal(true, interval))
330 }
331 _ => Ok(PrimitiveBoolean::get_literal(false, interval)),
332 }
333 }
334
335 fn to_string(
336 string: &mut PrimitiveString,
337 args: &HashMap<String, Literal>,
338 _additional_info: &Option<HashMap<String, Literal>>,
339 interval: Interval,
340 data: &mut Data,
341 _msg_data: &mut MessageData,
342 _sender: &Option<mpsc::Sender<MSG>>,
343 ) -> Result<Literal, ErrorInfo> {
344 let usage = "to_string() => string";
345
346 if !args.is_empty() {
347 return Err(gen_error_info(
348 Position::new(interval, &data.context.flow),
349 format!("usage: {}", usage),
350 ));
351 }
352
353 Ok(PrimitiveString::get_literal(&string.to_string(), interval))
354 }
355
356 fn to_csml_json(
357 string: &mut PrimitiveString,
358 args: &HashMap<String, Literal>,
359 _additional_info: &Option<HashMap<String, Literal>>,
360 interval: Interval,
361 data: &mut Data,
362 _msg_data: &mut MessageData,
363 _sender: &Option<mpsc::Sender<MSG>>,
364 ) -> Result<Literal, ErrorInfo> {
365 let usage = "to_json() => obj";
366
367 if !args.is_empty() {
368 return Err(gen_error_info(
369 Position::new(interval, &data.context.flow),
370 format!("usage: {}", usage),
371 ));
372 }
373
374 let value = string.to_string();
375
376 let config = quickxml_to_serde::Config::new_with_custom_values(
377 true,
378 "@",
379 "$text",
380 quickxml_to_serde::NullValue::Ignore,
381 );
382
383 let xml: Option<serde_json::Value> =
384 quickxml_to_serde::xml_string_to_json(value.clone(), &config).ok();
385
386 let yaml: Option<serde_json::Value> = serde_yaml::from_str(&value).ok();
387
388 match (&yaml, &xml) {
389 (_, Some(json)) | (Some(json), _) => {
390 json_to_literal(json, interval, &data.context.flow)
391 }
392 _ => {
393 return Err(gen_error_info(
394 Position::new(interval, &data.context.flow),
395 format!("Invalid format string is not a valid yaml or xml"),
396 ));
397 }
398 }
399 }
400
401 fn encode_uri(
402 string: &mut PrimitiveString,
403 args: &HashMap<String, Literal>,
404 _additional_info: &Option<HashMap<String, Literal>>,
405 interval: Interval,
406 data: &mut Data,
407 _msg_data: &mut MessageData,
408 _sender: &Option<mpsc::Sender<MSG>>,
409 ) -> Result<Literal, ErrorInfo> {
410 let usage = "encode_uri() => String";
411
412 if !args.is_empty() {
413 return Err(gen_error_info(
414 Position::new(interval, &data.context.flow),
415 format!("usage: {}", usage),
416 ));
417 }
418
419 let vec: Vec<&str> = string.value.split('?').collect();
420
421 let (q_separator, query, separator, fragment) = if vec.len() > 1 {
422 let url = Url::parse(&string.value).unwrap();
423
424 let query_pairs = url.query_pairs();
425 let (q_separator, query) = match query_pairs.count() {
426 0 => ("", "".to_owned()),
427 _ => {
428 let query = encode_value(&query_pairs);
429 ("?", query)
430 }
431 };
432
433 let (f_serparatorm, fragment) = match url.fragment() {
434 Some(frag) => {
435 let pairs = form_urlencoded::parse(frag.as_bytes());
436 let fragment = encode_value(&pairs);
437
438 ("#", fragment)
439 }
440 None => ("", "".to_owned()),
441 };
442
443 (q_separator, query, f_serparatorm, fragment)
444 } else {
445 ("", "".to_owned(), "", "".to_owned())
446 };
447
448 Ok(PrimitiveString::get_literal(
449 &format!("{}{q_separator}{query}{separator}{fragment}", vec[0]),
450 interval,
451 ))
452 }
453
454 fn decode_uri(
455 string: &mut PrimitiveString,
456 args: &HashMap<String, Literal>,
457 _additional_info: &Option<HashMap<String, Literal>>,
458 interval: Interval,
459 data: &mut Data,
460 _msg_data: &mut MessageData,
461 _sender: &Option<mpsc::Sender<MSG>>,
462 ) -> Result<Literal, ErrorInfo> {
463 let usage = "encode_uri() => String";
464
465 if !args.is_empty() {
466 return Err(gen_error_info(
467 Position::new(interval, &data.context.flow),
468 format!("usage: {}", usage),
469 ));
470 }
471
472 let vec: Vec<&str> = string.value.split('?').collect();
473
474 let (q_separator, query, separator, fragment) = if vec.len() > 1 {
475 let url = Url::parse(&string.value).unwrap();
476
477 let query_pairs = url.query_pairs();
478 let (q_separator, query) = match query_pairs.count() {
479 0 => ("", "".to_owned()),
480 _ => {
481 let query = decode_value(&query_pairs);
482 ("?", query)
483 }
484 };
485
486 let (f_serparatorm, fragment) = match url.fragment() {
487 Some(frag) => {
488 let pairs = form_urlencoded::parse(frag.as_bytes());
489 let fragment = decode_value(&pairs);
490
491 ("#", fragment)
492 }
493 None => ("", "".to_owned()),
494 };
495
496 (q_separator, query, f_serparatorm, fragment)
497 } else {
498 ("", "".to_owned(), "", "".to_owned())
499 };
500
501 Ok(PrimitiveString::get_literal(
502 &format!("{}{q_separator}{query}{separator}{fragment}", vec[0]),
503 interval,
504 ))
505 }
506
507 fn encode_uri_component(
508 string: &mut PrimitiveString,
509 args: &HashMap<String, Literal>,
510 _additional_info: &Option<HashMap<String, Literal>>,
511 interval: Interval,
512 data: &mut Data,
513 _msg_data: &mut MessageData,
514 _sender: &Option<mpsc::Sender<MSG>>,
515 ) -> Result<Literal, ErrorInfo> {
516 let usage = "encode_uri_component() => String";
517
518 if !args.is_empty() {
519 return Err(gen_error_info(
520 Position::new(interval, &data.context.flow),
521 format!("usage: {}", usage),
522 ));
523 }
524
525 let encoded: String = urlencoding::encode(&string.value).into_owned();
526
527 Ok(PrimitiveString::get_literal(&encoded, interval))
528 }
529
530 fn decode_uri_component(
531 string: &mut PrimitiveString,
532 args: &HashMap<String, Literal>,
533 _additional_info: &Option<HashMap<String, Literal>>,
534 interval: Interval,
535 data: &mut Data,
536 _msg_data: &mut MessageData,
537 _sender: &Option<mpsc::Sender<MSG>>,
538 ) -> Result<Literal, ErrorInfo> {
539 let usage = "decode_uri_component() => String";
540
541 if !args.is_empty() {
542 return Err(gen_error_info(
543 Position::new(interval, &data.context.flow),
544 format!("usage: {}", usage),
545 ));
546 }
547
548 match urlencoding::decode(&string.value) {
549 Ok(decoded) => Ok(PrimitiveString::get_literal(
550 &decoded.into_owned(),
551 interval,
552 )),
553 Err(_) => Err(gen_error_info(
554 Position::new(interval, &data.context.flow),
555 format!("Invalid UTF8 string"),
556 )),
557 }
558 }
559
560 fn decode_html_entities(
561 string: &mut PrimitiveString,
562 args: &HashMap<String, Literal>,
563 _additional_info: &Option<HashMap<String, Literal>>,
564 interval: Interval,
565 data: &mut Data,
566 _msg_data: &mut MessageData,
567 _sender: &Option<mpsc::Sender<MSG>>,
568 ) -> Result<Literal, ErrorInfo> {
569 let usage = "decode_html_entities() => String";
570
571 if !args.is_empty() {
572 return Err(gen_error_info(
573 Position::new(interval, &data.context.flow),
574 format!("usage: {}", usage),
575 ));
576 }
577
578 let decoded = html_escape::decode_html_entities(&string.value);
579
580 Ok(PrimitiveString::get_literal(&decoded, interval))
581 }
582
583 fn encode_html_entities(
584 string: &mut PrimitiveString,
585 args: &HashMap<String, Literal>,
586 _additional_info: &Option<HashMap<String, Literal>>,
587 interval: Interval,
588 data: &mut Data,
589 _msg_data: &mut MessageData,
590 _sender: &Option<mpsc::Sender<MSG>>,
591 ) -> Result<Literal, ErrorInfo> {
592 let usage = "encode_html_entities() => String";
593
594 if !args.is_empty() {
595 return Err(gen_error_info(
596 Position::new(interval, &data.context.flow),
597 format!("usage: {}", usage),
598 ));
599 }
600
601 let decoded = html_escape::encode_text(&string.value);
602
603 Ok(PrimitiveString::get_literal(&decoded, interval))
604 }
605}
606
607impl PrimitiveString {
608 fn append(
609 string: &mut PrimitiveString,
610 args: &HashMap<String, Literal>,
611 _additional_info: &Option<HashMap<String, Literal>>,
612 interval: Interval,
613 data: &mut Data,
614 _msg_data: &mut MessageData,
615 _sender: &Option<mpsc::Sender<MSG>>,
616 ) -> Result<Literal, ErrorInfo> {
617 let usage = "append(value: string) => string";
618
619 if args.len() != 1 {
620 return Err(gen_error_info(
621 Position::new(interval, &data.context.flow),
622 format!("usage: {}", usage),
623 ));
624 }
625
626 let mut result = string.value.to_owned();
627
628 let value = match args.get("arg0") {
629 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
630 Literal::get_value::<String>(
631 &res.primitive,
632 &data.context.flow,
633 interval,
634 ERROR_STRING_APPEND.to_owned(),
635 )?
636 }
637 _ => {
638 return Err(gen_error_info(
639 Position::new(interval, &data.context.flow),
640 ERROR_STRING_APPEND.to_owned(),
641 ));
642 }
643 };
644
645 result.push_str(value);
646
647 Ok(PrimitiveString::get_literal(&result, interval))
648 }
649
650 fn contains(
651 string: &mut PrimitiveString,
652 args: &HashMap<String, Literal>,
653 _additional_info: &Option<HashMap<String, Literal>>,
654 interval: Interval,
655 data: &mut Data,
656 _msg_data: &mut MessageData,
657 _sender: &Option<mpsc::Sender<MSG>>,
658 ) -> Result<Literal, ErrorInfo> {
659 let usage = "contains(value: string) => boolean";
660
661 if args.len() != 1 {
662 return Err(gen_error_info(
663 Position::new(interval, &data.context.flow),
664 format!("usage: {}", usage),
665 ));
666 }
667
668 let value = match args.get("arg0") {
669 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
670 Literal::get_value::<String>(
671 &res.primitive,
672 &data.context.flow,
673 interval,
674 ERROR_STRING_DO_MATCH.to_owned(),
675 )?
676 }
677 _ => {
678 return Err(gen_error_info(
679 Position::new(interval, &data.context.flow),
680 ERROR_STRING_DO_MATCH.to_owned(),
681 ));
682 }
683 };
684
685 let result = string.value.contains(value);
686
687 Ok(PrimitiveBoolean::get_literal(result, interval))
688 }
689
690 fn contains_regex(
691 string: &mut PrimitiveString,
692 args: &HashMap<String, Literal>,
693 _additional_info: &Option<HashMap<String, Literal>>,
694 interval: Interval,
695 data: &mut Data,
696 _msg_data: &mut MessageData,
697 _sender: &Option<mpsc::Sender<MSG>>,
698 ) -> Result<Literal, ErrorInfo> {
699 let usage = "contains_regex(value: string) => boolean";
700
701 if args.len() != 1 {
702 return Err(gen_error_info(
703 Position::new(interval, &data.context.flow),
704 format!("usage: {}", usage),
705 ));
706 }
707
708 let value = match args.get("arg0") {
709 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
710 Literal::get_value::<String>(
711 &res.primitive,
712 &data.context.flow,
713 interval,
714 ERROR_STRING_CONTAINS_REGEX.to_owned(),
715 )?
716 }
717 _ => {
718 return Err(gen_error_info(
719 Position::new(interval, &data.context.flow),
720 ERROR_STRING_CONTAINS_REGEX.to_owned(),
721 ));
722 }
723 };
724
725 let action = match Regex::new(value) {
726 Ok(res) => res,
727 Err(_) => {
728 return Err(gen_error_info(
729 Position::new(interval, &data.context.flow),
730 ERROR_STRING_CONTAINS_REGEX.to_owned(),
731 ));
732 }
733 };
734
735 let result = action.is_match(&string.value);
736
737 Ok(PrimitiveBoolean::get_literal(result, interval))
738 }
739
740 fn replace(
741 string: &mut PrimitiveString,
742 args: &HashMap<String, Literal>,
743 _additional_info: &Option<HashMap<String, Literal>>,
744 interval: Interval,
745 data: &mut Data,
746 _msg_data: &mut MessageData,
747 _sender: &Option<mpsc::Sender<MSG>>,
748 ) -> Result<Literal, ErrorInfo> {
749 let usage = "replace(value_to_replace: string, replace_by: string) => string";
750
751 if args.len() != 2 {
752 return Err(gen_error_info(
753 Position::new(interval, &data.context.flow),
754 format!("usage: {}", usage),
755 ));
756 }
757
758 let (to_replace, replace_by) = match (args.get("arg0"), args.get("arg1")) {
759 (Some(old), Some(new))
760 if old.primitive.get_type() == PrimitiveType::PrimitiveString
761 && new.primitive.get_type() == PrimitiveType::PrimitiveString =>
762 {
763 (
764 Literal::get_value::<String>(
765 &old.primitive,
766 &data.context.flow,
767 interval,
768 ERROR_STRING_REPLACE.to_owned(),
769 )?,
770 Literal::get_value::<String>(
771 &new.primitive,
772 &data.context.flow,
773 interval,
774 ERROR_STRING_REPLACE.to_owned(),
775 )?,
776 )
777 }
778 _ => {
779 return Err(gen_error_info(
780 Position::new(interval, &data.context.flow),
781 ERROR_STRING_REPLACE.to_owned(),
782 ));
783 }
784 };
785
786 let new_string = string.value.replacen(to_replace, replace_by, 1);
787
788 Ok(PrimitiveString::get_literal(&new_string, interval))
789 }
790
791 fn replace_all(
792 string: &mut PrimitiveString,
793 args: &HashMap<String, Literal>,
794 _additional_info: &Option<HashMap<String, Literal>>,
795 interval: Interval,
796 data: &mut Data,
797 _msg_data: &mut MessageData,
798 _sender: &Option<mpsc::Sender<MSG>>,
799 ) -> Result<Literal, ErrorInfo> {
800 let usage = "replace_all(value_to_replace: string, replace_by: string) => string";
801
802 if args.len() != 2 {
803 return Err(gen_error_info(
804 Position::new(interval, &data.context.flow),
805 format!("usage: {}", usage),
806 ));
807 }
808
809 let (to_replace, replace_by) = match (args.get("arg0"), args.get("arg1")) {
810 (Some(old), Some(new))
811 if old.primitive.get_type() == PrimitiveType::PrimitiveString
812 && new.primitive.get_type() == PrimitiveType::PrimitiveString =>
813 {
814 (
815 Literal::get_value::<String>(
816 &old.primitive,
817 &data.context.flow,
818 interval,
819 ERROR_STRING_REPLACE_ALL.to_owned(),
820 )?,
821 Literal::get_value::<String>(
822 &new.primitive,
823 &data.context.flow,
824 interval,
825 ERROR_STRING_REPLACE_ALL.to_owned(),
826 )?,
827 )
828 }
829 _ => {
830 return Err(gen_error_info(
831 Position::new(interval, &data.context.flow),
832 ERROR_STRING_REPLACE_ALL.to_owned(),
833 ));
834 }
835 };
836
837 let new_string = string.value.replace(to_replace, replace_by);
838
839 Ok(PrimitiveString::get_literal(&new_string, interval))
840 }
841
842 fn replace_regex(
843 string: &mut PrimitiveString,
844 args: &HashMap<String, Literal>,
845 _additional_info: &Option<HashMap<String, Literal>>,
846 interval: Interval,
847 data: &mut Data,
848 _msg_data: &mut MessageData,
849 _sender: &Option<mpsc::Sender<MSG>>,
850 ) -> Result<Literal, ErrorInfo> {
851 let usage = "replace_regex(regex: string, replace_by: string) => string";
852
853 if args.len() != 2 {
854 return Err(gen_error_info(
855 Position::new(interval, &data.context.flow),
856 format!("usage: {}", usage),
857 ));
858 }
859
860 let (regex, replace_by) = match (args.get("arg0"), args.get("arg1")) {
861 (Some(old), Some(new))
862 if old.primitive.get_type() == PrimitiveType::PrimitiveString
863 && new.primitive.get_type() == PrimitiveType::PrimitiveString =>
864 {
865 (
866 Literal::get_value::<String>(
867 &old.primitive,
868 &data.context.flow,
869 interval,
870 ERROR_STRING_REPLACE_REGEX.to_owned(),
871 )?,
872 Literal::get_value::<String>(
873 &new.primitive,
874 &data.context.flow,
875 interval,
876 ERROR_STRING_REPLACE_REGEX.to_owned(),
877 )?,
878 )
879 }
880 _ => {
881 return Err(gen_error_info(
882 Position::new(interval, &data.context.flow),
883 ERROR_STRING_REPLACE_REGEX.to_owned(),
884 ));
885 }
886 };
887
888 let reg = match Regex::new(regex) {
889 Ok(res) => res,
890 Err(_) => {
891 return Err(gen_error_info(
892 Position::new(interval, &data.context.flow),
893 ERROR_STRING_REPLACE_REGEX.to_owned(),
894 ));
895 }
896 };
897
898 let new_string = reg.replace_all(&string.value, replace_by);
899
900 Ok(PrimitiveString::get_literal(&new_string, interval))
901 }
902
903 fn ends_with(
904 string: &mut PrimitiveString,
905 args: &HashMap<String, Literal>,
906 _additional_info: &Option<HashMap<String, Literal>>,
907 interval: Interval,
908 data: &mut Data,
909 _msg_data: &mut MessageData,
910 _sender: &Option<mpsc::Sender<MSG>>,
911 ) -> Result<Literal, ErrorInfo> {
912 let usage = "ends_with(value: string) => boolean";
913
914 if args.len() != 1 {
915 return Err(gen_error_info(
916 Position::new(interval, &data.context.flow),
917 format!("usage: {}", usage),
918 ));
919 }
920
921 let value = match args.get("arg0") {
922 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
923 Literal::get_value::<String>(
924 &res.primitive,
925 &data.context.flow,
926 interval,
927 ERROR_STRING_CONTAINS.to_owned(),
928 )?
929 }
930 _ => {
931 return Err(gen_error_info(
932 Position::new(interval, &data.context.flow),
933 ERROR_STRING_END_WITH.to_owned(),
934 ));
935 }
936 };
937
938 let result = string.value.ends_with(value);
939
940 Ok(PrimitiveBoolean::get_literal(result, interval))
941 }
942
943 fn ends_with_regex(
944 string: &mut PrimitiveString,
945 args: &HashMap<String, Literal>,
946 _additional_info: &Option<HashMap<String, Literal>>,
947 interval: Interval,
948 data: &mut Data,
949 _msg_data: &mut MessageData,
950 _sender: &Option<mpsc::Sender<MSG>>,
951 ) -> Result<Literal, ErrorInfo> {
952 let usage = "ends_with_regex(value: string) => boolean";
953
954 if args.len() != 1 {
955 return Err(gen_error_info(
956 Position::new(interval, &data.context.flow),
957 format!("usage: {}", usage),
958 ));
959 }
960
961 let value = match args.get("arg0") {
962 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
963 Literal::get_value::<String>(
964 &res.primitive,
965 &data.context.flow,
966 interval,
967 ERROR_STRING_END_WITH_REGEX.to_owned(),
968 )?
969 }
970 _ => {
971 return Err(gen_error_info(
972 Position::new(interval, &data.context.flow),
973 ERROR_STRING_END_WITH_REGEX.to_owned(),
974 ));
975 }
976 };
977
978 let action = match Regex::new(value) {
979 Ok(res) => res,
980 Err(_) => {
981 return Err(gen_error_info(
982 Position::new(interval, &data.context.flow),
983 ERROR_STRING_END_WITH_REGEX.to_owned(),
984 ));
985 }
986 };
987
988 for key in action.find_iter(&string.value) {
989 if key.end() == string.value.len() {
990 return Ok(PrimitiveBoolean::get_literal(true, interval));
991 }
992 }
993
994 Ok(PrimitiveBoolean::get_literal(false, interval))
995 }
996
997 fn from_json(
998 string: &mut PrimitiveString,
999 args: &HashMap<String, Literal>,
1000 _additional_info: &Option<HashMap<String, Literal>>,
1001 interval: Interval,
1002 data: &mut Data,
1003 _msg_data: &mut MessageData,
1004 _sender: &Option<mpsc::Sender<MSG>>,
1005 ) -> Result<Literal, ErrorInfo> {
1006 let usage = "from_json() => object";
1007
1008 if !args.is_empty() {
1009 return Err(gen_error_info(
1010 Position::new(interval, &data.context.flow),
1011 format!("usage: {}", usage),
1012 ));
1013 }
1014
1015 let object = match serde_json::from_str(&string.value) {
1016 Ok(result) => result,
1017 Err(_) => {
1018 return Err(gen_error_info(
1019 Position::new(interval, &data.context.flow),
1020 ERROR_STRING_FROM_JSON.to_owned(),
1021 ));
1022 }
1023 };
1024
1025 json_to_literal(&object, interval, &data.context.flow)
1026 }
1027
1028 fn is_empty(
1029 string: &mut PrimitiveString,
1030 args: &HashMap<String, Literal>,
1031 _additional_info: &Option<HashMap<String, Literal>>,
1032 interval: Interval,
1033 data: &mut Data,
1034 _msg_data: &mut MessageData,
1035 _sender: &Option<mpsc::Sender<MSG>>,
1036 ) -> Result<Literal, ErrorInfo> {
1037 let usage = "is_empty() => boolean";
1038
1039 if args.len() != 1 {
1040 return Err(gen_error_info(
1041 Position::new(interval, &data.context.flow),
1042 format!("usage: {}", usage),
1043 ));
1044 }
1045
1046 let result = string.value.is_empty();
1047
1048 Ok(PrimitiveBoolean::get_literal(result, interval))
1049 }
1050
1051 fn length(
1052 string: &mut PrimitiveString,
1053 args: &HashMap<String, Literal>,
1054 _additional_info: &Option<HashMap<String, Literal>>,
1055 interval: Interval,
1056 data: &mut Data,
1057 _msg_data: &mut MessageData,
1058 _sender: &Option<mpsc::Sender<MSG>>,
1059 ) -> Result<Literal, ErrorInfo> {
1060 let usage = "length() => int";
1061
1062 if !args.is_empty() {
1063 return Err(gen_error_info(
1064 Position::new(interval, &data.context.flow),
1065 format!("usage: {}", usage),
1066 ));
1067 }
1068
1069 let result = string.value.len();
1070
1071 Ok(PrimitiveInt::get_literal(result as i64, interval))
1072 }
1073
1074 fn do_match(
1075 string: &mut PrimitiveString,
1076 args: &HashMap<String, Literal>,
1077 _additional_info: &Option<HashMap<String, Literal>>,
1078 interval: Interval,
1079 data: &mut Data,
1080 _msg_data: &mut MessageData,
1081 _sender: &Option<mpsc::Sender<MSG>>,
1082 ) -> Result<Literal, ErrorInfo> {
1083 let usage = "match(value: string>) => array";
1084
1085 if args.len() != 1 {
1086 return Err(gen_error_info(
1087 Position::new(interval, &data.context.flow),
1088 format!("usage: {}", usage),
1089 ));
1090 }
1091
1092 let mut vector: Vec<Literal> = Vec::new();
1093
1094 let value = match args.get("arg0") {
1095 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
1096 Literal::get_value::<String>(
1097 &res.primitive,
1098 &data.context.flow,
1099 interval,
1100 ERROR_STRING_DO_MATCH.to_owned(),
1101 )?
1102 }
1103 _ => {
1104 return Err(gen_error_info(
1105 Position::new(interval, &data.context.flow),
1106 ERROR_STRING_DO_MATCH.to_owned(),
1107 ));
1108 }
1109 };
1110
1111 for result in string.value.matches(value) {
1112 vector.push(PrimitiveString::get_literal(result, interval));
1113 }
1114
1115 if vector.is_empty() {
1116 return Ok(PrimitiveNull::get_literal(interval));
1117 }
1118
1119 Ok(PrimitiveArray::get_literal(&vector, interval))
1120 }
1121
1122 fn do_match_regex(
1123 string: &mut PrimitiveString,
1124 args: &HashMap<String, Literal>,
1125 _additional_info: &Option<HashMap<String, Literal>>,
1126 interval: Interval,
1127 data: &mut Data,
1128 _msg_data: &mut MessageData,
1129 _sender: &Option<mpsc::Sender<MSG>>,
1130 ) -> Result<Literal, ErrorInfo> {
1131 let usage = "match_regex(value: string>) => array";
1132
1133 if args.len() != 1 {
1134 return Err(gen_error_info(
1135 Position::new(interval, &data.context.flow),
1136 format!("usage: {}", usage),
1137 ));
1138 }
1139
1140 let mut s: &str = &string.value;
1141 let mut vector: Vec<Literal> = Vec::new();
1142
1143 let value = match args.get("arg0") {
1144 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
1145 Literal::get_value::<String>(
1146 &res.primitive,
1147 &data.context.flow,
1148 interval,
1149 ERROR_STRING_MATCH_REGEX.to_owned(),
1150 )?
1151 }
1152 _ => {
1153 return Err(gen_error_info(
1154 Position::new(interval, &data.context.flow),
1155 ERROR_STRING_MATCH_REGEX.to_owned(),
1156 ));
1157 }
1158 };
1159
1160 let action = match Regex::new(value) {
1161 Ok(res) => res,
1162 Err(_) => {
1163 return Err(gen_error_info(
1164 Position::new(interval, &data.context.flow),
1165 ERROR_STRING_VALID_REGEX.to_owned(),
1166 ));
1167 }
1168 };
1169
1170 while let Some(result) = action.find(&s) {
1171 vector.push(PrimitiveString::get_literal(
1172 &s[result.start()..result.end()],
1173 interval,
1174 ));
1175 s = &s[result.end()..];
1176 }
1177
1178 if vector.is_empty() {
1179 return Ok(PrimitiveNull::get_literal(interval));
1180 }
1181
1182 Ok(PrimitiveArray::get_literal(&vector, interval))
1183 }
1184
1185 fn starts_with(
1186 string: &mut PrimitiveString,
1187 args: &HashMap<String, Literal>,
1188 _additional_info: &Option<HashMap<String, Literal>>,
1189 interval: Interval,
1190 data: &mut Data,
1191 _msg_data: &mut MessageData,
1192 _sender: &Option<mpsc::Sender<MSG>>,
1193 ) -> Result<Literal, ErrorInfo> {
1194 let usage = "starts_with(value: string) => boolean";
1195
1196 if args.len() != 1 {
1197 return Err(gen_error_info(
1198 Position::new(interval, &data.context.flow),
1199 format!("usage: {}", usage),
1200 ));
1201 }
1202
1203 let value = match args.get("arg0") {
1204 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
1205 Literal::get_value::<String>(
1206 &res.primitive,
1207 &data.context.flow,
1208 interval,
1209 ERROR_STRING_START_WITH.to_owned(),
1210 )?
1211 }
1212 _ => {
1213 return Err(gen_error_info(
1214 Position::new(interval, &data.context.flow),
1215 ERROR_STRING_START_WITH.to_owned(),
1216 ));
1217 }
1218 };
1219
1220 let result = string.value.starts_with(value);
1221
1222 Ok(PrimitiveBoolean::get_literal(result, interval))
1223 }
1224
1225 fn starts_with_regex(
1226 string: &mut PrimitiveString,
1227 args: &HashMap<String, Literal>,
1228 _additional_info: &Option<HashMap<String, Literal>>,
1229 interval: Interval,
1230 data: &mut Data,
1231 _msg_data: &mut MessageData,
1232 _sender: &Option<mpsc::Sender<MSG>>,
1233 ) -> Result<Literal, ErrorInfo> {
1234 let usage = "starts_with_regex(value: string) => boolean";
1235
1236 if args.len() != 1 {
1237 return Err(gen_error_info(
1238 Position::new(interval, &data.context.flow),
1239 format!("usage: {}", usage),
1240 ));
1241 }
1242
1243 let value = match args.get("arg0") {
1244 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
1245 Literal::get_value::<String>(
1246 &res.primitive,
1247 &data.context.flow,
1248 interval,
1249 ERROR_STRING_START_WITH_REGEX.to_owned(),
1250 )?
1251 }
1252 _ => {
1253 return Err(gen_error_info(
1254 Position::new(interval, &data.context.flow),
1255 ERROR_STRING_START_WITH_REGEX.to_owned(),
1256 ));
1257 }
1258 };
1259
1260 let action = match Regex::new(value) {
1261 Ok(res) => res,
1262 Err(_) => {
1263 return Err(gen_error_info(
1264 Position::new(interval, &data.context.flow),
1265 ERROR_STRING_VALID_REGEX.to_owned(),
1266 ));
1267 }
1268 };
1269
1270 if let Some(res) = action.find(&string.value) {
1271 if res.start() == 0 {
1272 return Ok(PrimitiveBoolean::get_literal(true, interval));
1273 }
1274 }
1275
1276 Ok(PrimitiveBoolean::get_literal(false, interval))
1277 }
1278
1279 fn to_lowercase(
1280 string: &mut PrimitiveString,
1281 args: &HashMap<String, Literal>,
1282 _additional_info: &Option<HashMap<String, Literal>>,
1283 interval: Interval,
1284 data: &mut Data,
1285 _msg_data: &mut MessageData,
1286 _sender: &Option<mpsc::Sender<MSG>>,
1287 ) -> Result<Literal, ErrorInfo> {
1288 let usage = "to_lowercase() => string";
1289
1290 if !args.is_empty() {
1291 return Err(gen_error_info(
1292 Position::new(interval, &data.context.flow),
1293 format!("usage: {}", usage),
1294 ));
1295 }
1296
1297 let s = &string.value;
1298 Ok(PrimitiveString::get_literal(&s.to_lowercase(), interval))
1299 }
1300
1301 fn to_uppercase(
1302 string: &mut PrimitiveString,
1303 args: &HashMap<String, Literal>,
1304 _additional_info: &Option<HashMap<String, Literal>>,
1305 interval: Interval,
1306 data: &mut Data,
1307 _msg_data: &mut MessageData,
1308 _sender: &Option<mpsc::Sender<MSG>>,
1309 ) -> Result<Literal, ErrorInfo> {
1310 let usage = "to_uppercase() => string";
1311
1312 if !args.is_empty() {
1313 return Err(gen_error_info(
1314 Position::new(interval, &data.context.flow),
1315 format!("usage: {}", usage),
1316 ));
1317 }
1318
1319 let s = &string.value;
1320 Ok(PrimitiveString::get_literal(&s.to_uppercase(), interval))
1321 }
1322
1323 fn capitalize(
1324 string: &mut PrimitiveString,
1325 args: &HashMap<String, Literal>,
1326 _additional_info: &Option<HashMap<String, Literal>>,
1327 interval: Interval,
1328 data: &mut Data,
1329 _msg_data: &mut MessageData,
1330 _sender: &Option<mpsc::Sender<MSG>>,
1331 ) -> Result<Literal, ErrorInfo> {
1332 let usage = "capitalize() => string";
1333
1334 if !args.is_empty() {
1335 return Err(gen_error_info(
1336 Position::new(interval, &data.context.flow),
1337 format!("usage: {}", usage),
1338 ));
1339 }
1340
1341 let s = &string.value;
1342
1343 let mut c = s.chars();
1344 let string = match c.next() {
1345 None => String::new(),
1346 Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
1347 };
1348
1349 Ok(PrimitiveString::get_literal(&string, interval))
1350 }
1351
1352 fn slice(
1353 string: &mut PrimitiveString,
1354 args: &HashMap<String, Literal>,
1355 _additional_info: &Option<HashMap<String, Literal>>,
1356 interval: Interval,
1357 data: &mut Data,
1358 _msg_data: &mut MessageData,
1359 _sender: &Option<mpsc::Sender<MSG>>,
1360 ) -> Result<Literal, ErrorInfo> {
1361 let usage = "slice(start: Integer, end: Optional<Integer>) => string";
1362 let text_vec = string.value.chars().collect::<Vec<_>>();
1363 let len = text_vec.len();
1364
1365 match args.len() {
1366 1 => match args.get("arg0") {
1367 Some(literal) => {
1368 let mut int_start = Literal::get_value::<i64>(
1369 &literal.primitive,
1370 &data.context.flow,
1371 literal.interval,
1372 ERROR_SLICE_ARG_INT.to_owned(),
1373 )?
1374 .to_owned();
1375
1376 if int_start < 0 {
1377 int_start = len as i64 + int_start;
1378 }
1379
1380 let start = match int_start {
1381 value if value >= 0 && (value as usize) < len => value as usize,
1382 _ => {
1383 return Err(gen_error_info(
1384 Position::new(interval, &data.context.flow),
1385 ERROR_SLICE_ARG_LEN.to_owned(),
1386 ))
1387 }
1388 };
1389
1390 let value = text_vec[start..].iter().cloned().collect::<String>();
1391
1392 Ok(PrimitiveString::get_literal(&value, interval))
1393 }
1394 _ => Err(gen_error_info(
1395 Position::new(interval, &data.context.flow),
1396 ERROR_SLICE_ARG_INT.to_owned(),
1397 )),
1398 },
1399 2 => match (args.get("arg0"), args.get("arg1")) {
1400 (Some(literal_start), Some(literal_end)) => {
1401 let mut int_start = Literal::get_value::<i64>(
1402 &literal_start.primitive,
1403 &data.context.flow,
1404 literal_start.interval,
1405 ERROR_SLICE_ARG_INT.to_owned(),
1406 )?
1407 .to_owned();
1408 let mut int_end = Literal::get_value::<i64>(
1409 &literal_end.primitive,
1410 &data.context.flow,
1411 literal_end.interval,
1412 ERROR_SLICE_ARG_INT.to_owned(),
1413 )?
1414 .to_owned();
1415
1416 if int_start < 0 {
1417 int_start = len as i64 + int_start;
1418 }
1419
1420 if int_end.is_negative() {
1421 int_end = len as i64 + int_end;
1422 }
1423 if int_end < int_start {
1424 return Err(gen_error_info(
1425 Position::new(interval, &data.context.flow),
1426 ERROR_SLICE_ARG2.to_owned(),
1427 ));
1428 }
1429
1430 let (start, end) = match (int_start, int_end) {
1431 (start, end)
1432 if int_start >= 0
1433 && end >= 0
1434 && (start as usize) < len
1435 && (end as usize) <= len =>
1436 {
1437 (start as usize, end as usize)
1438 }
1439 _ => {
1440 return Err(gen_error_info(
1441 Position::new(interval, &data.context.flow),
1442 ERROR_SLICE_ARG_LEN.to_owned(),
1443 ))
1444 }
1445 };
1446 let value = text_vec[start..end].iter().cloned().collect::<String>();
1447
1448 Ok(PrimitiveString::get_literal(&value, interval))
1449 }
1450 _ => Err(gen_error_info(
1451 Position::new(interval, &data.context.flow),
1452 ERROR_SLICE_ARG_INT.to_owned(),
1453 )),
1454 },
1455 _ => Err(gen_error_info(
1456 Position::new(interval, &data.context.flow),
1457 format!("usage: {}", usage),
1458 )),
1459 }
1460 }
1461
1462 fn split(
1463 string: &mut PrimitiveString,
1464 args: &HashMap<String, Literal>,
1465 _additional_info: &Option<HashMap<String, Literal>>,
1466 interval: Interval,
1467 data: &mut Data,
1468 _msg_data: &mut MessageData,
1469 _sender: &Option<mpsc::Sender<MSG>>,
1470 ) -> Result<Literal, ErrorInfo> {
1471 let usage = "string(separator: string) => array";
1472
1473 if args.len() != 1 {
1474 return Err(gen_error_info(
1475 Position::new(interval, &data.context.flow),
1476 format!("usage: {}", usage),
1477 ));
1478 }
1479
1480 let separator = match args.get("arg0") {
1481 Some(res) if res.primitive.get_type() == PrimitiveType::PrimitiveString => {
1482 Literal::get_value::<String>(
1483 &res.primitive,
1484 &data.context.flow,
1485 interval,
1486 ERROR_STRING_SPLIT.to_owned(),
1487 )?
1488 }
1489 _ => {
1490 return Err(gen_error_info(
1491 Position::new(interval, &data.context.flow),
1492 ERROR_ARRAY_JOIN.to_owned(),
1493 ));
1494 }
1495 };
1496
1497 let mut vector: Vec<Literal> = Vec::new();
1498
1499 for result in string.value.split(separator) {
1500 vector.push(PrimitiveString::get_literal(result, interval));
1501 }
1502
1503 Ok(PrimitiveArray::get_literal(&vector, interval))
1504 }
1505
1506 fn trim(
1507 string: &mut PrimitiveString,
1508 args: &HashMap<String, Literal>,
1509 _additional_info: &Option<HashMap<String, Literal>>,
1510 interval: Interval,
1511 data: &mut Data,
1512 _msg_data: &mut MessageData,
1513 _sender: &Option<mpsc::Sender<MSG>>,
1514 ) -> Result<Literal, ErrorInfo> {
1515 let usage = "trim() => string";
1516
1517 if !args.is_empty() {
1518 return Err(gen_error_info(
1519 Position::new(interval, &data.context.flow),
1520 format!("usage: {}", usage),
1521 ));
1522 }
1523
1524 let s = &string.value;
1525 Ok(PrimitiveString::get_literal(&s.trim(), interval))
1526 }
1527
1528 fn trim_left(
1529 string: &mut PrimitiveString,
1530 args: &HashMap<String, Literal>,
1531 _additional_info: &Option<HashMap<String, Literal>>,
1532 interval: Interval,
1533 data: &mut Data,
1534 _msg_data: &mut MessageData,
1535 _sender: &Option<mpsc::Sender<MSG>>,
1536 ) -> Result<Literal, ErrorInfo> {
1537 let usage = "trim_left() => string";
1538
1539 if !args.is_empty() {
1540 return Err(gen_error_info(
1541 Position::new(interval, &data.context.flow),
1542 format!("usage: {}", usage),
1543 ));
1544 }
1545
1546 let s = &string.value;
1547 Ok(PrimitiveString::get_literal(&s.trim_start(), interval))
1548 }
1549
1550 fn trim_right(
1551 string: &mut PrimitiveString,
1552 args: &HashMap<String, Literal>,
1553 _additional_info: &Option<HashMap<String, Literal>>,
1554 interval: Interval,
1555 data: &mut Data,
1556 _msg_data: &mut MessageData,
1557 _sender: &Option<mpsc::Sender<MSG>>,
1558 ) -> Result<Literal, ErrorInfo> {
1559 let usage = "trim_right() => string";
1560
1561 if !args.is_empty() {
1562 return Err(gen_error_info(
1563 Position::new(interval, &data.context.flow),
1564 format!("usage: {}", usage),
1565 ));
1566 }
1567
1568 let s = &string.value;
1569 Ok(PrimitiveString::get_literal(&s.trim_end(), interval))
1570 }
1571}
1572
1573impl PrimitiveString {
1575 fn abs(
1576 string: &mut PrimitiveString,
1577 args: &HashMap<String, Literal>,
1578 additional_info: &Option<HashMap<String, Literal>>,
1579 interval: Interval,
1580 data: &mut Data,
1581 msg_data: &mut MessageData,
1582 sender: &Option<mpsc::Sender<MSG>>,
1583 ) -> Result<Literal, ErrorInfo> {
1584 if let Ok(int) = string.value.parse::<i64>() {
1585 let mut primitive = PrimitiveInt::new(int);
1586
1587 let (literal, _right) = primitive.do_exec(
1588 "abs",
1589 args,
1590 &MemoryType::Use,
1591 additional_info,
1592 interval,
1593 &ContentType::Primitive,
1594 data,
1595 msg_data,
1596 sender,
1597 )?;
1598
1599 return Ok(literal);
1600 }
1601 if let Ok(float) = string.value.parse::<f64>() {
1602 let mut primitive = PrimitiveFloat::new(float);
1603
1604 let (literal, _right) = primitive.do_exec(
1605 "abs",
1606 args,
1607 &MemoryType::Use,
1608 additional_info,
1609 interval,
1610 &ContentType::Primitive,
1611 data,
1612 msg_data,
1613 sender,
1614 )?;
1615
1616 return Ok(literal);
1617 }
1618
1619 Err(gen_error_info(
1620 Position::new(interval, &data.context.flow),
1621 format!("[{}] {}", "abs", ERROR_STRING_NUMERIC),
1622 ))
1623 }
1624
1625 fn cos(
1626 string: &mut PrimitiveString,
1627 args: &HashMap<String, Literal>,
1628 additional_info: &Option<HashMap<String, Literal>>,
1629 interval: Interval,
1630 data: &mut Data,
1631 msg_data: &mut MessageData,
1632 sender: &Option<mpsc::Sender<MSG>>,
1633 ) -> Result<Literal, ErrorInfo> {
1634 if let Ok(int) = string.value.parse::<i64>() {
1635 let mut primitive = PrimitiveInt::new(int);
1636
1637 let (literal, _right) = primitive.do_exec(
1638 "cos",
1639 args,
1640 &MemoryType::Use,
1641 additional_info,
1642 interval,
1643 &ContentType::Primitive,
1644 data,
1645 msg_data,
1646 sender,
1647 )?;
1648
1649 return Ok(literal);
1650 }
1651
1652 if let Ok(float) = string.value.parse::<f64>() {
1653 let mut primitive = PrimitiveFloat::new(float);
1654
1655 let (literal, _right) = primitive.do_exec(
1656 "cos",
1657 args,
1658 &MemoryType::Use,
1659 additional_info,
1660 interval,
1661 &ContentType::Primitive,
1662 data,
1663 msg_data,
1664 sender,
1665 )?;
1666
1667 return Ok(literal);
1668 }
1669
1670 Err(gen_error_info(
1671 Position::new(interval, &data.context.flow),
1672 format!("[{}] {}", "cos", ERROR_STRING_NUMERIC),
1673 ))
1674 }
1675
1676 fn ceil(
1677 string: &mut PrimitiveString,
1678 args: &HashMap<String, Literal>,
1679 additional_info: &Option<HashMap<String, Literal>>,
1680 interval: Interval,
1681 data: &mut Data,
1682 msg_data: &mut MessageData,
1683 sender: &Option<mpsc::Sender<MSG>>,
1684 ) -> Result<Literal, ErrorInfo> {
1685 if let Ok(int) = string.value.parse::<i64>() {
1686 let mut primitive = PrimitiveInt::new(int);
1687
1688 let (literal, _right) = primitive.do_exec(
1689 "ceil",
1690 args,
1691 &MemoryType::Use,
1692 additional_info,
1693 interval,
1694 &ContentType::Primitive,
1695 data,
1696 msg_data,
1697 sender,
1698 )?;
1699
1700 return Ok(literal);
1701 }
1702 if let Ok(float) = string.value.parse::<f64>() {
1703 let mut primitive = PrimitiveFloat::new(float);
1704
1705 let (literal, _right) = primitive.do_exec(
1706 "ceil",
1707 args,
1708 &MemoryType::Use,
1709 additional_info,
1710 interval,
1711 &ContentType::Primitive,
1712 data,
1713 msg_data,
1714 sender,
1715 )?;
1716
1717 return Ok(literal);
1718 }
1719
1720 Err(gen_error_info(
1721 Position::new(interval, &data.context.flow),
1722 format!("[{}] {}", "ceil", ERROR_STRING_NUMERIC),
1723 ))
1724 }
1725
1726 fn pow(
1727 string: &mut PrimitiveString,
1728 args: &HashMap<String, Literal>,
1729 additional_info: &Option<HashMap<String, Literal>>,
1730 interval: Interval,
1731 data: &mut Data,
1732 msg_data: &mut MessageData,
1733 sender: &Option<mpsc::Sender<MSG>>,
1734 ) -> Result<Literal, ErrorInfo> {
1735 if let Ok(int) = string.value.parse::<i64>() {
1736 let mut primitive = PrimitiveInt::new(int);
1737
1738 let (literal, _right) = primitive.do_exec(
1739 "pow",
1740 args,
1741 &MemoryType::Use,
1742 additional_info,
1743 interval,
1744 &ContentType::Primitive,
1745 data,
1746 msg_data,
1747 sender,
1748 )?;
1749
1750 return Ok(literal);
1751 }
1752 if let Ok(float) = string.value.parse::<f64>() {
1753 let mut primitive = PrimitiveFloat::new(float);
1754
1755 let (literal, _right) = primitive.do_exec(
1756 "pow",
1757 args,
1758 &MemoryType::Use,
1759 additional_info,
1760 interval,
1761 &ContentType::Primitive,
1762 data,
1763 msg_data,
1764 sender,
1765 )?;
1766
1767 return Ok(literal);
1768 }
1769
1770 Err(gen_error_info(
1771 Position::new(interval, &data.context.flow),
1772 format!("[{}] {}", "pow", ERROR_STRING_NUMERIC),
1773 ))
1774 }
1775
1776 fn floor(
1777 string: &mut PrimitiveString,
1778 args: &HashMap<String, Literal>,
1779 additional_info: &Option<HashMap<String, Literal>>,
1780 interval: Interval,
1781 data: &mut Data,
1782 msg_data: &mut MessageData,
1783 sender: &Option<mpsc::Sender<MSG>>,
1784 ) -> Result<Literal, ErrorInfo> {
1785 if let Ok(int) = string.value.parse::<i64>() {
1786 let mut primitive = PrimitiveInt::new(int);
1787
1788 let (literal, _right) = primitive.do_exec(
1789 "floor",
1790 args,
1791 &MemoryType::Use,
1792 additional_info,
1793 interval,
1794 &ContentType::Primitive,
1795 data,
1796 msg_data,
1797 sender,
1798 )?;
1799
1800 return Ok(literal);
1801 }
1802 if let Ok(float) = string.value.parse::<f64>() {
1803 let mut primitive = PrimitiveFloat::new(float);
1804
1805 let (literal, _right) = primitive.do_exec(
1806 "floor",
1807 args,
1808 &MemoryType::Use,
1809 additional_info,
1810 interval,
1811 &ContentType::Primitive,
1812 data,
1813 msg_data,
1814 sender,
1815 )?;
1816
1817 return Ok(literal);
1818 }
1819
1820 Err(gen_error_info(
1821 Position::new(interval, &data.context.flow),
1822 format!("[{}] {}", "floor", ERROR_STRING_NUMERIC),
1823 ))
1824 }
1825
1826 fn round(
1827 string: &mut PrimitiveString,
1828 args: &HashMap<String, Literal>,
1829 additional_info: &Option<HashMap<String, Literal>>,
1830 interval: Interval,
1831 data: &mut Data,
1832 msg_data: &mut MessageData,
1833 sender: &Option<mpsc::Sender<MSG>>,
1834 ) -> Result<Literal, ErrorInfo> {
1835 if let Ok(int) = string.value.parse::<i64>() {
1836 let mut primitive = PrimitiveInt::new(int);
1837
1838 let (literal, _right) = primitive.do_exec(
1839 "round",
1840 args,
1841 &MemoryType::Use,
1842 additional_info,
1843 interval,
1844 &ContentType::Primitive,
1845 data,
1846 msg_data,
1847 sender,
1848 )?;
1849
1850 return Ok(literal);
1851 }
1852 if let Ok(float) = string.value.parse::<f64>() {
1853 let mut primitive = PrimitiveFloat::new(float);
1854
1855 let (literal, _right) = primitive.do_exec(
1856 "round",
1857 args,
1858 &MemoryType::Use,
1859 additional_info,
1860 interval,
1861 &ContentType::Primitive,
1862 data,
1863 msg_data,
1864 sender,
1865 )?;
1866
1867 return Ok(literal);
1868 }
1869
1870 Err(gen_error_info(
1871 Position::new(interval, &data.context.flow),
1872 format!("[{}] {}", "round", ERROR_STRING_NUMERIC),
1873 ))
1874 }
1875
1876 fn sin(
1877 string: &mut PrimitiveString,
1878 args: &HashMap<String, Literal>,
1879 additional_info: &Option<HashMap<String, Literal>>,
1880 interval: Interval,
1881 data: &mut Data,
1882 msg_data: &mut MessageData,
1883 sender: &Option<mpsc::Sender<MSG>>,
1884 ) -> Result<Literal, ErrorInfo> {
1885 if let Ok(int) = string.value.parse::<i64>() {
1886 let mut primitive = PrimitiveInt::new(int);
1887
1888 let (literal, _right) = primitive.do_exec(
1889 "sin",
1890 args,
1891 &MemoryType::Use,
1892 additional_info,
1893 interval,
1894 &ContentType::Primitive,
1895 data,
1896 msg_data,
1897 sender,
1898 )?;
1899
1900 return Ok(literal);
1901 }
1902 if let Ok(float) = string.value.parse::<f64>() {
1903 let mut primitive = PrimitiveFloat::new(float);
1904
1905 let (literal, _right) = primitive.do_exec(
1906 "sin",
1907 args,
1908 &MemoryType::Use,
1909 additional_info,
1910 interval,
1911 &ContentType::Primitive,
1912 data,
1913 msg_data,
1914 sender,
1915 )?;
1916
1917 return Ok(literal);
1918 }
1919
1920 Err(gen_error_info(
1921 Position::new(interval, &data.context.flow),
1922 format!("[{}] {}", "sin", ERROR_STRING_NUMERIC),
1923 ))
1924 }
1925
1926 fn sqrt(
1927 string: &mut PrimitiveString,
1928 args: &HashMap<String, Literal>,
1929 additional_info: &Option<HashMap<String, Literal>>,
1930 interval: Interval,
1931 data: &mut Data,
1932 msg_data: &mut MessageData,
1933 sender: &Option<mpsc::Sender<MSG>>,
1934 ) -> Result<Literal, ErrorInfo> {
1935 if let Ok(int) = string.value.parse::<i64>() {
1936 let mut primitive = PrimitiveInt::new(int);
1937
1938 let (literal, _right) = primitive.do_exec(
1939 "sqrt",
1940 args,
1941 &MemoryType::Use,
1942 additional_info,
1943 interval,
1944 &ContentType::Primitive,
1945 data,
1946 msg_data,
1947 sender,
1948 )?;
1949
1950 return Ok(literal);
1951 }
1952 if let Ok(float) = string.value.parse::<f64>() {
1953 let mut primitive = PrimitiveFloat::new(float);
1954
1955 let (literal, _right) = primitive.do_exec(
1956 "sqrt",
1957 args,
1958 &MemoryType::Use,
1959 additional_info,
1960 interval,
1961 &ContentType::Primitive,
1962 data,
1963 msg_data,
1964 sender,
1965 )?;
1966
1967 return Ok(literal);
1968 }
1969
1970 Err(gen_error_info(
1971 Position::new(interval, &data.context.flow),
1972 format!("[{}] {}", "sqrt", ERROR_STRING_NUMERIC),
1973 ))
1974 }
1975
1976 fn tan(
1977 string: &mut PrimitiveString,
1978 args: &HashMap<String, Literal>,
1979 additional_info: &Option<HashMap<String, Literal>>,
1980 interval: Interval,
1981 data: &mut Data,
1982 msg_data: &mut MessageData,
1983 sender: &Option<mpsc::Sender<MSG>>,
1984 ) -> Result<Literal, ErrorInfo> {
1985 if let Ok(int) = string.value.parse::<i64>() {
1986 let mut primitive = PrimitiveInt::new(int);
1987
1988 let (literal, _right) = primitive.do_exec(
1989 "tan",
1990 args,
1991 &MemoryType::Use,
1992 additional_info,
1993 interval,
1994 &ContentType::Primitive,
1995 data,
1996 msg_data,
1997 sender,
1998 )?;
1999
2000 return Ok(literal);
2001 }
2002 if let Ok(float) = string.value.parse::<f64>() {
2003 let mut primitive = PrimitiveFloat::new(float);
2004
2005 let (literal, _right) = primitive.do_exec(
2006 "tan",
2007 args,
2008 &MemoryType::Use,
2009 additional_info,
2010 interval,
2011 &ContentType::Primitive,
2012 data,
2013 msg_data,
2014 sender,
2015 )?;
2016
2017 return Ok(literal);
2018 }
2019
2020 Err(gen_error_info(
2021 Position::new(interval, &data.context.flow),
2022 format!("[{}] {}", "tan", ERROR_STRING_NUMERIC),
2023 ))
2024 }
2025
2026 fn to_int(
2027 string: &mut PrimitiveString,
2028 args: &HashMap<String, Literal>,
2029 additional_info: &Option<HashMap<String, Literal>>,
2030 interval: Interval,
2031 data: &mut Data,
2032 msg_data: &mut MessageData,
2033 sender: &Option<mpsc::Sender<MSG>>,
2034 ) -> Result<Literal, ErrorInfo> {
2035 if let Ok(int) = string.value.parse::<i64>() {
2036 let mut primitive = PrimitiveInt::new(int);
2037
2038 let (literal, _right) = primitive.do_exec(
2039 "to_int",
2040 args,
2041 &MemoryType::Use,
2042 additional_info,
2043 interval,
2044 &ContentType::Primitive,
2045 data,
2046 msg_data,
2047 sender,
2048 )?;
2049
2050 return Ok(literal);
2051 }
2052 if let Ok(float) = string.value.parse::<f64>() {
2053 let mut primitive = PrimitiveFloat::new(float);
2054
2055 let (literal, _right) = primitive.do_exec(
2056 "to_int",
2057 args,
2058 &MemoryType::Use,
2059 additional_info,
2060 interval,
2061 &ContentType::Primitive,
2062 data,
2063 msg_data,
2064 sender,
2065 )?;
2066
2067 return Ok(literal);
2068 }
2069
2070 Err(gen_error_info(
2071 Position::new(interval, &data.context.flow),
2072 format!("[{}] {}", "to_int", ERROR_STRING_NUMERIC),
2073 ))
2074 }
2075
2076 fn to_float(
2077 string: &mut PrimitiveString,
2078 args: &HashMap<String, Literal>,
2079 additional_info: &Option<HashMap<String, Literal>>,
2080 interval: Interval,
2081 data: &mut Data,
2082 msg_data: &mut MessageData,
2083 sender: &Option<mpsc::Sender<MSG>>,
2084 ) -> Result<Literal, ErrorInfo> {
2085 if let Ok(int) = string.value.parse::<i64>() {
2086 let mut primitive = PrimitiveInt::new(int);
2087
2088 let (literal, _right) = primitive.do_exec(
2089 "to_float",
2090 args,
2091 &MemoryType::Use,
2092 additional_info,
2093 interval,
2094 &ContentType::Primitive,
2095 data,
2096 msg_data,
2097 sender,
2098 )?;
2099
2100 return Ok(literal);
2101 }
2102 if let Ok(float) = string.value.parse::<f64>() {
2103 let mut primitive = PrimitiveFloat::new(float);
2104
2105 let (literal, _right) = primitive.do_exec(
2106 "to_float",
2107 args,
2108 &MemoryType::Use,
2109 additional_info,
2110 interval,
2111 &ContentType::Primitive,
2112 data,
2113 msg_data,
2114 sender,
2115 )?;
2116
2117 return Ok(literal);
2118 }
2119
2120 Err(gen_error_info(
2121 Position::new(interval, &data.context.flow),
2122 format!("[{}] {}", "to_float", ERROR_STRING_NUMERIC),
2123 ))
2124 }
2125}
2126
2127impl PrimitiveString {
2132 pub fn new(value: &str) -> Self {
2133 Self {
2134 value: value.to_owned(),
2135 }
2136 }
2137
2138 pub fn get_literal(string: &str, interval: Interval) -> Literal {
2139 let primitive = Box::new(PrimitiveString::new(string));
2140
2141 Literal {
2142 content_type: "string".to_owned(),
2143 primitive,
2144 additional_info: None,
2145 secure_variable: false,
2146 interval,
2147 }
2148 }
2149
2150 pub fn get_array_char(string: String, interval: Interval) -> Vec<Literal> {
2151 let array = string
2152 .chars()
2153 .map(|c| {
2154 let interval = interval.clone();
2155 PrimitiveString::get_literal(&c.to_string(), interval)
2156 })
2157 .collect::<Vec<Literal>>();
2158
2159 array
2160 }
2161}
2162
2163#[typetag::serde]
2164impl Primitive for PrimitiveString {
2165 fn is_eq(&self, other: &dyn Primitive) -> bool {
2166 if let Some(rhs) = other.as_any().downcast_ref::<PrimitiveString>() {
2167 return match (get_integer(&self.value), get_integer(&rhs.value)) {
2168 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => (lhs as f64) == rhs,
2169 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => lhs == (rhs as f64),
2170 _ => self.value == rhs.value,
2171 };
2172 }
2173
2174 false
2175 }
2176
2177 fn is_cmp(&self, other: &dyn Primitive) -> Option<Ordering> {
2178 if let Some(rhs) = other.as_any().downcast_ref::<PrimitiveString>() {
2179 return match (get_integer(&self.value), get_integer(&rhs.value)) {
2180 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => (lhs as f64).partial_cmp(&rhs),
2181 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => lhs.partial_cmp(&(rhs as f64)),
2182 _ => self.value.partial_cmp(&rhs.value),
2183 };
2184 }
2185
2186 None
2187 }
2188
2189 fn do_add(&self, other: &dyn Primitive) -> Result<Box<dyn Primitive>, String> {
2190 let rhs = match other.as_any().downcast_ref::<PrimitiveString>() {
2191 Some(res) => res,
2192 None => {
2193 return Err(ERROR_STRING_RHS.to_owned());
2194 }
2195 };
2196
2197 if let Ok(number) = get_integer(&self.value) {
2198 match (number, get_integer(&rhs.value)) {
2199 (Integer::Int(lhs), Ok(Integer::Int(rhs))) => {
2200 Ok(Box::new(PrimitiveInt::new(lhs + rhs)))
2201 }
2202 (Integer::Float(lhs), Ok(Integer::Float(rhs))) => {
2203 Ok(Box::new(PrimitiveFloat::new(lhs + rhs)))
2204 }
2205 (Integer::Int(lhs), Ok(Integer::Float(rhs))) => {
2206 Ok(Box::new(PrimitiveFloat::new(lhs as f64 + rhs)))
2207 }
2208 (Integer::Float(lhs), Ok(Integer::Int(rhs))) => {
2209 Ok(Box::new(PrimitiveFloat::new(lhs + rhs as f64)))
2210 }
2211 _ => Err(format!(
2212 "{} {:?} + {:?}",
2213 ERROR_ILLEGAL_OPERATION,
2214 self.get_type(),
2215 other.get_type()
2216 )),
2217 }
2218 } else {
2219 let mut new_string = self.value.clone();
2220
2221 new_string.push_str(&rhs.value);
2222
2223 Ok(Box::new(PrimitiveString::new(&new_string)))
2224 }
2225 }
2226
2227 fn do_sub(&self, other: &dyn Primitive) -> Result<Box<dyn Primitive>, String> {
2228 let rhs = match other.as_any().downcast_ref::<PrimitiveString>() {
2229 Some(res) => res,
2230 None => {
2231 return Err(ERROR_STRING_RHS.to_owned());
2232 }
2233 };
2234
2235 match (get_integer(&self.value), get_integer(&rhs.value)) {
2236 (Ok(Integer::Int(lhs)), Ok(Integer::Int(rhs))) => {
2237 Ok(Box::new(PrimitiveInt::new(lhs - rhs)))
2238 }
2239 (Ok(Integer::Float(lhs)), Ok(Integer::Float(rhs))) => {
2240 Ok(Box::new(PrimitiveFloat::new(lhs - rhs)))
2241 }
2242 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => {
2243 Ok(Box::new(PrimitiveFloat::new(lhs as f64 - rhs)))
2244 }
2245 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => {
2246 Ok(Box::new(PrimitiveFloat::new(lhs - rhs as f64)))
2247 }
2248 _ => Err(format!(
2249 "{} {:?} - {:?}",
2250 ERROR_ILLEGAL_OPERATION,
2251 self.get_type(),
2252 other.get_type()
2253 )),
2254 }
2255 }
2256
2257 fn do_div(&self, other: &dyn Primitive) -> Result<Box<dyn Primitive>, String> {
2258 let rhs = match other.as_any().downcast_ref::<PrimitiveString>() {
2259 Some(res) => res,
2260 None => {
2261 return Err(ERROR_STRING_RHS.to_owned());
2262 }
2263 };
2264
2265 match (get_integer(&self.value), get_integer(&rhs.value)) {
2266 (Ok(Integer::Int(lhs)), Ok(Integer::Int(rhs))) => {
2267 check_division_by_zero_i64(lhs, rhs)?;
2268
2269 Ok(Box::new(PrimitiveInt::new(lhs / rhs)))
2270 }
2271 (Ok(Integer::Float(lhs)), Ok(Integer::Float(rhs))) => {
2272 check_division_by_zero_i64(lhs as i64, rhs as i64)?;
2273
2274 Ok(Box::new(PrimitiveFloat::new(lhs / rhs)))
2275 }
2276 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => {
2277 check_division_by_zero_i64(lhs, rhs as i64)?;
2278
2279 Ok(Box::new(PrimitiveFloat::new(lhs as f64 / rhs)))
2280 }
2281 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => {
2282 check_division_by_zero_i64(lhs as i64, rhs)?;
2283
2284 Ok(Box::new(PrimitiveFloat::new(lhs / rhs as f64)))
2285 }
2286 _ => Err(format!(
2287 "{} {:?} / {:?}",
2288 ERROR_ILLEGAL_OPERATION,
2289 self.get_type(),
2290 other.get_type()
2291 )),
2292 }
2293 }
2294
2295 fn do_mul(&self, other: &dyn Primitive) -> Result<Box<dyn Primitive>, String> {
2296 let rhs = match other.as_any().downcast_ref::<PrimitiveString>() {
2297 Some(res) => res,
2298 None => {
2299 return Err(ERROR_STRING_RHS.to_owned());
2300 }
2301 };
2302
2303 match (get_integer(&self.value), get_integer(&rhs.value)) {
2304 (Ok(Integer::Int(lhs)), Ok(Integer::Int(rhs))) => {
2305 Ok(Box::new(PrimitiveInt::new(lhs * rhs)))
2306 }
2307 (Ok(Integer::Float(lhs)), Ok(Integer::Float(rhs))) => {
2308 Ok(Box::new(PrimitiveFloat::new(lhs * rhs)))
2309 }
2310 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => {
2311 Ok(Box::new(PrimitiveFloat::new(lhs as f64 * rhs)))
2312 }
2313 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => {
2314 Ok(Box::new(PrimitiveFloat::new(lhs * rhs as f64)))
2315 }
2316 _ => Err(format!(
2317 "{} {:?} * {:?}",
2318 ERROR_ILLEGAL_OPERATION,
2319 self.get_type(),
2320 other.get_type()
2321 )),
2322 }
2323 }
2324
2325 fn do_rem(&self, other: &dyn Primitive) -> Result<Box<dyn Primitive>, String> {
2326 let rhs = match other.as_any().downcast_ref::<PrimitiveString>() {
2327 Some(res) => res,
2328 None => {
2329 return Err(ERROR_STRING_RHS.to_owned());
2330 }
2331 };
2332
2333 match (get_integer(&self.value), get_integer(&rhs.value)) {
2334 (Ok(Integer::Int(lhs)), Ok(Integer::Int(rhs))) => {
2335 Ok(Box::new(PrimitiveInt::new(lhs % rhs)))
2336 }
2337 (Ok(Integer::Float(lhs)), Ok(Integer::Float(rhs))) => {
2338 Ok(Box::new(PrimitiveFloat::new(lhs % rhs)))
2339 }
2340 (Ok(Integer::Int(lhs)), Ok(Integer::Float(rhs))) => {
2341 Ok(Box::new(PrimitiveFloat::new(lhs as f64 % rhs)))
2342 }
2343 (Ok(Integer::Float(lhs)), Ok(Integer::Int(rhs))) => {
2344 Ok(Box::new(PrimitiveFloat::new(lhs * rhs as f64)))
2345 }
2346 _ => Err(format!(
2347 "{} {:?} % {:?}",
2348 ERROR_ILLEGAL_OPERATION,
2349 self.get_type(),
2350 other.get_type()
2351 )),
2352 }
2353 }
2354
2355 fn as_debug(&self) -> &dyn std::fmt::Debug {
2356 self
2357 }
2358
2359 fn as_any(&self) -> &dyn std::any::Any {
2360 self
2361 }
2362
2363 fn get_type(&self) -> PrimitiveType {
2364 PrimitiveType::PrimitiveString
2365 }
2366
2367 fn as_box_clone(&self) -> Box<dyn Primitive> {
2368 Box::new((*self).clone())
2369 }
2370
2371 fn to_json(&self) -> serde_json::Value {
2372 serde_json::json!(self.value)
2373 }
2374
2375 fn format_mem(&self, _content_type: &str, _first: bool) -> serde_json::Value {
2376 serde_json::json!(self.value)
2377 }
2378
2379 fn to_string(&self) -> String {
2380 self.value.to_owned()
2381 }
2382
2383 fn as_bool(&self) -> bool {
2384 true
2385 }
2386
2387 fn get_value(&self) -> &dyn std::any::Any {
2388 &self.value
2389 }
2390
2391 fn get_mut_value(&mut self) -> &mut dyn std::any::Any {
2392 &mut self.value
2393 }
2394
2395 fn to_msg(&self, _content_type: String) -> Message {
2396 let mut hashmap: HashMap<String, Literal> = HashMap::new();
2397
2398 hashmap.insert(
2399 "text".to_owned(),
2400 Literal {
2401 content_type: "string".to_owned(),
2402 primitive: Box::new(PrimitiveString::new(&self.value)),
2403 additional_info: None,
2404 secure_variable: false,
2405 interval: Interval {
2406 start_column: 0,
2407 start_line: 0,
2408 offset: 0,
2409 end_line: None,
2410 end_column: None,
2411 },
2412 },
2413 );
2414
2415 let mut result = PrimitiveObject::get_literal(
2416 &hashmap,
2417 Interval {
2418 start_column: 0,
2419 start_line: 0,
2420 offset: 0,
2421 end_line: None,
2422 end_column: None,
2423 },
2424 );
2425 result.set_content_type("text");
2426
2427 Message {
2428 content_type: result.content_type,
2429 content: result.primitive.to_json(),
2430 }
2431 }
2432
2433 fn do_exec(
2434 &mut self,
2435 name: &str,
2436 args: &HashMap<String, Literal>,
2437 mem_type: &MemoryType,
2438 additional_info: &Option<HashMap<String, Literal>>,
2439 interval: Interval,
2440 _content_type: &ContentType,
2441 data: &mut Data,
2442 msg_data: &mut MessageData,
2443 sender: &Option<mpsc::Sender<MSG>>,
2444 ) -> Result<(Literal, Right), ErrorInfo> {
2445 if let Some((f, right)) = FUNCTIONS.get(name) {
2446 if *mem_type == MemoryType::Constant && *right == Right::Write {
2447 return Err(gen_error_info(
2448 Position::new(interval, &data.context.flow),
2449 format!("{}", ERROR_CONSTANT_MUTABLE_FUNCTION),
2450 ));
2451 } else {
2452 let res = f(
2453 self,
2454 args,
2455 additional_info,
2456 interval,
2457 data,
2458 msg_data,
2459 sender,
2460 )?;
2461
2462 return Ok((res, *right));
2463 }
2464 }
2465
2466 Err(gen_error_info(
2467 Position::new(interval, &data.context.flow),
2468 format!("[{}] {}", name, ERROR_STRING_UNKNOWN_METHOD),
2469 ))
2470 }
2471}