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#[derive(Debug, Clone, PartialEq)]
30pub(crate) enum Filter {
31 None,
33 Raw,
35 Len,
37 Set,
39 Unset,
41 Index,
43 Dump,
45}
46
47#[derive(Debug, Clone)]
54pub(crate) enum Value {
55 Number(i64),
57 Value { name: Vec<String>, filter: Filter },
59}
60
61#[derive(Debug, Clone)]
70pub(crate) struct For {
71 name: Value,
73 local: String,
75 nodes: Nodes,
77 empty: Option<Nodes>,
79}
80
81#[derive(Debug, Clone, PartialEq)]
93pub(crate) enum Eq {
94 None,
96 Equal,
98 NotEqual,
100 LessThan,
102 LessThanOrEqual,
104 GreaterThan,
106 GreaterThanOrEqual,
108}
109
110#[derive(Debug, Clone)]
118pub(crate) struct ExpValue {
119 val: Value,
121 eq: Eq,
123 other: Option<Value>,
125}
126
127#[derive(Debug, Clone)]
134pub(crate) struct Exp {
135 val: ExpValue,
137 nodes: Nodes,
139}
140
141#[derive(Debug, Clone)]
148pub(crate) struct If {
149 exp: Vec<Exp>,
151 else_exp: Option<Nodes>,
153}
154
155#[derive(Debug, Clone)]
163pub(crate) struct EchoValue {
164 val: Value,
166 begin: bool,
168 end: bool,
170}
171
172#[derive(Debug, Clone)]
181pub(crate) enum Node {
182 Text(String),
184 Value(EchoValue),
186 For(For),
188 IF(If),
190}
191
192#[derive(Debug, Clone, PartialEq)]
194enum ItemCondition {
195 None,
197 Text,
199 If,
201 ElseIf,
203 Else,
205 EndIf,
207 For,
209 ElseFor,
211 EndFor,
213}
214
215#[derive(Debug, Clone)]
217struct Item {
218 begin: usize,
220 end: usize,
222 text: String,
224 level: usize,
226 cond: ItemCondition,
228 child: Vec<Item>,
230}
231
232pub(crate) type Nodes = Vec<Node>;
234
235#[derive(Debug)]
241pub(crate) struct Html {
242 #[allow(clippy::type_complexity)]
251 pub list: BTreeMap<i64, BTreeMap<i64, Arc<BTreeMap<i64, Nodes>>>>,
252 #[cfg(debug_assertions)]
254 pub(crate) last: SystemTime,
255 #[cfg(debug_assertions)]
257 hash: i128,
258 root: Arc<String>,
260}
261
262impl Html {
263 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 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 let mut ignore = None;
349 while shift < len + 1 {
350 current = unsafe { html.get_unchecked(shift..shift + 2) };
352 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 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 current = unsafe { html.get_unchecked(shift..shift + 2) };
393 prev = unsafe { html.get_unchecked(shift - 1..shift) };
395 match (current, order) {
396 ("{%", false) => {
398 if prev == "@" {
399 ignore = Some(0);
400 } else {
401 idx = shift + 2;
402 }
403 shift += 2;
404 order = true;
405 }
406 ("%}", 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 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 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 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 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 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 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 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 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 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 fn get_exp(text: &str) -> Option<ExpValue> {
715 let res = text.split_whitespace().collect::<Vec<&str>>();
717 if res.len() == 1 {
718 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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("&"),
1903 '"' => new_text.push_str("""),
1904 '\'' => new_text.push_str("'"),
1905 '<' => new_text.push_str("<"),
1906 '>' => new_text.push_str(">"),
1907 _ => new_text.push(c),
1908 };
1909 }
1910 new_text
1911 }
1912
1913 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 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 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 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 #[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 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 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}