tiny_web/sys/
html.rs

1use std::{
2    collections::{btree_map::Entry, BTreeMap},
3    fs::{read_dir, read_to_string},
4    path::PathBuf,
5    sync::Arc,
6};
7
8#[cfg(debug_assertions)]
9use std::time::SystemTime;
10
11#[cfg(debug_assertions)]
12use tokio::fs;
13
14use crate::fnv1a_64;
15
16use super::{action::Answer, data::Data, log::Log};
17
18/// The filter of the variable
19///
20/// # Values
21///
22/// * `None` - None filter.
23/// * `Raw` - Do not escape the output.
24/// * `Len` - Use function len().
25/// * `Set` - Values is set.
26/// * `Unset` - Values is unset.
27/// * `Index` - Index of loop.
28/// * `Dump` - Dump of value.
29#[derive(Debug, Clone, PartialEq)]
30pub(crate) enum Filter {
31    /// None filter
32    None,
33    /// Do not escape the output
34    Raw,
35    /// Use function len()
36    Len,
37    /// Values is set
38    Set,
39    /// Values is unset
40    Unset,
41    /// Index of loop
42    Index,
43    /// Dump of value
44    Dump,
45}
46
47/// The value of the variable
48///
49/// # Values
50///
51/// * `Number(i64)` - i64 value.
52/// * `Value { name: Vec<String>, filter: Filter }` - Variable name and its filter.
53#[derive(Debug, Clone)]
54pub(crate) enum Value {
55    /// i64 value
56    Number(i64),
57    /// Variable name and its filter
58    Value { name: Vec<String>, filter: Filter },
59}
60
61/// For branch
62///
63/// # Values
64///
65/// * `name: Value` - The value.
66/// * `local: String` - Local (inside) name of value.
67/// * `nodes: Nodes` - Nodes inside a loop.
68/// * `empty: Option<Nodes>` - Nodes that will be executed if the cycle is empty.
69#[derive(Debug, Clone)]
70pub(crate) struct For {
71    /// The value
72    name: Value,
73    /// Local (inside) name of value
74    local: String,
75    /// Nodes inside a loop
76    nodes: Nodes,
77    /// Nodes that will be executed if the cycle is empty
78    empty: Option<Nodes>,
79}
80
81/// Equality comparisons
82///
83/// # Values
84///
85/// * `None` - None comparisons.
86/// * `Eq` - `==`.
87/// * `Ne` - `!=`.
88/// * `Lt` - `<`.
89/// * `Le` - `<=`.
90/// * `Gt` - `>`.
91/// * `Ge` - `>=`.
92#[derive(Debug, Clone, PartialEq)]
93pub(crate) enum Eq {
94    /// None comparisons
95    None,
96    /// `==`
97    Equal,
98    /// `!=`
99    NotEqual,
100    /// `<`
101    LessThan,
102    /// `<=`
103    LessThanOrEqual,
104    /// `>`
105    GreaterThan,
106    /// `>=`
107    GreaterThanOrEqual,
108}
109
110/// Condition for `If`
111///
112/// # Values
113///
114/// * `val: Value` - Value.
115/// * `eq: Eq` - Equality comparisons.
116/// * `other: Option<Value>` - Second values if needed.
117#[derive(Debug, Clone)]
118pub(crate) struct ExpValue {
119    /// Value
120    val: Value,
121    /// Equality comparisons
122    eq: Eq,
123    /// Second values if needed
124    other: Option<Value>,
125}
126
127/// Expression for `If`
128///
129/// # Values
130///
131/// * `val: ExpValue` - Condition for `If`.
132/// * `nodes: Nodes` - Nodes if true.
133#[derive(Debug, Clone)]
134pub(crate) struct Exp {
135    /// Condition for `If`
136    val: ExpValue,
137    /// Nodes if true
138    nodes: Nodes,
139}
140
141/// If branch
142///
143/// # Values
144///
145/// * `exp: Vec<Exp>` - List of expression for `If`.
146/// * `else_exp: Option<Nodes>` - Nodes if else.
147#[derive(Debug, Clone)]
148pub(crate) struct If {
149    /// List of expression for `If`
150    exp: Vec<Exp>,
151    /// Nodes if else
152    else_exp: Option<Nodes>,
153}
154
155/// Echo value branch
156///
157/// # Values
158///
159/// * `val: Value` - Value.
160/// * `begin: bool` - Trim text in front.
161/// * `end: bool` - Trim the text at the back.
162#[derive(Debug, Clone)]
163pub(crate) struct EchoValue {
164    /// Value
165    val: Value,
166    /// Trim text in front
167    begin: bool,
168    /// Trim the text at the back
169    end: bool,
170}
171
172/// Describes a Node of template.
173///
174/// # Values
175///
176/// * `Text(String)` - Simple text.
177/// * `Value(EchoValue)` - Echo value.
178/// * `For(For)` - For value.
179/// * `IF(If)` - If value.
180#[derive(Debug, Clone)]
181pub(crate) enum Node {
182    /// Simple text
183    Text(String),
184    /// Echo value
185    Value(EchoValue),
186    /// For value
187    For(For),
188    /// If value
189    IF(If),
190}
191
192/// Conditions in template
193#[derive(Debug, Clone, PartialEq)]
194enum ItemCondition {
195    /// None conditions
196    None,
197    /// Simple text
198    Text,
199    /// If condition
200    If,
201    /// ElseIf condition
202    ElseIf,
203    /// Else condition
204    Else,
205    /// EndIf condition
206    EndIf,
207    /// For condition
208    For,
209    /// ElseFor condition
210    ElseFor,
211    /// EndFor condition
212    EndFor,
213}
214
215/// Item of condition for parsing tmplate
216#[derive(Debug, Clone)]
217struct Item {
218    /// Begin position of condition
219    begin: usize,
220    /// Begin position of condition
221    end: usize,
222    /// Content of condition
223    text: String,
224    /// Level of condition
225    level: usize,
226    /// Conditions in template
227    cond: ItemCondition,
228    /// Childen list of item
229    child: Vec<Item>,
230}
231
232/// Template nodes
233pub(crate) type Nodes = Vec<Node>;
234
235/// Html template marker
236///
237/// # Values
238///
239/// * `list: BTreeMap<i64, BTreeMap<i64, Arc<BTreeMap<i64, Nodes>>>>` - List of templates.
240#[derive(Debug)]
241pub(crate) struct Html {
242    /// List of templates
243    ///
244    /// # Index
245    ///
246    /// * 1 - Module ID
247    /// * 2 - Class ID
248    /// * 3 - Template ID
249    /// * 4 - List of Nodes
250    #[allow(clippy::type_complexity)]
251    pub list: BTreeMap<i64, BTreeMap<i64, Arc<BTreeMap<i64, Nodes>>>>,
252    /// SystemTime last modification
253    #[cfg(debug_assertions)]
254    pub(crate) last: SystemTime,
255    /// Sum of all filename hashes
256    #[cfg(debug_assertions)]
257    hash: i128,
258    /// Path to templates' files
259    root: Arc<String>,
260}
261
262impl Html {
263    /// Reads ./app/ and recognizes templates
264    ///
265    /// # Description
266    ///
267    /// In the root directory of the project (`Init::root_path`) the `app` directory is searched.
268    ///
269    /// Template files are logically located in this directory.  
270    /// Each file must be named and have the extension `.html`
271    ///
272    /// ## Example:
273    ///
274    /// * index template:   ./app/module_name/class_name/index.html
275    /// * not_found template: ./app/module_name/class_name/not_found.html
276    ///
277    /// module_name - Name of the module  <br />
278    /// class_name - Class name  
279    ///
280    /// ## Use in the template:
281    ///
282    /// To get a template, it is enough to set the `this.render("template")` function <br />
283    /// If no template is found, the asnwer will be None.
284    ///
285    /// # Used symbols
286    ///
287    /// @ - If it is at the beginning, then do not change the expression after it, but simply remove this symbol
288    /// {{- trim left
289    /// -}} trim right
290    /// {{ name }} htmlspecialchar
291    /// {{ name.title }} htmlspecialchar
292    /// {{ name.title.title_ua }} htmlspecialchar
293    /// {{ name|raw }}
294    /// {{ name|dump }}
295    /// {# comment #}
296    ///
297    /// {% if bool %}
298    /// {% if bool|len %}
299    /// {% if bool|set %}
300    /// {% if bool|unset %}
301    /// {% if int > 0 %} > >= < <= = !=
302    /// {% elseif ... %}
303    /// {% else ... %}
304    /// {% endif ... %}
305    ///
306    /// {% for arr in array %}
307    ///   {{ arr|idx }}
308    ///   {{ arr.title|raw }}
309    ///   {{ arr.body }}
310    /// {% elsefor %} empty or null array
311    /// {% endfor %}
312    pub async fn new(root: Arc<String>) -> Html {
313        #[cfg(debug_assertions)]
314        let last_time = SystemTime::UNIX_EPOCH;
315
316        let mut html = Html {
317            list: BTreeMap::new(),
318            #[cfg(debug_assertions)]
319            last: last_time,
320            #[cfg(debug_assertions)]
321            hash: 0,
322            root: Arc::new(root.as_str().to_owned()),
323        };
324        html.load().await;
325        html
326    }
327
328    /// Gets temptale from String
329    fn parse(orig: &str) -> Result<Nodes, String> {
330        if orig.is_empty() {
331            return Ok(Vec::new());
332        }
333        let mut shift = 1;
334        let mut last = 1;
335
336        let mut html = String::with_capacity(orig.len() + 4);
337        let mut len = orig.len();
338        html.push('_');
339        html.push_str(orig);
340        html.push_str("___");
341
342        let mut current;
343        let mut prev;
344
345        let mut result = String::with_capacity(len);
346
347        // remove comment
348        let mut ignore = None;
349        while shift < len + 1 {
350            // Take 2 symbols
351            current = unsafe { html.get_unchecked(shift..shift + 2) };
352            // Take prev symbol
353            prev = unsafe { html.get_unchecked(shift - 1..shift) };
354            match current {
355                "{#" => {
356                    if prev == "@" {
357                        ignore = Some(shift - 1);
358                    } else {
359                        result.push_str(&html[last..shift]);
360                    }
361                    shift += 2;
362                }
363                "#}" => {
364                    if let Some(idx) = ignore {
365                        result.push_str(&html[last..idx]);
366                        result.push_str(&html[idx + 1..shift + 2]);
367                        ignore = None;
368                    }
369                    shift += 2;
370                    last = shift;
371                }
372                _ => shift += 1,
373            }
374        }
375        result.push_str(&html[last..len + 1]);
376
377        let mut html = String::with_capacity(result.len() + 4);
378        len = result.len();
379        html.push('_');
380        html.push_str(&result);
381        html.push_str("___");
382
383        // read conditions
384        shift = 1;
385        last = 1;
386
387        let mut order = false;
388        let mut idx = 0;
389        let mut vec = Vec::new();
390        while shift < len + 1 {
391            // Take 2 symbols
392            current = unsafe { html.get_unchecked(shift..shift + 2) };
393            // Take prev symbol
394            prev = unsafe { html.get_unchecked(shift - 1..shift) };
395            match (current, order) {
396                // Begin condition
397                ("{%", false) => {
398                    if prev == "@" {
399                        ignore = Some(0);
400                    } else {
401                        idx = shift + 2;
402                    }
403                    shift += 2;
404                    order = true;
405                }
406                // End condition
407                ("%}", true) => {
408                    if ignore.is_some() {
409                        ignore = None;
410                    } else {
411                        vec.push(Item {
412                            begin: last - 1,
413                            end: idx - 3,
414                            text: html[last..idx - 2].to_owned(),
415                            level: 0,
416                            cond: ItemCondition::Text,
417                            child: Vec::new(),
418                        });
419                        vec.push(Item {
420                            begin: idx - 1,
421                            end: shift - 1,
422                            text: html[idx..shift].trim().to_owned(),
423                            level: 0,
424                            cond: ItemCondition::None,
425                            child: Vec::new(),
426                        });
427                        last = shift + 2;
428                    }
429                    shift += 2;
430                    order = false;
431                }
432                ("{%", true) | ("%}", false) => {
433                    return Err(format!(r#"Mismatched parentheses in "{}""#, Html::get_err_msg(shift, shift, &html)));
434                }
435                _ => shift += 1,
436            }
437        }
438        // Add closing text
439        vec.push(Item {
440            begin: last - 1,
441            end: len,
442            text: html[last..len + 1].to_owned(),
443            level: 0,
444            cond: ItemCondition::Text,
445            child: Vec::new(),
446        });
447
448        // check tree conditions
449        let mut level = 0;
450        for i in vec.as_mut_slice() {
451            if i.cond != ItemCondition::Text {
452                idx = match i.text.find(' ') {
453                    Some(idx) => idx,
454                    None => i.text.len(),
455                };
456                match &i.text[..idx] {
457                    "if" => {
458                        level += 1;
459                        i.level = level;
460                        i.cond = ItemCondition::If;
461                        if idx == i.text.len() {
462                            return Err(format!(
463                                r#"The expression has an incorrect format in "{}""#,
464                                Html::get_err_msg(i.begin, i.end, &html)
465                            ));
466                        }
467                        i.text = i.text[idx + 1..].to_string();
468                    }
469                    "elseif" => {
470                        i.level = level;
471                        i.cond = ItemCondition::ElseIf;
472                        if idx == i.text.len() {
473                            return Err(format!(
474                                r#"The expression has an incorrect format in "{}""#,
475                                Html::get_err_msg(i.begin, i.end, &html)
476                            ));
477                        }
478                        i.text = i.text[idx + 1..].to_string();
479                    }
480                    "else" => {
481                        i.level = level;
482                        i.cond = ItemCondition::Else;
483                        if idx != i.text.len() {
484                            return Err(format!(
485                                r#"The expression has an incorrect format in "{}""#,
486                                Html::get_err_msg(i.begin, i.end, &html)
487                            ));
488                        }
489                        i.text = String::new();
490                    }
491                    "endif" => {
492                        i.level = level;
493                        level -= 1;
494                        i.cond = ItemCondition::EndIf;
495                        if idx != i.text.len() {
496                            return Err(format!(
497                                r#"The expression has an incorrect format in "{}""#,
498                                Html::get_err_msg(i.begin, i.end, &html)
499                            ));
500                        }
501                        i.text = String::new();
502                    }
503                    "for" => {
504                        level += 1;
505                        i.level = level;
506                        i.cond = ItemCondition::For;
507                        if idx == i.text.len() {
508                            return Err(format!(
509                                r#"The expression has an incorrect format in "{}""#,
510                                Html::get_err_msg(i.begin, i.end, &html)
511                            ));
512                        }
513                        i.text = i.text[idx + 1..].to_string();
514                    }
515                    "elsefor" => {
516                        i.level = level;
517                        i.cond = ItemCondition::ElseFor;
518                        if idx != i.text.len() {
519                            return Err(format!(
520                                r#"The expression has an incorrect format in "{}""#,
521                                Html::get_err_msg(i.begin, i.end, &html)
522                            ));
523                        }
524                        i.text = String::new();
525                    }
526                    "endfor" => {
527                        i.level = level;
528                        level -= 1;
529                        i.cond = ItemCondition::EndFor;
530                        if idx != i.text.len() {
531                            return Err(format!(
532                                r#"The expression has an incorrect format in "{}""#,
533                                Html::get_err_msg(i.begin, i.end, &html)
534                            ));
535                        }
536                        i.text = String::new();
537                    }
538                    _ => {
539                        return Err(format!(r#"Unrecognized operator in "{}""#, Html::get_err_msg(i.begin, i.end, &html)));
540                    }
541                }
542            } else {
543                i.level = level + 1;
544            }
545        }
546        if level != 0 {
547            return Err("No closing tag found".to_owned());
548        }
549        // build tree
550        let vec = match Html::build_tree(&vec, &mut 0, 1) {
551            Some(v) => v,
552            None => return Err("The nesting structure does not match".to_owned()),
553        };
554        // create template
555        let mut vec = match Html::build_vec(&vec, &html) {
556            Ok(vec) => vec,
557            Err(e) => return Err(format!("An error occurred while creating the template nodes: {}", e)),
558        };
559        // Clear templates
560        let mut remove = false;
561        if let Node::Text(node) = unsafe { vec.get_unchecked_mut(0) } {
562            if node.is_empty() {
563                remove = true;
564            }
565        }
566        if remove {
567            vec.remove(0);
568            remove = false;
569        }
570        let len = vec.len() - 1;
571        if let Node::Text(node) = unsafe { vec.get_unchecked_mut(len) } {
572            if node.is_empty() {
573                remove = true;
574            }
575        }
576        if remove {
577            vec.pop();
578        }
579        Ok(vec)
580    }
581
582    /// Check name of value A-Za-z0-9_|
583    fn is_valid_input(val: &str) -> bool {
584        if val.is_empty() {
585            return false;
586        }
587        let val = val.as_bytes();
588        for c in val {
589            match *c {
590                46 | 48..=57 | 65..=90 | 95 | 97..=122 => {}
591                _ => return false,
592            }
593        }
594        !(48..=57).contains(unsafe { val.get_unchecked(0) })
595    }
596
597    /// Check name of value A-Za-z0-9_
598    fn is_simple_name(val: &str) -> bool {
599        if val.is_empty() {
600            return false;
601        }
602        let val = val.as_bytes();
603        for c in val {
604            match *c {
605                48..=57 | 65..=90 | 95 | 97..=122 => {}
606                _ => return false,
607            }
608        }
609        !(48..=57).contains(unsafe { val.get_unchecked(0) })
610    }
611
612    /// Check name of value 0-9
613    fn is_number_input(val: &str) -> bool {
614        if val.is_empty() {
615            return false;
616        }
617        let val = val.as_bytes();
618        for c in val {
619            match *c {
620                48..=57 => {}
621                _ => return false,
622            }
623        }
624        true
625    }
626
627    /// Get Value fron text
628    fn get_val(val: &str, exp: Option<bool>) -> Option<Value> {
629        if !val.is_empty() {
630            match val.find('|') {
631                Some(idx) => {
632                    let v = &val[0..idx];
633                    if Html::is_valid_input(v) {
634                        let vl: Vec<&str> = v.split('.').collect();
635                        match &val[idx + 1..] {
636                            "len" => Some(Value::Value {
637                                name: vl.iter().map(|s| s.to_string()).collect(),
638                                filter: Filter::Len,
639                            }),
640                            "set" => Some(Value::Value {
641                                name: vl.iter().map(|s| s.to_string()).collect(),
642                                filter: Filter::Set,
643                            }),
644                            "unset" => Some(Value::Value {
645                                name: vl.iter().map(|s| s.to_string()).collect(),
646                                filter: Filter::Unset,
647                            }),
648                            "raw" => {
649                                if exp.is_none() {
650                                    Some(Value::Value {
651                                        name: vl.iter().map(|s| s.to_string()).collect(),
652                                        filter: Filter::Raw,
653                                    })
654                                } else {
655                                    None
656                                }
657                            }
658                            "dump" => {
659                                if exp.is_none() {
660                                    Some(Value::Value {
661                                        name: vl.iter().map(|s| s.to_string()).collect(),
662                                        filter: Filter::Dump,
663                                    })
664                                } else {
665                                    None
666                                }
667                            }
668                            "key" => {
669                                if exp.is_none() {
670                                    Some(Value::Value {
671                                        name: vl.iter().map(|s| s.to_string()).collect(),
672                                        filter: Filter::Index,
673                                    })
674                                } else {
675                                    None
676                                }
677                            }
678                            _ => None,
679                        }
680                    } else {
681                        None
682                    }
683                }
684                None => {
685                    if exp.unwrap_or(true) {
686                        if Html::is_valid_input(val) {
687                            let vl: Vec<&str> = val.split('.').collect();
688                            Some(Value::Value {
689                                name: vl.iter().map(|s| s.to_string()).collect(),
690                                filter: Filter::None,
691                            })
692                        } else {
693                            None
694                        }
695                    } else if Html::is_number_input(val) {
696                        Some(Value::Number(val.parse().ok()?))
697                    } else if Html::is_valid_input(val) {
698                        let vl: Vec<&str> = val.split('.').collect();
699                        Some(Value::Value {
700                            name: vl.iter().map(|s| s.to_string()).collect(),
701                            filter: Filter::None,
702                        })
703                    } else {
704                        None
705                    }
706                }
707            }
708        } else {
709            None
710        }
711    }
712
713    /// Get condition for `If`
714    fn get_exp(text: &str) -> Option<ExpValue> {
715        // Split name
716        let res = text.split_whitespace().collect::<Vec<&str>>();
717        if res.len() == 1 {
718            // One value
719            let val = unsafe { res.get_unchecked(0).to_string() };
720            Some(ExpValue {
721                val: Html::get_val(&val, Some(true))?,
722                eq: Eq::None,
723                other: None,
724            })
725        } else if res.len() == 3 {
726            // Two value
727            let val = unsafe { res.get_unchecked(0).to_string() };
728            let val = Html::get_val(&val, Some(true))?;
729            let eq = match unsafe { *res.get_unchecked(1) } {
730                ">" => Eq::GreaterThan,
731                ">=" => Eq::GreaterThanOrEqual,
732                "<" => Eq::LessThan,
733                "<=" => Eq::LessThanOrEqual,
734                "=" => Eq::Equal,
735                "==" => Eq::Equal,
736                "!=" => Eq::NotEqual,
737                _ => return None,
738            };
739            let other = unsafe { res.get_unchecked(2).to_string() };
740            let other = Some(Html::get_val(&other, Some(false))?);
741            Some(ExpValue { val, eq, other })
742        } else {
743            None
744        }
745    }
746
747    /// Parse text for searching `echo` conditions
748    fn get_echo(orig: &str) -> Result<Nodes, usize> {
749        let len = orig.len();
750        let mut val = String::with_capacity(len + 4);
751        val.push('_');
752        val.push_str(orig);
753        val.push_str("___");
754
755        let mut shift = 1;
756        let mut last = 1;
757        let mut current;
758        let mut prev;
759        let mut idx = 0;
760
761        let mut ignore = false;
762        let mut ignore_idx = 0;
763        let mut result = Vec::new();
764        let mut order = false;
765        let mut vl;
766        let mut trim_begin = false;
767        let mut trim_end = false;
768        let mut val = val.to_owned();
769        while shift < len + 1 {
770            // Get the initial condition and ignore symbol
771            current = unsafe { val.get_unchecked(shift..shift + 2) };
772            prev = unsafe { val.get_unchecked(shift - 1..shift) };
773            match (current, order) {
774                ("{{", false) => {
775                    if prev == "@" {
776                        ignore = true;
777                        ignore_idx = shift - 1;
778                    } else {
779                        idx = shift + 2;
780                    }
781                    shift += 2;
782                    order = true;
783                }
784                ("}}", true) => {
785                    if ignore {
786                        val.remove(ignore_idx);
787                        ignore = false;
788                    } else {
789                        result.push(Node::Text(val[last..idx - 2].to_owned()));
790                        vl = val[idx..shift].trim().to_owned();
791                        if vl.is_empty() {
792                            return Err(shift);
793                        }
794                        // Check begin trim
795                        if unsafe { vl.get_unchecked(..1) } == "-" {
796                            trim_begin = true;
797                            vl = vl[1..].trim().to_owned();
798                            if vl.is_empty() {
799                                return Err(shift);
800                            }
801                        }
802                        // Check end trim
803                        if unsafe { vl.get_unchecked(vl.len() - 1..) } == "-" {
804                            trim_end = true;
805                            vl = vl[..vl.len() - 1].trim().to_owned();
806                            if vl.is_empty() {
807                                return Err(shift);
808                            }
809                        }
810                        // Save begin/end trim
811                        match (trim_begin, trim_end) {
812                            (true, true) => {
813                                result.push(Node::Value(EchoValue {
814                                    val: Html::get_val(&vl, None).ok_or(shift)?,
815                                    begin: true,
816                                    end: true,
817                                }));
818                                trim_begin = false;
819                                trim_end = false;
820                            }
821                            (true, false) => {
822                                result.push(Node::Value(EchoValue {
823                                    val: Html::get_val(&vl, None).ok_or(shift)?,
824                                    begin: true,
825                                    end: false,
826                                }));
827                                trim_begin = false;
828                            }
829                            (false, true) => {
830                                result.push(Node::Value(EchoValue {
831                                    val: Html::get_val(&vl, None).ok_or(shift)?,
832                                    begin: false,
833                                    end: true,
834                                }));
835                                trim_end = false;
836                            }
837                            (false, false) => result.push(Node::Value(EchoValue {
838                                val: Html::get_val(&vl, None).ok_or(shift)?,
839                                begin: false,
840                                end: false,
841                            })),
842                        }
843                        last = shift + 2;
844                    }
845                    shift += 2;
846                    order = false;
847                }
848                ("{{", true) => return Err(shift),
849                _ => shift += 1,
850            }
851        }
852        result.push(Node::Text(val[last..len + 1].to_owned()));
853        Ok(result)
854    }
855
856    /// Check if expressions
857    fn get_if_exp(val: &ExpValue, data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> bool {
858        match &val.other {
859            Some(d) => {
860                if val.eq != Eq::None {
861                    let first = match Html::get_if_data(&val.val, data, tmp) {
862                        Some(d) => d,
863                        None => return false,
864                    };
865                    let second = match Html::get_if_data(d, data, tmp) {
866                        Some(d) => d,
867                        None => return false,
868                    };
869                    Html::compare_value(&first, &second, &val.eq)
870                } else {
871                    false
872                }
873            }
874            None => match Html::get_if_data(&val.val, data, tmp) {
875                Some(Data::Bool(b)) => b,
876                _ => false,
877            },
878        }
879    }
880
881    /// Buld branch tree from list
882    fn build_vec(vec: &Vec<Item>, html: &str) -> Result<Nodes, String> {
883        let mut is_if = false;
884        let mut is_if_else = false;
885        let mut is_for = false;
886        let mut is_for_else = false;
887        let mut nodes = Vec::new();
888        let mut if_list = Vec::new();
889        let mut if_else = None;
890        let mut for_list = Vec::new();
891        let mut for_else = None;
892        let mut for_local = String::new();
893        let mut for_name = None;
894        let mut sub_nodes;
895        for item in vec {
896            match item.cond {
897                ItemCondition::None => {
898                    return Err(format!(r#"Incorrect tag None in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
899                }
900                ItemCondition::Text => match Html::get_echo(&item.text) {
901                    Ok(ns) => {
902                        for n in ns {
903                            nodes.push(n);
904                        }
905                    }
906                    Err(shift) => {
907                        let start = if shift < 25 { 0 } else { shift - 25 };
908                        let finish = if shift + 25 > item.text.len() - 3 { item.text.len() - 3 } else { shift + 25 };
909                        return Err(format!(
910                            r#"Incorrect echo "{}" in "{}""#,
911                            &item.text[start..finish],
912                            Html::get_err_msg(item.begin, item.end, html)
913                        ));
914                    }
915                },
916                ItemCondition::If => {
917                    if !(is_if || is_if_else || is_for || is_for_else) {
918                        is_if = true;
919                        let exp = match Html::get_exp(&item.text) {
920                            Some(e) => e,
921                            None => {
922                                return Err(format!(r#"Incorrect expression in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
923                            }
924                        };
925                        sub_nodes = Html::build_vec(&item.child, html)?;
926                        if_list.push(Exp { val: exp, nodes: sub_nodes });
927                    } else {
928                        return Err(format!(r#"Incorrect identical 'IF' tags in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
929                    }
930                }
931                ItemCondition::ElseIf => {
932                    if is_if && !is_if_else && !is_for && !is_for_else {
933                        let exp = match Html::get_exp(&item.text) {
934                            Some(e) => e,
935                            None => {
936                                return Err(format!(r#"Incorrect expression in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
937                            }
938                        };
939                        sub_nodes = Html::build_vec(&item.child, html)?;
940                        if_list.push(Exp { val: exp, nodes: sub_nodes });
941                    } else {
942                        return Err(format!(r#"Incorrect identical 'ElseIf' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
943                    }
944                }
945                ItemCondition::Else => {
946                    if is_if && !is_for && !is_for_else {
947                        is_if_else = true;
948                        if_else = Some(Html::build_vec(&item.child, html)?);
949                    } else {
950                        return Err(format!(r#"Incorrect identical 'Else' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
951                    }
952                }
953                ItemCondition::EndIf => {
954                    if is_if && !is_for && !is_for_else {
955                        is_if = false;
956                        is_if_else = false;
957                        if if_list.is_empty() {
958                            return Err(format!(r#"Incorrect 'IF' tag format in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
959                        }
960                        nodes.push(Node::IF(If {
961                            exp: if_list.clone(),
962                            else_exp: if_else,
963                        }));
964                        if_else = None;
965                        if_list.clear();
966                    } else {
967                        return Err(format!(r#"Incorrect identical 'EndIf' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
968                    }
969                }
970                ItemCondition::For => {
971                    if !(is_if || is_if_else || is_for || is_for_else) {
972                        is_for = true;
973                        let vl: Vec<&str> = item.text.split_whitespace().collect();
974                        if vl.len() != 3 {
975                            return Err(format!(r#"Incorrect identical 'For' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
976                        }
977                        if unsafe { *vl.get_unchecked(1) } != "in" {
978                            return Err(format!(r#"Incorrect identical 'For' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
979                        }
980                        for_name = match Html::get_val(unsafe { vl.get_unchecked(2) }, Some(true)) {
981                            Some(n) => Some(n),
982                            None => {
983                                return Err(format!(
984                                    r#"Incorrect identical 'For' tag in "{}""#,
985                                    Html::get_err_msg(item.begin, item.end, html)
986                                ));
987                            }
988                        };
989                        for_local = unsafe { *vl.get_unchecked(0) }.to_string();
990                        if !Html::is_simple_name(&for_local) {
991                            return Err(format!(r#"Incorrect identical 'For' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
992                        }
993                        for_list = Html::build_vec(&item.child, html)?;
994                    } else {
995                        return Err(format!(r#"Incorrect identical 'For' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
996                    }
997                }
998                ItemCondition::ElseFor => {
999                    if is_for && !is_if && !is_if_else && !is_for_else {
1000                        is_for_else = true;
1001                        for_else = Some(Html::build_vec(&item.child, html)?);
1002                    } else {
1003                        return Err(format!(r#"Incorrect identical 'ElseFor' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
1004                    }
1005                }
1006                ItemCondition::EndFor => {
1007                    if is_for && !is_if && !is_if_else {
1008                        is_for = false;
1009                        is_for_else = false;
1010                        if for_list.is_empty() {
1011                            return Err(format!(r#"Incorrect 'For' tag format in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
1012                        }
1013                        if let Some(name) = for_name {
1014                            nodes.push(Node::For(For {
1015                                name,
1016                                local: for_local.clone(),
1017                                nodes: for_list.clone(),
1018                                empty: for_else,
1019                            }));
1020                        } else {
1021                            return Err(format!(r#"Incorrect 'For' tag format in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
1022                        }
1023                        for_local = String::new();
1024                        for_name = None;
1025                        for_else = None;
1026                        for_list.clear();
1027                    } else {
1028                        return Err(format!(r#"Incorrect identical 'EndFor' tag in "{}""#, Html::get_err_msg(item.begin, item.end, html)));
1029                    }
1030                }
1031            }
1032        }
1033        nodes.shrink_to_fit();
1034        Ok(nodes)
1035    }
1036
1037    /// Prepares an error message
1038    fn get_err_msg(begin: usize, end: usize, html: &str) -> String {
1039        let html = &html[1..html.len() - 3];
1040        let end = if end > html.len() { html.len() } else { end };
1041        let chars_start: Vec<char> = html[0..begin].chars().collect();
1042        let chars_middle: Vec<char> = html[begin..end].chars().collect();
1043        let chars_finish: Vec<char> = html[end..html.len()].chars().collect();
1044        let start = if chars_start.len() < 25 { 0 } else { chars_start.len() - 25 };
1045        let finish = if chars_finish.len() < 25 { chars_finish.len() } else { 25 };
1046        let mut msg = chars_start[start..].iter().collect::<String>();
1047        msg.push_str(&chars_middle[..].iter().collect::<String>());
1048        msg.push_str(&chars_finish[..finish].iter().collect::<String>());
1049        msg
1050    }
1051
1052    /// Set level for list of conditions
1053    fn build_tree(vec: &Vec<Item>, shift: &mut usize, level: usize) -> Option<Vec<Item>> {
1054        let mut item;
1055        let mut res = Vec::new();
1056        let mut last;
1057        while *shift < vec.len() {
1058            item = unsafe { vec.get_unchecked(*shift) };
1059            if item.level < level {
1060                return Some(res);
1061            } else if item.level == level {
1062                res.push(item.clone());
1063                *shift += 1;
1064            } else if item.level == level + 1 {
1065                last = res.pop()?;
1066                last.child = Html::build_tree(vec, shift, level + 1)?;
1067                res.push(last);
1068            }
1069        }
1070        Some(res)
1071    }
1072
1073    /// Render of html template
1074    pub fn render(data: &BTreeMap<i64, Data>, list: &Nodes) -> Answer {
1075        let mut tmp = BTreeMap::new();
1076        Answer::String(Html::render_level(list, data, &mut tmp))
1077    }
1078
1079    /// Render one level of template
1080    fn render_level(list: &Nodes, data: &BTreeMap<i64, Data>, tmp: &mut BTreeMap<i64, Data>) -> String {
1081        let mut html = String::new();
1082        let mut trim_end = false;
1083        for item in list {
1084            match item {
1085                Node::Text(s) => {
1086                    if trim_end {
1087                        let t = html.trim_end().len();
1088                        if t < html.len() {
1089                            unsafe {
1090                                html.as_mut_vec().truncate(t);
1091                            }
1092                        }
1093                        trim_end = false;
1094                        html.push_str(s.trim_start());
1095                    } else {
1096                        html.push_str(s)
1097                    }
1098                }
1099                Node::Value(v) => {
1100                    if trim_end {
1101                        let t = html.trim_end().len();
1102                        if t < html.len() {
1103                            unsafe {
1104                                html.as_mut_vec().truncate(t);
1105                            }
1106                        }
1107                        trim_end = false;
1108                    }
1109                    if v.begin {
1110                        let t = html.trim_end().len();
1111                        if t < html.len() {
1112                            unsafe {
1113                                html.as_mut_vec().truncate(t);
1114                            }
1115                        }
1116                        html.push_str(Html::print_echo(&v.val, data, tmp).trim_start())
1117                    } else {
1118                        html.push_str(&Html::print_echo(&v.val, data, tmp))
1119                    }
1120                    if v.end {
1121                        trim_end = true;
1122                    }
1123                }
1124                Node::For(f) => {
1125                    if trim_end {
1126                        let t = html.trim_end().len();
1127                        if t < html.len() {
1128                            unsafe {
1129                                html.as_mut_vec().truncate(t);
1130                            }
1131                        }
1132                        trim_end = false;
1133                    }
1134                    match Html::get_for_data(&f.name, data, tmp) {
1135                        Some(d) => match d {
1136                            Data::Vec(vec) => {
1137                                if !vec.is_empty() {
1138                                    let key_idx = fnv1a_64(format!("{}|key", f.local).as_bytes());
1139                                    let key = fnv1a_64(f.local.as_bytes());
1140                                    for (idx, v) in vec.into_iter().enumerate() {
1141                                        tmp.insert(key_idx, Data::Usize(idx + 1));
1142                                        tmp.insert(key, v.clone());
1143                                        html.push_str(&Html::render_level(&f.nodes, data, tmp));
1144                                    }
1145                                    tmp.remove(&key_idx);
1146                                    tmp.remove(&key);
1147                                }
1148                            }
1149                            Data::Map(map) => {
1150                                if !map.is_empty() {
1151                                    let key_idx = fnv1a_64(format!("{}|key", f.local).as_bytes());
1152                                    let key = fnv1a_64(f.local.as_bytes());
1153                                    for (key, v) in map {
1154                                        tmp.insert(key_idx, Data::I64(key));
1155                                        tmp.insert(key, v.clone());
1156                                        html.push_str(&Html::render_level(&f.nodes, data, tmp));
1157                                    }
1158                                    tmp.remove(&key_idx);
1159                                    tmp.remove(&key);
1160                                }
1161                            }
1162                            _ => {}
1163                        },
1164                        None => {
1165                            if let Some(v) = &f.empty {
1166                                html.push_str(&Html::render_level(v, data, tmp));
1167                            }
1168                        }
1169                    }
1170                }
1171                Node::IF(i) => {
1172                    if trim_end {
1173                        let t = html.trim_end().len();
1174                        if t < html.len() {
1175                            unsafe {
1176                                html.as_mut_vec().truncate(t);
1177                            }
1178                        }
1179                        trim_end = false;
1180                    }
1181                    let mut run = false;
1182                    for item in &i.exp {
1183                        if Html::get_if_exp(&item.val, data, tmp) {
1184                            html.push_str(&Html::render_level(&item.nodes, data, tmp));
1185                            run = true;
1186                            break;
1187                        }
1188                    }
1189                    if !run {
1190                        if let Some(n) = &i.else_exp {
1191                            html.push_str(&Html::render_level(n, data, tmp));
1192                        }
1193                    }
1194                }
1195            }
1196        }
1197        if trim_end {
1198            let t = html.trim_end().len();
1199            if t < html.len() {
1200                unsafe {
1201                    html.as_mut_vec().truncate(t);
1202                }
1203            }
1204        }
1205        html
1206    }
1207
1208    /// Compare values for if condition
1209    fn compare_value(first: &Data, second: &Data, eq: &Eq) -> bool {
1210        match first {
1211            Data::Usize(u1) => match second {
1212                Data::Usize(u2) => match eq {
1213                    Eq::Equal => *u1 == *u2,
1214                    Eq::NotEqual => *u1 != *u2,
1215                    Eq::LessThan => *u1 < *u2,
1216                    Eq::LessThanOrEqual => *u1 <= *u2,
1217                    Eq::GreaterThan => *u1 > *u2,
1218                    Eq::GreaterThanOrEqual => *u1 >= *u2,
1219                    _ => false,
1220                },
1221                Data::I16(i2) => match usize::try_from(*i2) {
1222                    Ok(u2) => match eq {
1223                        Eq::Equal => *u1 == u2,
1224                        Eq::NotEqual => *u1 != u2,
1225                        Eq::LessThan => *u1 < u2,
1226                        Eq::LessThanOrEqual => *u1 <= u2,
1227                        Eq::GreaterThan => *u1 > u2,
1228                        Eq::GreaterThanOrEqual => *u1 >= u2,
1229                        _ => false,
1230                    },
1231                    Err(_) => false,
1232                },
1233                Data::I32(i2) => match usize::try_from(*i2) {
1234                    Ok(u2) => match eq {
1235                        Eq::Equal => *u1 == u2,
1236                        Eq::NotEqual => *u1 != u2,
1237                        Eq::LessThan => *u1 < u2,
1238                        Eq::LessThanOrEqual => *u1 <= u2,
1239                        Eq::GreaterThan => *u1 > u2,
1240                        Eq::GreaterThanOrEqual => *u1 >= u2,
1241                        _ => false,
1242                    },
1243                    Err(_) => false,
1244                },
1245                Data::I64(i2) => match usize::try_from(*i2) {
1246                    Ok(u2) => match eq {
1247                        Eq::Equal => *u1 == u2,
1248                        Eq::NotEqual => *u1 != u2,
1249                        Eq::LessThan => *u1 < u2,
1250                        Eq::LessThanOrEqual => *u1 <= u2,
1251                        Eq::GreaterThan => *u1 > u2,
1252                        Eq::GreaterThanOrEqual => *u1 >= u2,
1253                        _ => false,
1254                    },
1255                    Err(_) => false,
1256                },
1257                Data::F32(f2) => match eq {
1258                    Eq::Equal => *u1 == ((*f2).floor() as usize),
1259                    Eq::NotEqual => *u1 != ((*f2).floor() as usize),
1260                    Eq::LessThan => *u1 < ((*f2).floor() as usize),
1261                    Eq::LessThanOrEqual => *u1 <= ((*f2).floor() as usize),
1262                    Eq::GreaterThan => *u1 > ((*f2).floor() as usize),
1263                    Eq::GreaterThanOrEqual => *u1 >= ((*f2).floor() as usize),
1264                    _ => false,
1265                },
1266                Data::F64(f2) => match eq {
1267                    Eq::Equal => *u1 == ((*f2).floor() as usize),
1268                    Eq::NotEqual => *u1 != ((*f2).floor() as usize),
1269                    Eq::LessThan => *u1 < ((*f2).floor() as usize),
1270                    Eq::LessThanOrEqual => *u1 <= ((*f2).floor() as usize),
1271                    Eq::GreaterThan => *u1 > ((*f2).floor() as usize),
1272                    Eq::GreaterThanOrEqual => *u1 >= ((*f2).floor() as usize),
1273                    _ => false,
1274                },
1275                _ => false,
1276            },
1277            Data::I16(i1) => match second {
1278                Data::Usize(u2) => match i16::try_from(*u2) {
1279                    Ok(i2) => match eq {
1280                        Eq::Equal => *i1 == i2,
1281                        Eq::NotEqual => *i1 != i2,
1282                        Eq::LessThan => *i1 < i2,
1283                        Eq::LessThanOrEqual => *i1 <= i2,
1284                        Eq::GreaterThan => *i1 > i2,
1285                        Eq::GreaterThanOrEqual => *i1 >= i2,
1286                        _ => false,
1287                    },
1288                    Err(_) => false,
1289                },
1290                Data::I16(i2) => match eq {
1291                    Eq::Equal => *i1 == *i2,
1292                    Eq::NotEqual => *i1 != *i2,
1293                    Eq::LessThan => *i1 < *i2,
1294                    Eq::LessThanOrEqual => *i1 <= *i2,
1295                    Eq::GreaterThan => *i1 > *i2,
1296                    Eq::GreaterThanOrEqual => *i1 >= *i2,
1297                    _ => false,
1298                },
1299                Data::I32(i2) => match i16::try_from(*i2) {
1300                    Ok(i2) => match eq {
1301                        Eq::Equal => *i1 == i2,
1302                        Eq::NotEqual => *i1 != i2,
1303                        Eq::LessThan => *i1 < i2,
1304                        Eq::LessThanOrEqual => *i1 <= i2,
1305                        Eq::GreaterThan => *i1 > i2,
1306                        Eq::GreaterThanOrEqual => *i1 >= i2,
1307                        _ => false,
1308                    },
1309                    Err(_) => false,
1310                },
1311                Data::I64(i2) => match i16::try_from(*i2) {
1312                    Ok(i2) => match eq {
1313                        Eq::Equal => *i1 == i2,
1314                        Eq::NotEqual => *i1 != i2,
1315                        Eq::LessThan => *i1 < i2,
1316                        Eq::LessThanOrEqual => *i1 <= i2,
1317                        Eq::GreaterThan => *i1 > i2,
1318                        Eq::GreaterThanOrEqual => *i1 >= i2,
1319                        _ => false,
1320                    },
1321                    Err(_) => false,
1322                },
1323                Data::F32(f2) => match eq {
1324                    Eq::Equal => *i1 == ((*f2).floor() as i16),
1325                    Eq::NotEqual => *i1 != ((*f2).floor() as i16),
1326                    Eq::LessThan => *i1 < ((*f2).floor() as i16),
1327                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i16),
1328                    Eq::GreaterThan => *i1 > ((*f2).floor() as i16),
1329                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i16),
1330                    _ => false,
1331                },
1332                Data::F64(f2) => match eq {
1333                    Eq::Equal => *i1 == ((*f2).floor() as i16),
1334                    Eq::NotEqual => *i1 != ((*f2).floor() as i16),
1335                    Eq::LessThan => *i1 < ((*f2).floor() as i16),
1336                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i16),
1337                    Eq::GreaterThan => *i1 > ((*f2).floor() as i16),
1338                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i16),
1339                    _ => false,
1340                },
1341                _ => false,
1342            },
1343            Data::I32(i1) => match second {
1344                Data::Usize(u2) => match i32::try_from(*u2) {
1345                    Ok(i2) => match eq {
1346                        Eq::Equal => *i1 == i2,
1347                        Eq::NotEqual => *i1 != i2,
1348                        Eq::LessThan => *i1 < i2,
1349                        Eq::LessThanOrEqual => *i1 <= i2,
1350                        Eq::GreaterThan => *i1 > i2,
1351                        Eq::GreaterThanOrEqual => *i1 >= i2,
1352                        _ => false,
1353                    },
1354                    Err(_) => false,
1355                },
1356                Data::I16(i2) => match eq {
1357                    Eq::Equal => *i1 == (*i2 as i32),
1358                    Eq::NotEqual => *i1 != (*i2 as i32),
1359                    Eq::LessThan => *i1 < (*i2 as i32),
1360                    Eq::LessThanOrEqual => *i1 <= (*i2 as i32),
1361                    Eq::GreaterThan => *i1 > (*i2 as i32),
1362                    Eq::GreaterThanOrEqual => *i1 >= (*i2 as i32),
1363                    _ => false,
1364                },
1365                Data::I32(i2) => match eq {
1366                    Eq::Equal => *i1 == *i2,
1367                    Eq::NotEqual => *i1 != *i2,
1368                    Eq::LessThan => *i1 < *i2,
1369                    Eq::LessThanOrEqual => *i1 <= *i2,
1370                    Eq::GreaterThan => *i1 > *i2,
1371                    Eq::GreaterThanOrEqual => *i1 >= *i2,
1372                    _ => false,
1373                },
1374                Data::I64(i2) => match i32::try_from(*i2) {
1375                    Ok(i2) => match eq {
1376                        Eq::Equal => *i1 == i2,
1377                        Eq::NotEqual => *i1 != i2,
1378                        Eq::LessThan => *i1 < i2,
1379                        Eq::LessThanOrEqual => *i1 <= i2,
1380                        Eq::GreaterThan => *i1 > i2,
1381                        Eq::GreaterThanOrEqual => *i1 >= i2,
1382                        _ => false,
1383                    },
1384                    Err(_) => false,
1385                },
1386                Data::F32(f2) => match eq {
1387                    Eq::Equal => *i1 == ((*f2).floor() as i32),
1388                    Eq::NotEqual => *i1 != ((*f2).floor() as i32),
1389                    Eq::LessThan => *i1 < ((*f2).floor() as i32),
1390                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i32),
1391                    Eq::GreaterThan => *i1 > ((*f2).floor() as i32),
1392                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i32),
1393                    _ => false,
1394                },
1395                Data::F64(f2) => match eq {
1396                    Eq::Equal => *i1 == ((*f2).floor() as i32),
1397                    Eq::NotEqual => *i1 != ((*f2).floor() as i32),
1398                    Eq::LessThan => *i1 < ((*f2).floor() as i32),
1399                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i32),
1400                    Eq::GreaterThan => *i1 > ((*f2).floor() as i32),
1401                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i32),
1402                    _ => false,
1403                },
1404                _ => false,
1405            },
1406            Data::I64(i1) => match second {
1407                Data::Usize(u2) => match i64::try_from(*u2) {
1408                    Ok(i2) => match eq {
1409                        Eq::Equal => *i1 == i2,
1410                        Eq::NotEqual => *i1 != i2,
1411                        Eq::LessThan => *i1 < i2,
1412                        Eq::LessThanOrEqual => *i1 <= i2,
1413                        Eq::GreaterThan => *i1 > i2,
1414                        Eq::GreaterThanOrEqual => *i1 >= i2,
1415                        _ => false,
1416                    },
1417                    Err(_) => false,
1418                },
1419                Data::I16(i2) => match eq {
1420                    Eq::Equal => *i1 == (*i2 as i64),
1421                    Eq::NotEqual => *i1 != (*i2 as i64),
1422                    Eq::LessThan => *i1 < (*i2 as i64),
1423                    Eq::LessThanOrEqual => *i1 <= (*i2 as i64),
1424                    Eq::GreaterThan => *i1 > (*i2 as i64),
1425                    Eq::GreaterThanOrEqual => *i1 >= (*i2 as i64),
1426                    _ => false,
1427                },
1428                Data::I32(i2) => match eq {
1429                    Eq::Equal => *i1 == (*i2 as i64),
1430                    Eq::NotEqual => *i1 != (*i2 as i64),
1431                    Eq::LessThan => *i1 < (*i2 as i64),
1432                    Eq::LessThanOrEqual => *i1 <= (*i2 as i64),
1433                    Eq::GreaterThan => *i1 > (*i2 as i64),
1434                    Eq::GreaterThanOrEqual => *i1 >= (*i2 as i64),
1435                    _ => false,
1436                },
1437                Data::I64(i2) => match eq {
1438                    Eq::Equal => *i1 == *i2,
1439                    Eq::NotEqual => *i1 != *i2,
1440                    Eq::LessThan => *i1 < *i2,
1441                    Eq::LessThanOrEqual => *i1 <= *i2,
1442                    Eq::GreaterThan => *i1 > *i2,
1443                    Eq::GreaterThanOrEqual => *i1 >= *i2,
1444                    _ => false,
1445                },
1446                Data::F32(f2) => match eq {
1447                    Eq::Equal => *i1 == ((*f2).floor() as i64),
1448                    Eq::NotEqual => *i1 != ((*f2).floor() as i64),
1449                    Eq::LessThan => *i1 < ((*f2).floor() as i64),
1450                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i64),
1451                    Eq::GreaterThan => *i1 > ((*f2).floor() as i64),
1452                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i64),
1453                    _ => false,
1454                },
1455                Data::F64(f2) => match eq {
1456                    Eq::Equal => *i1 == ((*f2).floor() as i64),
1457                    Eq::NotEqual => *i1 != ((*f2).floor() as i64),
1458                    Eq::LessThan => *i1 < ((*f2).floor() as i64),
1459                    Eq::LessThanOrEqual => *i1 <= ((*f2).floor() as i64),
1460                    Eq::GreaterThan => *i1 > ((*f2).floor() as i64),
1461                    Eq::GreaterThanOrEqual => *i1 >= ((*f2).floor() as i64),
1462                    _ => false,
1463                },
1464                _ => false,
1465            },
1466            Data::F32(f1) => match second {
1467                Data::Usize(u2) => match eq {
1468                    Eq::Equal => *f1 == (*u2 as f32),
1469                    Eq::NotEqual => *f1 != (*u2 as f32),
1470                    Eq::LessThan => *f1 < (*u2 as f32),
1471                    Eq::LessThanOrEqual => *f1 <= (*u2 as f32),
1472                    Eq::GreaterThan => *f1 > (*u2 as f32),
1473                    Eq::GreaterThanOrEqual => *f1 >= (*u2 as f32),
1474                    _ => false,
1475                },
1476                Data::I16(i2) => match eq {
1477                    Eq::Equal => *f1 == (*i2 as f32),
1478                    Eq::NotEqual => *f1 != (*i2 as f32),
1479                    Eq::LessThan => *f1 < (*i2 as f32),
1480                    Eq::LessThanOrEqual => *f1 <= (*i2 as f32),
1481                    Eq::GreaterThan => *f1 > (*i2 as f32),
1482                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f32),
1483                    _ => false,
1484                },
1485                Data::I32(i2) => match eq {
1486                    Eq::Equal => *f1 == (*i2 as f32),
1487                    Eq::NotEqual => *f1 != (*i2 as f32),
1488                    Eq::LessThan => *f1 < (*i2 as f32),
1489                    Eq::LessThanOrEqual => *f1 <= (*i2 as f32),
1490                    Eq::GreaterThan => *f1 > (*i2 as f32),
1491                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f32),
1492                    _ => false,
1493                },
1494                Data::I64(i2) => match eq {
1495                    Eq::Equal => *f1 == (*i2 as f32),
1496                    Eq::NotEqual => *f1 != (*i2 as f32),
1497                    Eq::LessThan => *f1 < (*i2 as f32),
1498                    Eq::LessThanOrEqual => *f1 <= (*i2 as f32),
1499                    Eq::GreaterThan => *f1 > (*i2 as f32),
1500                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f32),
1501                    _ => false,
1502                },
1503                Data::F32(f2) => match eq {
1504                    Eq::Equal => *f1 == *f2,
1505                    Eq::NotEqual => *f1 != *f2,
1506                    Eq::LessThan => *f1 < *f2,
1507                    Eq::LessThanOrEqual => *f1 <= *f2,
1508                    Eq::GreaterThan => *f1 > *f2,
1509                    Eq::GreaterThanOrEqual => *f1 >= *f2,
1510                    _ => false,
1511                },
1512                Data::F64(f2) => match eq {
1513                    Eq::Equal => *f1 == (*f2 as f32),
1514                    Eq::NotEqual => *f1 != (*f2 as f32),
1515                    Eq::LessThan => *f1 < (*f2 as f32),
1516                    Eq::LessThanOrEqual => *f1 <= (*f2 as f32),
1517                    Eq::GreaterThan => *f1 > (*f2 as f32),
1518                    Eq::GreaterThanOrEqual => *f1 >= (*f2 as f32),
1519                    _ => false,
1520                },
1521                _ => false,
1522            },
1523            Data::F64(f1) => match second {
1524                Data::Usize(u2) => match eq {
1525                    Eq::Equal => *f1 == (*u2 as f64),
1526                    Eq::NotEqual => *f1 != (*u2 as f64),
1527                    Eq::LessThan => *f1 < (*u2 as f64),
1528                    Eq::LessThanOrEqual => *f1 <= (*u2 as f64),
1529                    Eq::GreaterThan => *f1 > (*u2 as f64),
1530                    Eq::GreaterThanOrEqual => *f1 >= (*u2 as f64),
1531                    _ => false,
1532                },
1533                Data::I16(i2) => match eq {
1534                    Eq::Equal => *f1 == (*i2 as f64),
1535                    Eq::NotEqual => *f1 != (*i2 as f64),
1536                    Eq::LessThan => *f1 < (*i2 as f64),
1537                    Eq::LessThanOrEqual => *f1 <= (*i2 as f64),
1538                    Eq::GreaterThan => *f1 > (*i2 as f64),
1539                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f64),
1540                    _ => false,
1541                },
1542                Data::I32(i2) => match eq {
1543                    Eq::Equal => *f1 == (*i2 as f64),
1544                    Eq::NotEqual => *f1 != (*i2 as f64),
1545                    Eq::LessThan => *f1 < (*i2 as f64),
1546                    Eq::LessThanOrEqual => *f1 <= (*i2 as f64),
1547                    Eq::GreaterThan => *f1 > (*i2 as f64),
1548                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f64),
1549                    _ => false,
1550                },
1551                Data::I64(i2) => match eq {
1552                    Eq::Equal => *f1 == (*i2 as f64),
1553                    Eq::NotEqual => *f1 != (*i2 as f64),
1554                    Eq::LessThan => *f1 < (*i2 as f64),
1555                    Eq::LessThanOrEqual => *f1 <= (*i2 as f64),
1556                    Eq::GreaterThan => *f1 > (*i2 as f64),
1557                    Eq::GreaterThanOrEqual => *f1 >= (*i2 as f64),
1558                    _ => false,
1559                },
1560                Data::F32(f2) => match eq {
1561                    Eq::Equal => *f1 == (*f2 as f64),
1562                    Eq::NotEqual => *f1 != (*f2 as f64),
1563                    Eq::LessThan => *f1 < (*f2 as f64),
1564                    Eq::LessThanOrEqual => *f1 <= (*f2 as f64),
1565                    Eq::GreaterThan => *f1 > (*f2 as f64),
1566                    Eq::GreaterThanOrEqual => *f1 >= (*f2 as f64),
1567                    _ => false,
1568                },
1569                Data::F64(f2) => match eq {
1570                    Eq::Equal => *f1 == *f2,
1571                    Eq::NotEqual => *f1 != *f2,
1572                    Eq::LessThan => *f1 < *f2,
1573                    Eq::LessThanOrEqual => *f1 <= *f2,
1574                    Eq::GreaterThan => *f1 > *f2,
1575                    Eq::GreaterThanOrEqual => *f1 >= *f2,
1576                    _ => false,
1577                },
1578                _ => false,
1579            },
1580            Data::Bool(b1) => match second {
1581                Data::Bool(b2) => match eq {
1582                    Eq::Equal => *b1 == *b2,
1583                    Eq::NotEqual => *b1 != *b2,
1584                    _ => false,
1585                },
1586                _ => false,
1587            },
1588            Data::Date(d1) => match second {
1589                Data::Date(d2) => match eq {
1590                    Eq::Equal => *d1 == *d2,
1591                    Eq::NotEqual => *d1 != *d2,
1592                    Eq::LessThan => *d1 < *d2,
1593                    Eq::LessThanOrEqual => *d1 <= *d2,
1594                    Eq::GreaterThan => *d1 > *d2,
1595                    Eq::GreaterThanOrEqual => *d1 >= *d2,
1596                    _ => false,
1597                },
1598                _ => false,
1599            },
1600            Data::String(s1) => match second {
1601                Data::String(s2) => match eq {
1602                    Eq::Equal => (*s1).eq(s2),
1603                    Eq::NotEqual => (*s1).ne(s2),
1604                    Eq::LessThan => (*s1).lt(s2),
1605                    Eq::LessThanOrEqual => (*s1).le(s2),
1606                    Eq::GreaterThan => (*s1).gt(s2),
1607                    Eq::GreaterThanOrEqual => (*s1).ge(s2),
1608                    _ => false,
1609                },
1610                _ => false,
1611            },
1612            _ => false,
1613        }
1614    }
1615
1616    /// Extract Data from a value for If condition
1617    fn get_if_data(val: &Value, data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> Option<Data> {
1618        match val {
1619            Value::Number(n) => Some(Data::I64(*n)),
1620            Value::Value { name, filter } => {
1621                if !name.is_empty() {
1622                    match filter {
1623                        Filter::None => {
1624                            let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1625                            let mut val = match data.get(&key) {
1626                                Some(v) => v,
1627                                None => match tmp.get(&key) {
1628                                    Some(v) => v,
1629                                    None => return None,
1630                                },
1631                            };
1632                            let mut shift = 1;
1633                            while shift < name.len() {
1634                                if let Data::Map(map) = val {
1635                                    key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1636                                    val = match map.get(&key) {
1637                                        Some(v) => v,
1638                                        None => return None,
1639                                    };
1640                                } else {
1641                                    return None;
1642                                }
1643                                shift += 1;
1644                            }
1645                            Some(val.clone())
1646                        }
1647                        Filter::Len => {
1648                            let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1649                            let mut val = match data.get(&key) {
1650                                Some(v) => v,
1651                                None => match tmp.get(&key) {
1652                                    Some(v) => v,
1653                                    None => return None,
1654                                },
1655                            };
1656                            let mut shift = 1;
1657                            while shift < name.len() {
1658                                if let Data::Map(map) = val {
1659                                    key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1660                                    val = match map.get(&key) {
1661                                        Some(v) => v,
1662                                        None => return None,
1663                                    };
1664                                } else {
1665                                    return None;
1666                                }
1667                                shift += 1;
1668                            }
1669                            match val {
1670                                Data::String(s) => Some(Data::Usize(s.len())),
1671                                Data::Vec(v) => Some(Data::Usize(v.len())),
1672                                Data::Map(m) => Some(Data::Usize(m.len())),
1673                                _ => None,
1674                            }
1675                        }
1676                        Filter::Set => {
1677                            let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1678                            let mut val = match data.get(&key) {
1679                                Some(v) => v,
1680                                None => match tmp.get(&key) {
1681                                    Some(v) => v,
1682                                    None => return Some(Data::Bool(false)),
1683                                },
1684                            };
1685                            let mut shift = 1;
1686                            while shift < name.len() {
1687                                if let Data::Map(map) = val {
1688                                    key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1689                                    val = match map.get(&key) {
1690                                        Some(v) => v,
1691                                        None => return Some(Data::Bool(false)),
1692                                    };
1693                                } else {
1694                                    return Some(Data::Bool(false));
1695                                }
1696                                shift += 1;
1697                            }
1698                            Some(Data::Bool(true))
1699                        }
1700                        Filter::Unset => {
1701                            let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1702                            let mut val = match data.get(&key) {
1703                                Some(v) => v,
1704                                None => match tmp.get(&key) {
1705                                    Some(v) => v,
1706                                    None => return Some(Data::Bool(true)),
1707                                },
1708                            };
1709                            let mut shift = 1;
1710                            while shift < name.len() {
1711                                if let Data::Map(map) = val {
1712                                    key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1713                                    val = match map.get(&key) {
1714                                        Some(v) => v,
1715                                        None => return Some(Data::Bool(true)),
1716                                    };
1717                                } else {
1718                                    return Some(Data::Bool(true));
1719                                }
1720                                shift += 1;
1721                            }
1722                            Some(Data::Bool(false))
1723                        }
1724                        _ => None,
1725                    }
1726                } else {
1727                    None
1728                }
1729            }
1730        }
1731    }
1732
1733    /// Extract Data from a value for For condition
1734    fn get_for_data(val: &Value, data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> Option<Data> {
1735        if let Value::Value { name, filter } = val {
1736            if *filter == Filter::None || !name.is_empty() {
1737                let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1738                let mut val = match data.get(&key) {
1739                    Some(v) => v,
1740                    None => match tmp.get(&key) {
1741                        Some(v) => v,
1742                        None => return None,
1743                    },
1744                };
1745                let mut shift = 1;
1746                while shift < name.len() {
1747                    if let Data::Map(map) = val {
1748                        key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1749                        val = match map.get(&key) {
1750                            Some(v) => v,
1751                            None => return None,
1752                        };
1753                    } else {
1754                        return None;
1755                    }
1756                    shift += 1;
1757                }
1758                Some(val.clone())
1759            } else {
1760                None
1761            }
1762        } else {
1763            None
1764        }
1765    }
1766
1767    /// Extract Data from Value and print its
1768    fn print_echo(val: &Value, data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> String {
1769        match val {
1770            Value::Number(n) => format!("{{{{err::Number({})}}}}", n),
1771            Value::Value { name, filter } => match filter {
1772                Filter::None => Html::escape(Html::data_to_text(name, data, tmp)),
1773                Filter::Raw => Html::data_to_text(name, data, tmp),
1774                Filter::Index => Html::data_to_index(name, tmp),
1775                Filter::Len => "{{err::Len}}".to_owned(),
1776                Filter::Set => "{{err::Set}}".to_owned(),
1777                Filter::Unset => "{{err::Unset}}".to_owned(),
1778                Filter::Dump => Html::data_to_dump(name, data, tmp),
1779            },
1780        }
1781    }
1782
1783    fn data_to_dump(name: &[String], data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> String {
1784        if name.is_empty() {
1785            return "{{{{EMPTY}}}}".to_owned();
1786        }
1787        let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1788        let mut val = match data.get(&key) {
1789            Some(v) => v,
1790            None => match tmp.get(&key) {
1791                Some(v) => v,
1792                None => return format!("{{{{KEY={}}}}}", name.join(".")),
1793            },
1794        };
1795        let mut shift = 1;
1796        while shift < name.len() {
1797            if let Data::Map(map) = val {
1798                key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1799                val = match map.get(&key) {
1800                    Some(v) => v,
1801                    None => return format!("{{{{KEY={}}}}}", name.join(".")),
1802                };
1803            } else {
1804                return format!("{{{{KEY={}}}}}", name.join("."));
1805            }
1806            shift += 1;
1807        }
1808        format!("{{{{KEY={} VALUE={:?}}}}}", name.join("."), val)
1809    }
1810
1811    /// Extract string from value
1812    /// name.subname.othername|Filter
1813    fn data_to_text(name: &[String], data: &BTreeMap<i64, Data>, tmp: &BTreeMap<i64, Data>) -> String {
1814        if name.is_empty() {
1815            return "{{unknown}}".to_owned();
1816        }
1817        let mut key = fnv1a_64(unsafe { name.get_unchecked(0) }.as_bytes());
1818        let mut val = match data.get(&key) {
1819            Some(v) => v,
1820            None => match tmp.get(&key) {
1821                Some(v) => v,
1822                None => return format!("{{{{{}}}}}", name.join(".")),
1823            },
1824        };
1825        let mut shift = 1;
1826        while shift < name.len() {
1827            if let Data::Map(map) = val {
1828                key = fnv1a_64(unsafe { name.get_unchecked(shift) }.as_bytes());
1829                val = match map.get(&key) {
1830                    Some(v) => v,
1831                    None => return format!("{{{{{}}}}}", name.join(".")),
1832                };
1833            } else {
1834                return format!("{{{{{}}}}}", name.join("."));
1835            }
1836            shift += 1;
1837        }
1838        Html::print_data(val)
1839    }
1840
1841    /// Data to String
1842    fn print_data(val: &Data) -> String {
1843        match val {
1844            Data::None => String::new(),
1845            Data::Usize(i) => i.to_string(),
1846            Data::I16(i) => i.to_string(),
1847            Data::I32(i) => i.to_string(),
1848            Data::I64(i) => i.to_string(),
1849            Data::F32(f) => f.to_string(),
1850            Data::F64(f) => f.to_string(),
1851            Data::Bool(b) => b.to_string(),
1852            Data::String(s) => s.to_owned(),
1853            Data::Date(d) => d.to_string(),
1854            Data::Json(j) => j.to_string(),
1855            Data::Vec(_) => "{{vec}}".to_owned(),
1856            Data::Raw(_) => "{{raw}}".to_owned(),
1857            Data::Map(_) => "{{map}}".to_owned(),
1858            Data::Route(_) => "{{route}}".to_owned(),
1859            Data::Redirect(_) => "{{redirect}}".to_owned(),
1860            Data::MailProvider(_) => "{{mail_provider}}".to_owned(),
1861        }
1862    }
1863
1864    /// Print index of loop
1865    fn data_to_index(name: &[String], tmp: &BTreeMap<i64, Data>) -> String {
1866        if name.len() == 1 {
1867            let key = fnv1a_64(format!("{}|idx", unsafe { name.get_unchecked(0) }).as_bytes());
1868            match tmp.get(&key) {
1869                Some(Data::Usize(i)) => i.to_string(),
1870                _ => {
1871                    let mut res = name.join(".");
1872                    res.push_str("|idx");
1873                    res
1874                }
1875            }
1876        } else {
1877            let mut res = name.join(".");
1878            res.push_str("|idx");
1879            res
1880        }
1881    }
1882
1883    /// Escape text
1884    fn escape(text: String) -> String {
1885        let t = text.as_bytes();
1886        let mut len = 0;
1887
1888        for b in t {
1889            len += match b {
1890                b'&' => 5,
1891                b'"' | b'\'' => 6,
1892                b'<' | b'>' => 4,
1893                _ => 0,
1894            };
1895        }
1896        if len == 0 {
1897            return text;
1898        }
1899        let mut new_text = String::with_capacity(text.len() + len);
1900        for c in text.chars() {
1901            match c {
1902                '&' => new_text.push_str("&amp;"),
1903                '"' => new_text.push_str("&quot;"),
1904                '\'' => new_text.push_str("&apos;"),
1905                '<' => new_text.push_str("&lt;"),
1906                '>' => new_text.push_str("&gt;"),
1907                _ => new_text.push(c),
1908            };
1909        }
1910        new_text
1911    }
1912
1913    /// Load lang's files
1914    async fn get_files(root: &str) -> Vec<(PathBuf, String, String, String)> {
1915        let mut vec = Vec::new();
1916        let path = format!("{}/app/", root);
1917        let read_path = match read_dir(&path) {
1918            Ok(r) => r,
1919            Err(e) => {
1920                Log::warning(1100, Some(format!("Path: {}. Err: {}", path, e)));
1921                return vec;
1922            }
1923        };
1924
1925        // Read first level dir
1926        for entry in read_path {
1927            let path = match entry {
1928                Ok(e) => e.path(),
1929                Err(e) => {
1930                    Log::warning(1101, Some(format!("{} ({})", e, path)));
1931                    continue;
1932                }
1933            };
1934            if !path.is_dir() {
1935                continue;
1936            }
1937            let module = match path.file_name() {
1938                Some(m) => match m.to_str() {
1939                    Some(module) => module,
1940                    None => continue,
1941                },
1942                None => continue,
1943            };
1944            let read_path = match read_dir(&path) {
1945                Ok(r) => r,
1946                Err(e) => {
1947                    Log::warning(1102, Some(format!("{} ({})", e, path.display())));
1948                    continue;
1949                }
1950            };
1951            // Read second level dir
1952            for entry in read_path {
1953                let path = match entry {
1954                    Ok(e) => e.path(),
1955                    Err(e) => {
1956                        Log::warning(1101, Some(format!("{} ({})", e, path.display())));
1957                        continue;
1958                    }
1959                };
1960                if !path.is_dir() {
1961                    continue;
1962                }
1963
1964                let class = match path.file_name() {
1965                    Some(c) => match c.to_str() {
1966                        Some(class) => class,
1967                        None => continue,
1968                    },
1969                    None => continue,
1970                };
1971                let read_path = match read_dir(&path) {
1972                    Ok(r) => r,
1973                    Err(e) => {
1974                        Log::warning(1102, Some(format!("{} ({})", e, path.display())));
1975                        continue;
1976                    }
1977                };
1978                // Read third level dir
1979                for entry in read_path {
1980                    let path = match entry {
1981                        Ok(e) => e.path(),
1982                        Err(e) => {
1983                            Log::warning(1101, Some(format!("{} ({})", e, path.display())));
1984                            continue;
1985                        }
1986                    };
1987                    if !path.is_file() {
1988                        continue;
1989                    }
1990                    let view = match path.file_name() {
1991                        Some(v) => match v.to_str() {
1992                            Some(view) => view,
1993                            None => continue,
1994                        },
1995                        None => continue,
1996                    };
1997                    if view.ends_with(".html") && view.len() > 5 {
1998                        let view = view[..view.len() - 5].to_owned();
1999                        vec.push((path, module.to_owned(), class.to_owned(), view));
2000                    }
2001                }
2002            }
2003        }
2004        vec
2005    }
2006
2007    /// Check system time
2008    #[cfg(debug_assertions)]
2009    pub(crate) async fn check_time(&self) -> bool {
2010        let files = Html::get_files(&self.root).await;
2011        let mut last_time = SystemTime::UNIX_EPOCH;
2012        let mut hash: i128 = 0;
2013
2014        for (path, _, _, _) in files {
2015            if let Ok(metadata) = fs::metadata(&path).await {
2016                if let Ok(modified_time) = metadata.modified() {
2017                    if modified_time > last_time {
2018                        last_time = modified_time;
2019                    }
2020                    if let Some(s) = path.as_os_str().to_str() {
2021                        hash += fnv1a_64(s.as_bytes()) as i128;
2022                    }
2023                }
2024            }
2025        }
2026        last_time != self.last || hash != self.hash
2027    }
2028
2029    /// Load translates
2030    pub(crate) async fn load(&mut self) {
2031        #[cfg(debug_assertions)]
2032        let mut last_time = SystemTime::UNIX_EPOCH;
2033        #[cfg(debug_assertions)]
2034        let mut hash: i128 = 0;
2035
2036        let mut list = BTreeMap::new();
2037        let files = Html::get_files(&self.root).await;
2038
2039        for (path, module, class, view) in files {
2040            if let Ok(html) = read_to_string(&path) {
2041                #[cfg(debug_assertions)]
2042                if let Ok(metadata) = fs::metadata(&path).await {
2043                    if let Ok(modified_time) = metadata.modified() {
2044                        if modified_time > last_time {
2045                            last_time = modified_time;
2046                        }
2047                        if let Some(s) = path.as_os_str().to_str() {
2048                            hash += fnv1a_64(s.as_bytes()) as i128;
2049                        }
2050                    }
2051                }
2052
2053                // Parse templates
2054                match Html::parse(html.as_str()) {
2055                    Ok(v) => {
2056                        let module = match list.entry(fnv1a_64(module.as_bytes())) {
2057                            Entry::Vacant(entry) => entry.insert(BTreeMap::new()),
2058                            Entry::Occupied(entry) => entry.into_mut(),
2059                        };
2060                        let class = match module.entry(fnv1a_64(class.as_bytes())) {
2061                            Entry::Vacant(entry) => entry.insert(Arc::new(BTreeMap::new())),
2062                            Entry::Occupied(entry) => entry.into_mut(),
2063                        };
2064                        if let Some(views) = Arc::get_mut(class) {
2065                            views.insert(fnv1a_64(view.as_bytes()), v);
2066                        }
2067                    }
2068                    Err(e) => {
2069                        Log::warning(700, Some(format!("{} ({})", e, path.display())));
2070                        continue;
2071                    }
2072                }
2073            }
2074        }
2075        self.list = list;
2076        #[cfg(debug_assertions)]
2077        {
2078            self.last = last_time;
2079        }
2080        #[cfg(debug_assertions)]
2081        {
2082            self.hash = hash;
2083        }
2084    }
2085}