csml_interpreter/data/primitive/
string.rs

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;
16// use http::Uri;
17use 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
26////////////////////////////////////////////////////////////////////////////////
27// DATA STRUCTURES
28////////////////////////////////////////////////////////////////////////////////
29
30type 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
102////////////////////////////////////////////////////////////////////////////////
103// PRIVATE FUNCTIONS
104////////////////////////////////////////////////////////////////////////////////
105
106fn 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
181////////////////////////////////////////////////////////////////////////////////
182// METHOD FUNCTIONS
183////////////////////////////////////////////////////////////////////////////////
184
185impl 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
1573// memory type can be set tu 'use' because the result of the operation will create a new literal.
1574impl 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
2127////////////////////////////////////////////////////////////////////////////////
2128// PUBLIC FUNCTIONS
2129////////////////////////////////////////////////////////////////////////////////
2130
2131impl 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}