cyfs_lib/base/
exp_filter.rs

1use cyfs_base::*;
2
3#[derive(Debug, Eq, PartialEq)]
4enum ExpLexItem {
5    Op(ExpOp),
6    LeftParen,
7    RightParen,
8    Token(String),
9}
10
11// 操作符的元数,目前只支持一元和二元操作符
12pub enum ExpOpArity {
13    Unary,
14    Binary,
15}
16
17#[derive(Debug, Eq, PartialEq, Clone)]
18pub enum ExpOp {
19    // ==
20    EQ,
21
22    // !=
23    NE,
24
25    // <
26    LT,
27
28    // <=
29    LE,
30
31    // >
32    GT,
33
34    // >=
35    GE,
36
37    // !
38    NOT,
39
40    // &&
41    AND,
42
43    // 支持三个位操作,和整型数操作结果转化为bool(0 -> false, 1 -> true)
44    // &
45    BAND,
46
47    // |
48    BOR,
49
50    // ^
51    BXOR,
52
53    // ||
54    OR,
55}
56
57impl ExpOp {
58    fn arity(&self) -> ExpOpArity {
59        match &self {
60            ExpOp::NOT => ExpOpArity::Unary,
61            _ => ExpOpArity::Binary,
62        }
63    }
64
65    // 获取运算符优先级
66    fn priority(&self) -> u8 {
67        match &self {
68            ExpOp::NOT => 17,
69            ExpOp::LT | ExpOp::LE | ExpOp::GT | ExpOp::GE => 12,
70            ExpOp::NE | ExpOp::EQ => 11,
71            ExpOp::BAND => 10,
72            ExpOp::BXOR => 9,
73            ExpOp::BOR => 8,
74            ExpOp::AND => 7,
75            ExpOp::OR => 6,
76        }
77    }
78
79    fn from_str(s: &str) -> Option<Self> {
80        let ret = match s {
81            "==" => Self::EQ,
82            "!=" => Self::NE,
83
84            "<" => Self::LT,
85            "<=" => Self::LE,
86
87            ">" => Self::GT,
88            ">=" => Self::GE,
89
90            "!" => Self::NOT,
91
92            "&&" => Self::AND,
93            "||" => Self::OR,
94
95            "&" => Self::BAND,
96            "^" => Self::BXOR,
97            "|" => Self::BOR,
98
99            _ => {
100                return None;
101            }
102        };
103
104        Some(ret)
105    }
106
107    fn to_str(&self) -> &str {
108        match *self {
109            Self::EQ => "==",
110            Self::NE => "!=",
111
112            Self::LT => "<",
113            Self::LE => "<=",
114
115            Self::GT => ">",
116            Self::GE => ">=",
117
118            Self::NOT => "!",
119
120            Self::AND => "&&",
121            Self::OR => "||",
122
123            Self::BAND => "&",
124            Self::BXOR => "^",
125            Self::BOR => "|",
126        }
127    }
128
129    pub fn parse(ch: char, it: &mut std::str::Chars<'_>) -> Option<Self> {
130        let result = match ch {
131            '!' => match it.clone().next() {
132                Some('=') => {
133                    it.next();
134                    Self::NE
135                }
136                _ => Self::NOT,
137            },
138            '=' => match it.next() {
139                Some('=') => Self::EQ,
140                _ => return None,
141            },
142            '>' => match it.clone().next() {
143                Some('=') => {
144                    it.next();
145                    Self::GE
146                }
147                _ => Self::GT,
148            },
149            '<' => match it.clone().next() {
150                Some('=') => {
151                    it.next();
152                    Self::LE
153                }
154                _ => Self::LT,
155            },
156            '&' => match it.clone().next() {
157                Some('&') => {
158                    it.next();
159                    Self::AND
160                }
161                _ => Self::BAND,
162            },
163            '|' => match it.clone().next() {
164                Some('|') => {
165                    it.next();
166                    Self::OR
167                }
168                _ => Self::BOR,
169            },
170            '^' => Self::BXOR,
171            _ => return None,
172        };
173
174        Some(result)
175    }
176}
177
178// 解析引号之间的token,支持单引号和双引号,但开始和结束必须匹配
179#[derive(Eq, PartialEq)]
180enum ExpTokenQuote {
181    Single,
182    Double,
183    None,
184}
185
186enum ExpTokenQuoteParserResult {
187    Continue,
188    Begin,
189    Token,
190    End,
191}
192
193impl ExpTokenQuote {
194    fn from_char(c: char) -> Self {
195        match c {
196            '"' => Self::Double,
197            '\'' => Self::Single,
198            _ => Self::None,
199        }
200    }
201}
202
203struct ExpTokenQuoteParser {
204    state: ExpTokenQuote,
205}
206
207impl ExpTokenQuoteParser {
208    pub fn new() -> Self {
209        Self {
210            state: ExpTokenQuote::None,
211        }
212    }
213
214    // 返回值
215    fn next(&mut self, exp: &str, c: char) -> BuckyResult<ExpTokenQuoteParserResult> {
216        match ExpTokenQuote::from_char(c) {
217            ExpTokenQuote::None => match self.state {
218                ExpTokenQuote::None => return Ok(ExpTokenQuoteParserResult::Continue),
219                _ => Ok(ExpTokenQuoteParserResult::Token),
220            },
221            state @ _ => match self.state {
222                ExpTokenQuote::None => {
223                    self.state = state;
224                    Ok(ExpTokenQuoteParserResult::Begin)
225                }
226                _ => {
227                    if self.state != state {
228                        let msg = format!("filter exp quote unmatch! exp={}", exp);
229                        error!("{}", msg);
230                        return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
231                    }
232
233                    self.state = ExpTokenQuote::None;
234                    Ok(ExpTokenQuoteParserResult::End)
235                }
236            },
237        }
238    }
239}
240
241//name op value
242//((obj_type >= 0 && obj_type <= 10 ) || obj_type == 100 && !first_time)
243struct ExpParser;
244
245const EXP_TOKEN_QUOTES: [char; 2] = ['\'', '"'];
246
247impl ExpParser {
248    // 判断一个字符是不是操作数
249    fn is_operand_char(ch: char) -> bool {
250        ch.is_ascii_alphabetic()
251            || ch.is_numeric()
252            || ch == '-'
253            || ch == '_'
254            || ch == '.'
255            || ch == '$'
256            || ch == '*'
257            || ch == '/'
258            || ch == '\\'
259    }
260
261    fn parse_token(token: &[char]) -> BuckyResult<ExpLexItem> {
262        let s: String = token.iter().collect();
263
264        match ExpOp::from_str(&s) {
265            Some(op) => Ok(ExpLexItem::Op(op)),
266            None => {
267                // 检查是不是有效token
268                for ch in token {
269                    if !Self::is_operand_char(*ch) {
270                        let msg = format!("invalid exp token: {}", s);
271                        error!("{}", msg);
272
273                        return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
274                    }
275                }
276
277                // 尝试去掉引号
278                let s = s
279                    .trim_start_matches(&EXP_TOKEN_QUOTES[..])
280                    .trim_end_matches(&EXP_TOKEN_QUOTES[..]);
281
282                Ok(ExpLexItem::Token(s.to_owned()))
283            }
284        }
285    }
286
287    fn direct_parse_token(token: &[char]) -> BuckyResult<ExpLexItem> {
288        let s: String = token.iter().collect();
289
290        // 尝试去掉引号
291        let s = s
292            .trim_start_matches(&EXP_TOKEN_QUOTES[..])
293            .trim_end_matches(&EXP_TOKEN_QUOTES[..]);
294
295        Ok(ExpLexItem::Token(s.to_owned()))
296    }
297
298    // 转为逆波兰表达式
299    fn convert_to_rpn(exp: &str, list: Vec<ExpLexItem>) -> BuckyResult<Vec<ExpLexItem>> {
300        let mut operands = vec![];
301        let mut operators = vec![];
302
303        for item in list {
304            match item {
305                ExpLexItem::Token(ref _v) => {
306                    operands.push(item);
307                }
308                ExpLexItem::LeftParen => {
309                    operators.push(item);
310                }
311                ExpLexItem::RightParen => {
312                    // 弹出所有操作符,直到左括号
313                    loop {
314                        match operators.pop() {
315                            Some(v) => match v {
316                                ExpLexItem::LeftParen => {
317                                    break;
318                                }
319                                _ => {
320                                    operands.push(v);
321                                }
322                            },
323                            None => {
324                                let msg = format!("unmatch exp paren: {}", exp);
325                                error!("{}", msg);
326
327                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
328                            }
329                        }
330                    }
331                }
332
333                ExpLexItem::Op(v) => {
334                    loop {
335                        let last_op = operators.last();
336
337                        // 如果运算符堆栈为空,那么直接放入运算符堆栈
338                        if last_op.is_none() {
339                            operators.push(ExpLexItem::Op(v));
340                            break;
341                        }
342
343                        let last_op = last_op.unwrap();
344
345                        // 处理!!情况
346                        if v == ExpOp::NOT {
347                            if let ExpLexItem::Op(prev) = last_op {
348                                if *prev == v {
349                                    operators.pop();
350                                    break;
351                                }
352                            }
353                        }
354
355                        // 取出栈顶比当前运算符优先级低的运算符,放入操作数堆栈
356                        match last_op {
357                            ExpLexItem::Op(lv) => {
358                                // 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈
359                                if v.priority() > lv.priority() {
360                                    operators.push(ExpLexItem::Op(v));
361                                    break;
362                                } else {
363                                    let last_op = operators.pop().unwrap();
364                                    operands.push(last_op);
365                                }
366                            }
367                            // 若运算符堆栈栈顶的运算符为括号(只可能是左括号),则直接存入运算符堆栈。
368                            ExpLexItem::LeftParen => {
369                                operators.push(ExpLexItem::Op(v));
370                                break;
371                            }
372                            _ => unreachable!(),
373                        }
374                    }
375                }
376            }
377        }
378
379        // 表达式读取完毕,剩余的运算符依次放入操作数堆栈
380        while !operators.is_empty() {
381            let op = operators.pop().unwrap();
382            operands.push(op);
383        }
384
385        /*
386        if !operators.is_empty() {
387            let msg = format!("invalid exp: {}, {:?}", exp, operators);
388            error!("{}", msg);
389
390            return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
391        }
392        */
393
394        Ok(operands)
395    }
396
397    pub fn parse_lex(exp: &str) -> BuckyResult<Vec<ExpLexItem>> {
398        let mut it = exp.chars();
399
400        let mut token_list = vec![];
401        let mut token = vec![];
402        let mut quote_parse = ExpTokenQuoteParser::new();
403        loop {
404            match it.next() {
405                Some(c) => {
406                    // 首先需要解析是不是引号括起来的内容
407                    match quote_parse.next(exp, c)? {
408                        ExpTokenQuoteParserResult::Continue => {
409                            // 无关,继续下面的解析
410                        }
411                        ExpTokenQuoteParserResult::Token => {
412                            token.push(c);
413                            continue;
414                        }
415                        ExpTokenQuoteParserResult::Begin => {
416                            continue;
417                        }
418                        ExpTokenQuoteParserResult::End => {
419                            token_list.push(Self::direct_parse_token(&token)?);
420                            token.clear();
421                            continue;
422                        }
423                    }
424                    if c.is_whitespace() {
425                        if !token.is_empty() {
426                            token_list.push(Self::parse_token(&token)?);
427                            token.clear();
428                        }
429                        continue;
430                    }
431
432                    match c {
433                        '(' => {
434                            if !token.is_empty() {
435                                token_list.push(Self::parse_token(&token)?);
436                                token.clear();
437                            }
438                            token_list.push(ExpLexItem::LeftParen);
439                        }
440                        ')' => {
441                            if !token.is_empty() {
442                                token_list.push(Self::parse_token(&token)?);
443                                token.clear();
444                            }
445                            token_list.push(ExpLexItem::RightParen);
446                        }
447                        _ => {
448                            if Self::is_operand_char(c) {
449                                token.push(c);
450                            } else {
451                                match ExpOp::parse(c, &mut it) {
452                                    Some(op) => {
453                                        if !token.is_empty() {
454                                            token_list.push(Self::parse_token(&token)?);
455                                            token.clear();
456                                        }
457
458                                        token_list.push(ExpLexItem::Op(op));
459                                    }
460                                    None => {
461                                        let msg = format!(
462                                            "invalid operand or operator: exp={}, char={}, token={}",
463                                            exp,
464                                            c,
465                                            it.as_str()
466                                        );
467                                        error!("{}", msg);
468                                        return Err(BuckyError::new(
469                                            BuckyErrorCode::InvalidFormat,
470                                            msg,
471                                        ));
472                                    }
473                                }
474                            }
475                        }
476                    }
477                }
478                None => {
479                    break;
480                }
481            }
482        }
483        if !token.is_empty() {
484            token_list.push(Self::parse_token(&token)?);
485        }
486
487        debug!("exp to lex list: exp={}, list={:?}", exp, token_list);
488
489        // 转为逆波兰表达式
490        Self::convert_to_rpn(exp, token_list)
491    }
492}
493
494pub struct ExpReservedTokenList {
495    list: Vec<(String, ExpTokenEvalValue)>,
496}
497
498impl ExpReservedTokenList {
499    pub fn new() -> Self {
500        Self { list: Vec::new() }
501    }
502
503    // 添加前缀
504    pub fn translate(&mut self, prefix: &str) {
505        self.list
506            .iter_mut()
507            .for_each(|v| v.0 = format!("{}.{}", prefix, v.0));
508    }
509
510    // 为所有条目添加"resp."前缀
511    pub fn translate_resp(&mut self) {
512        self.translate("resp");
513    }
514
515    pub fn append(&mut self, other: Self) {
516        for item in other.list {
517            assert!(!self.is_reserved_token(&item.0));
518
519            self.list.push(item);
520        }
521    }
522
523    fn add_token(&mut self, token: &str, default_value: ExpTokenEvalValue) {
524        assert!(!self.is_reserved_token(token));
525
526        self.list.push((token.to_owned(), default_value));
527    }
528
529    pub fn add_string(&mut self, token: &str) {
530        self.add_token(token, ExpTokenEvalValue::String(String::default()))
531    }
532
533    pub fn add_glob(&mut self, token: &str) {
534        self.add_token(token, ExpTokenEvalValue::Glob(ExpGlobToken::default()))
535    }
536
537    pub fn add_bool(&mut self, token: &str) {
538        self.add_token(token, ExpTokenEvalValue::Bool(false))
539    }
540
541    pub fn add_i8(&mut self, token: &str) {
542        self.add_token(token, ExpTokenEvalValue::I8(0))
543    }
544    pub fn add_i16(&mut self, token: &str) {
545        self.add_token(token, ExpTokenEvalValue::I16(0))
546    }
547    pub fn add_i32(&mut self, token: &str) {
548        self.add_token(token, ExpTokenEvalValue::I32(0))
549    }
550    pub fn add_i64(&mut self, token: &str) {
551        self.add_token(token, ExpTokenEvalValue::I64(0))
552    }
553
554    pub fn add_u8(&mut self, token: &str) {
555        self.add_token(token, ExpTokenEvalValue::U8(0))
556    }
557    pub fn add_u16(&mut self, token: &str) {
558        self.add_token(token, ExpTokenEvalValue::U16(0))
559    }
560    pub fn add_u32(&mut self, token: &str) {
561        self.add_token(token, ExpTokenEvalValue::U32(0))
562    }
563    pub fn add_u64(&mut self, token: &str) {
564        self.add_token(token, ExpTokenEvalValue::U64(0))
565    }
566
567    pub fn is_reserved_token(&self, token: &str) -> bool {
568        self.list.iter().find(|v| v.0.as_str() == token).is_some()
569    }
570
571    pub fn default_value(&self, token: &str) -> Option<ExpTokenEvalValue> {
572        self.list
573            .iter()
574            .find(|v| v.0.as_str() == token)
575            .map(|v| v.1.clone())
576    }
577}
578
579impl ExpReservedTokenTranslator for ExpReservedTokenList {
580    fn trans(&self, token: &str) -> ExpTokenEvalValue {
581        self.default_value(token).unwrap()
582    }
583}
584
585impl ExpReservedTokenTranslator for &ExpReservedTokenList {
586    fn trans(&self, token: &str) -> ExpTokenEvalValue {
587        self.default_value(token).unwrap()
588    }
589}
590
591#[derive(Clone, Debug)]
592pub enum ExpGlobToken {
593    Glob(globset::GlobMatcher),
594    StringList(Vec<String>),
595    String(String),
596}
597
598impl ExpGlobToken {
599    pub fn new_glob(token: &str) -> BuckyResult<Self> {
600        let glob = globset::GlobBuilder::new(token)
601            .case_insensitive(true)
602            .literal_separator(true)
603            .build()
604            .map_err(|e| {
605                let msg = format!("parse filter glob as glob error! token={}, {}", token, e);
606                error!("{}", msg);
607                BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
608            })?;
609
610        Ok(Self::Glob(glob.compile_matcher()))
611    }
612
613    // 对于一个req_path,确保req_path和req_path/都在匹配列表里面
614    fn append_string(list: &mut Vec<String>, token: String) {
615        let s = token.trim_end_matches('/');
616        if s.len() == token.len() {
617            list.push(format!("{}/", s));
618            drop(s);
619            list.push(token);
620        } else {
621            list.push(s.to_owned());
622            if s.len() + 1 == token.len() {
623                drop(s);
624                list.push(token);
625            } else {
626                list.push(format!("{}/", s));
627            }
628        }
629    }
630
631    pub fn new_string(token: String) -> Self {
632        let mut list = Vec::with_capacity(2);
633        Self::append_string(&mut list, token);
634        Self::StringList(list)
635    }
636
637    pub fn new_string_list(tokens: Vec<String>) -> Self {
638        let mut list = Vec::with_capacity(tokens.len() * 2);
639        for token in tokens {
640            Self::append_string(&mut list, token);
641        }
642        Self::StringList(list)
643    }
644
645    pub fn is_glob(&self) -> bool {
646        match *self {
647            Self::Glob(_) => true,
648            _ => false,
649        }
650    }
651
652    pub fn as_glob(&self) -> &globset::GlobMatcher {
653        match self {
654            Self::Glob(v) => v,
655            _ => unreachable!(),
656        }
657    }
658
659    // 左右必须一个glob,一个string
660    pub fn eq(left: &Self, right: &Self) -> bool {
661        match left {
662            Self::Glob(_) => Self::eq(right, left),
663            Self::String(s) => right.as_glob().is_match(s),
664            Self::StringList(list) => {
665                for s in list {
666                    if right.as_glob().is_match(&s) {
667                        return true;
668                    }
669                }
670
671                false
672            }
673        }
674    }
675}
676
677impl Default for ExpGlobToken {
678    fn default() -> Self {
679        Self::new_string("".to_owned())
680    }
681}
682
683impl PartialEq for ExpGlobToken {
684    fn eq(&self, other: &Self) -> bool {
685        Self::eq(&self, other)
686    }
687}
688impl Eq for ExpGlobToken {}
689
690impl PartialOrd for ExpGlobToken {
691    fn partial_cmp(&self, _other: &Self) -> Option<std::cmp::Ordering> {
692        unreachable!();
693    }
694}
695
696impl Ord for ExpGlobToken {
697    fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
698        unreachable!();
699    }
700}
701
702// token用以计算的目标类型
703#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
704pub enum ExpTokenEvalValue {
705    // 空值
706    None,
707
708    String(String),
709    Glob(ExpGlobToken),
710    Bool(bool),
711
712    I8(i8),
713    I16(i16),
714    I32(i32),
715    I64(i64),
716
717    U8(u8),
718    U16(u16),
719    U32(u32),
720    U64(u64),
721}
722
723impl Into<i8> for ExpTokenEvalValue {
724    fn into(self) -> i8 {
725        match self {
726            Self::I8(v) => v,
727            _ => unreachable!(),
728        }
729    }
730}
731impl Into<i16> for ExpTokenEvalValue {
732    fn into(self) -> i16 {
733        match self {
734            Self::I16(v) => v,
735            _ => unreachable!(),
736        }
737    }
738}
739impl Into<i32> for ExpTokenEvalValue {
740    fn into(self) -> i32 {
741        match self {
742            Self::I32(v) => v,
743            _ => unreachable!(),
744        }
745    }
746}
747impl Into<i64> for ExpTokenEvalValue {
748    fn into(self) -> i64 {
749        match self {
750            Self::I64(v) => v,
751            _ => unreachable!(),
752        }
753    }
754}
755
756impl Into<u8> for ExpTokenEvalValue {
757    fn into(self) -> u8 {
758        match self {
759            Self::U8(v) => v,
760            _ => unreachable!(),
761        }
762    }
763}
764impl Into<u16> for ExpTokenEvalValue {
765    fn into(self) -> u16 {
766        match self {
767            Self::U16(v) => v,
768            _ => unreachable!(),
769        }
770    }
771}
772impl Into<u32> for ExpTokenEvalValue {
773    fn into(self) -> u32 {
774        match self {
775            Self::U32(v) => v,
776            _ => unreachable!(),
777        }
778    }
779}
780impl Into<u64> for ExpTokenEvalValue {
781    fn into(self) -> u64 {
782        match self {
783            Self::U64(v) => v,
784            _ => unreachable!(),
785        }
786    }
787}
788
789// 对from_str_radix封装一级trait
790trait FromStrRadix<T> {
791    fn from_str_radix(src: &str, radix: u32) -> Result<T, std::num::ParseIntError>;
792}
793
794macro_rules! from_str_radix_trait_impl {
795    ($T:ty) => {
796        impl FromStrRadix<$T> for $T {
797            fn from_str_radix(src: &str, radix: u32) -> Result<$T, std::num::ParseIntError> {
798                <$T>::from_str_radix(src, radix)
799            }
800        }
801    };
802}
803from_str_radix_trait_impl!(i8);
804from_str_radix_trait_impl!(i16);
805from_str_radix_trait_impl!(i32);
806from_str_radix_trait_impl!(i64);
807from_str_radix_trait_impl!(u8);
808from_str_radix_trait_impl!(u16);
809from_str_radix_trait_impl!(u32);
810from_str_radix_trait_impl!(u64);
811
812impl ExpTokenEvalValue {
813    pub fn from_string<T>(v: &T) -> Self
814    where
815        T: ToString,
816    {
817        Self::String(v.to_string())
818    }
819
820    pub fn from_opt_string<T>(v: &Option<T>) -> Self
821    where
822        T: ToString,
823    {
824        match v {
825            Some(v) => Self::String(v.to_string()),
826            None => Self::None,
827        }
828    }
829
830    pub fn from_glob_list<T>(v: &Vec<T>) -> Self
831    where
832        T: ToString,
833    {
834        let list: Vec<String> = v.iter().map(|v| v.to_string()).collect();
835        Self::Glob(ExpGlobToken::new_string_list(list))
836    }
837
838    pub fn from_opt_glob<T>(v: &Option<T>) -> Self
839    where
840        T: ToString,
841    {
842        match v {
843            Some(v) => Self::Glob(ExpGlobToken::new_string(v.to_string())),
844            None => Self::None,
845        }
846    }
847
848    pub fn from_opt_u64(v: Option<u64>) -> Self
849    {
850        match v {
851            Some(v) => Self::U64(v),
852            None => Self::None,
853        }
854    }
855
856    pub fn is_none(&self) -> bool {
857        match *self {
858            Self::None => true,
859            _ => false,
860        }
861    }
862
863    // 判断是不是独立的token,比如*
864    pub fn try_from_single_const_token(token: &str) -> Option<Self> {
865        if token == "*" {
866            Some(Self::Bool(true))
867        } else {
868            None
869        }
870    }
871
872    pub fn new_from_const_token(target: &ExpTokenEvalValue, token: &str) -> BuckyResult<Self> {
873        // info!("token={}", token);
874        if token == "$none" {
875            return Ok(Self::None);
876        }
877
878        let ret = match target {
879            Self::None => unreachable!(),
880            Self::String(_) => Self::String(token.to_owned()),
881            Self::Glob(_) => Self::Glob(ExpGlobToken::new_glob(token)?),
882            Self::Bool(_) => {
883                let v;
884                if token == "true" || token == "1" {
885                    v = true;
886                } else if token == "false" || token == "0" {
887                    v = false;
888                } else {
889                    let msg = format!("invalid const value, bool expected: {}", token);
890                    error!("{}", msg);
891                    return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
892                }
893                Self::Bool(v)
894            }
895            Self::I8(_) => {
896                let v = Self::parse_number(token, "i8")?;
897                Self::I8(v)
898            }
899            Self::I16(_) => {
900                let v = Self::parse_number(token, "i16")?;
901                Self::I16(v)
902            }
903            Self::I32(_) => {
904                let v = Self::parse_number(token, "i32")?;
905                Self::I32(v)
906            }
907            Self::I64(_) => {
908                let v = Self::parse_number(token, "i64")?;
909                Self::I64(v)
910            }
911
912            Self::U8(_) => {
913                let v = Self::parse_number(token, "u8")?;
914                Self::U8(v)
915            }
916            Self::U16(_) => {
917                let v = Self::parse_number(token, "u16")?;
918                Self::U16(v)
919            }
920            Self::U32(_) => {
921                let v = Self::parse_number(token, "u32")?;
922                Self::U32(v)
923            }
924            Self::U64(_) => {
925                let v = Self::parse_number(token, "u64")?;
926                Self::U64(v)
927            }
928        };
929
930        Ok(ret)
931    }
932
933    /*
934    fn parse_number<I>(token: &str, type_name: &str) -> BuckyResult<I>
935    where
936        I: FromStr,
937        <I as FromStr>::Err: std::fmt::Display,
938    {
939        I::from_str(token).map_err(|e| {
940            let msg = format!(
941                "invalid number value, {} expected: {}, {}",
942                type_name, token, e
943            );
944            error!("{}", msg);
945            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
946        })
947    }
948    */
949
950    fn parse_number<I>(token: &str, type_name: &str) -> BuckyResult<I>
951    where
952        I: FromStrRadix<I>,
953    {
954        let radix = if token.starts_with("0x") || token.starts_with("0X") {
955            16
956        } else if token.starts_with("0o") || token.starts_with("0O") {
957            8
958        } else if token.starts_with("0b") || token.starts_with("0B") {
959            2
960        } else {
961            10
962        };
963
964        let token = if radix != 10 {
965            token.split_at(2).1
966        } else {
967            token
968        };
969
970        I::from_str_radix(token, radix).map_err(|e| {
971            let msg = format!(
972                "invalid number value, {} expected: {}, {}",
973                type_name, token, e
974            );
975            error!("{}", msg);
976            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
977        })
978    }
979
980    pub fn support_ops(&self) -> Vec<ExpOp> {
981        match *self {
982            Self::String(_) | Self::Glob(_) | Self::None => vec![ExpOp::EQ, ExpOp::NE],
983            Self::Bool(_) => vec![
984                ExpOp::EQ,
985                ExpOp::NE,
986                ExpOp::LT,
987                ExpOp::LE,
988                ExpOp::GT,
989                ExpOp::GE,
990                ExpOp::NOT,
991                ExpOp::AND,
992                ExpOp::OR,
993            ],
994
995            // 剩余所有的整型数
996            _ => vec![
997                ExpOp::EQ,
998                ExpOp::NE,
999                ExpOp::LT,
1000                ExpOp::LE,
1001                ExpOp::GT,
1002                ExpOp::GE,
1003                ExpOp::NOT,
1004                ExpOp::BAND,
1005                ExpOp::BOR,
1006                ExpOp::BXOR,
1007            ],
1008        }
1009    }
1010
1011    pub fn is_support_op(&self, op: &ExpOp) -> bool {
1012        self.support_ops().contains(op)
1013    }
1014
1015    pub fn as_bool(&self) -> Option<bool> {
1016        match self {
1017            Self::Bool(v) => Some(*v),
1018            _ => None,
1019        }
1020    }
1021
1022    // 如果是整型数,那么尝试进行|位运算,结果为bool类型
1023    fn bitor(&self, rhs: &Self) -> bool {
1024        let rhs = rhs.to_owned();
1025        match *self {
1026            Self::I8(v) => v | Into::<i8>::into(rhs) != 0,
1027            Self::I16(v) => v | Into::<i16>::into(rhs) != 0,
1028            Self::I32(v) => v | Into::<i32>::into(rhs) != 0,
1029            Self::I64(v) => v | Into::<i64>::into(rhs) != 0,
1030
1031            Self::U8(v) => v | Into::<u8>::into(rhs) != 0,
1032            Self::U16(v) => v | Into::<u16>::into(rhs) != 0,
1033            Self::U32(v) => v | Into::<u32>::into(rhs) != 0,
1034            Self::U64(v) => v | Into::<u64>::into(rhs) != 0,
1035            _ => {
1036                unreachable!("bitor only for int numbers");
1037            }
1038        }
1039    }
1040
1041    fn bitand(&self, rhs: &Self) -> bool {
1042        let rhs = rhs.to_owned();
1043        match *self {
1044            Self::I8(v) => v & Into::<i8>::into(rhs) != 0,
1045            Self::I16(v) => v & Into::<i16>::into(rhs) != 0,
1046            Self::I32(v) => v & Into::<i32>::into(rhs) != 0,
1047            Self::I64(v) => v & Into::<i64>::into(rhs) != 0,
1048
1049            Self::U8(v) => v & Into::<u8>::into(rhs) != 0,
1050            Self::U16(v) => v & Into::<u16>::into(rhs) != 0,
1051            Self::U32(v) => v & Into::<u32>::into(rhs) != 0,
1052            Self::U64(v) => v & Into::<u64>::into(rhs) != 0,
1053            _ => {
1054                unreachable!("bitand only for int numbers");
1055            }
1056        }
1057    }
1058
1059    fn bitxor(&self, rhs: &Self) -> bool {
1060        let rhs = rhs.to_owned();
1061        match *self {
1062            Self::I8(v) => v ^ Into::<i8>::into(rhs) != 0,
1063            Self::I16(v) => v ^ Into::<i16>::into(rhs) != 0,
1064            Self::I32(v) => v ^ Into::<i32>::into(rhs) != 0,
1065            Self::I64(v) => v ^ Into::<i64>::into(rhs) != 0,
1066
1067            Self::U8(v) => v ^ Into::<u8>::into(rhs) != 0,
1068            Self::U16(v) => v ^ Into::<u16>::into(rhs) != 0,
1069            Self::U32(v) => v ^ Into::<u32>::into(rhs) != 0,
1070            Self::U64(v) => v ^ Into::<u64>::into(rhs) != 0,
1071            _ => {
1072                unreachable!("bitxor only for int numbers");
1073            }
1074        }
1075    }
1076}
1077
1078// 关键字计算为具体的值
1079pub trait ExpReservedTokenTranslator {
1080    fn trans(&self, token: &str) -> ExpTokenEvalValue;
1081}
1082
1083#[derive(Debug, Clone)]
1084enum ExpEvalItem {
1085    Op(ExpOp),
1086
1087    ReservedToken(String),
1088
1089    // 常量,目前只支持string
1090    ConstToken(String),
1091
1092    // 经过目标类型转换的token
1093    EvalToken(ExpTokenEvalValue),
1094}
1095
1096impl ExpEvalItem {
1097    pub fn trans(self, translator: &impl ExpReservedTokenTranslator) -> Self {
1098        match self {
1099            Self::ReservedToken(v) => ExpEvalItem::EvalToken(translator.trans(&v)),
1100            _ => self,
1101        }
1102    }
1103
1104    pub fn is_token(&self) -> bool {
1105        match self {
1106            Self::Op(_) => false,
1107            _ => true,
1108        }
1109    }
1110
1111    pub fn is_const_token(&self) -> bool {
1112        match self {
1113            Self::ConstToken(_) => true,
1114            _ => false,
1115        }
1116    }
1117
1118    pub fn is_reserved_token(&self) -> bool {
1119        match self {
1120            Self::ReservedToken(_) => true,
1121            _ => false,
1122        }
1123    }
1124
1125    pub fn is_eval_token(&self) -> bool {
1126        match self {
1127            Self::EvalToken(_) => true,
1128            _ => false,
1129        }
1130    }
1131
1132    pub fn into_const_token(self) -> String {
1133        match self {
1134            Self::ConstToken(v) => v,
1135            _ => unreachable!(),
1136        }
1137    }
1138
1139    pub fn into_eval_value(self) -> ExpTokenEvalValue {
1140        match self {
1141            Self::EvalToken(v) => v,
1142            _ => unreachable!(),
1143        }
1144    }
1145}
1146
1147pub struct ExpEvaluator {
1148    exp: String,
1149    rpn: Vec<ExpEvalItem>,
1150}
1151
1152impl std::fmt::Debug for ExpEvaluator {
1153    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1154        write!(f, "{}", self.exp)?;
1155
1156        Ok(())
1157    }
1158}
1159
1160impl std::fmt::Display for ExpEvaluator {
1161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1162        write!(f, "{}", self.exp)?;
1163
1164        Ok(())
1165    }
1166}
1167
1168impl PartialEq for ExpEvaluator {
1169    fn eq(&self, other: &Self) -> bool {
1170        self.exp() == other.exp()
1171    }
1172}
1173impl Eq for ExpEvaluator {}
1174
1175use std::cmp::Ordering;
1176impl PartialOrd for ExpEvaluator {
1177    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1178        self.exp().partial_cmp(other.exp())
1179    }
1180}
1181
1182impl Ord for ExpEvaluator {
1183    fn cmp(&self, other: &Self) -> Ordering {
1184        self.partial_cmp(other).unwrap()
1185    }
1186}
1187
1188
1189impl ExpEvaluator {
1190    pub fn new(exp: impl Into<String>, reserved_token_list: &ExpReservedTokenList) -> BuckyResult<Self> {
1191        let exp = exp.into();
1192        let lex_list = ExpParser::parse_lex(&exp)?;
1193        // 不支持空表达式
1194        if lex_list.is_empty() {
1195            let msg = format!("empty exp filter not supported! exp={}", exp);
1196            error!("{}", msg);
1197            return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1198        }
1199
1200        debug!("exp to rpn lex list: exp={}, list={:?}", exp, lex_list);
1201
1202        let rpn = Self::convert(&exp, lex_list, reserved_token_list)?;
1203
1204        Ok(Self {
1205            exp,
1206            rpn,
1207        })
1208    }
1209
1210    pub fn new_uninit(exp: impl Into<String>) -> Self {
1211        let exp = exp.into();
1212        
1213        Self {
1214            exp,
1215            rpn: vec![],
1216        }
1217    }
1218
1219    pub fn exp(&self) -> &str {
1220        &self.exp
1221    }
1222
1223    pub fn into_exp(self) -> String {
1224        self.exp
1225    }
1226    
1227    fn convert(
1228        exp: &str,
1229        lex_list: Vec<ExpLexItem>,
1230        reserved_token_list: &ExpReservedTokenList,
1231    ) -> BuckyResult<Vec<ExpEvalItem>> {
1232        // 分离token,解析为保留关键字和常量
1233        let mut result = vec![];
1234        for item in lex_list.into_iter() {
1235            match item {
1236                ExpLexItem::Op(v) => {
1237                    result.push(ExpEvalItem::Op(v));
1238                }
1239                ExpLexItem::Token(v) => {
1240                    if reserved_token_list.is_reserved_token(&v) {
1241                        result.push(ExpEvalItem::ReservedToken(v));
1242                    } else {
1243                        result.push(ExpEvalItem::ConstToken(v));
1244                    }
1245                }
1246                _ => unreachable!(),
1247            }
1248        }
1249
1250        debug!("exp lex to eval: {:?}", result);
1251
1252        // 表达式类型检测和常量解析
1253        Self::check_and_convert(exp, result, reserved_token_list)
1254    }
1255
1256    fn check_and_convert(
1257        exp: &str,
1258        mut rpn: Vec<ExpEvalItem>,
1259        translator: &impl ExpReservedTokenTranslator,
1260    ) -> BuckyResult<Vec<ExpEvalItem>> {
1261        // 目前所有表达式的中间结果都是bool值
1262        let mid_result = ExpEvalItem::EvalToken(ExpTokenEvalValue::Bool(false));
1263
1264        let mut operands: Vec<(ExpEvalItem, usize)> = vec![];
1265        let mut result = vec![];
1266
1267        for (i, item) in rpn.iter().enumerate() {
1268            match item {
1269                ExpEvalItem::Op(op) => {
1270                    match op.arity() {
1271                        ExpOpArity::Unary => {
1272                            if operands.len() < 1 {
1273                                let msg = format!(
1274                                    "exp operator need one operands, got none: exp={}, op='{}'",
1275                                    exp,
1276                                    op.to_str()
1277                                );
1278                                error!("{}", msg);
1279                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1280                            }
1281
1282                            // 单操作符,操作数必须是关键字or中间结果,不能是常量
1283                            let (operand, _) = operands.pop().unwrap();
1284                            if operand.is_const_token() {
1285                                let msg = format!(
1286                                    "unary operator not support const token: exp={}, op='{}'",
1287                                    exp,
1288                                    op.to_str()
1289                                );
1290                                error!("{}", msg);
1291                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1292                            }
1293
1294                            let value = operand.into_eval_value();
1295
1296                            // 判断是否支持操作符
1297                            if !value.is_support_op(op) {
1298                                let msg = format!("operand not support operator: exp={}, operator={}, operand={:?}", exp, op.to_str(), value);
1299                                error!("{}", msg);
1300                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1301                            }
1302
1303                            // 结果直接压入操作数堆栈
1304                            operands.push((mid_result.clone(), usize::MAX));
1305                        }
1306                        ExpOpArity::Binary => {
1307                            if operands.len() < 2 {
1308                                let msg = format!(
1309                                    "exp operator need two operands, got one: {}",
1310                                    op.to_str()
1311                                );
1312                                error!("{}", msg);
1313                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1314                            }
1315
1316                            let (right, right_index) = operands.pop().unwrap();
1317                            let (left, left_index) = operands.pop().unwrap();
1318
1319                            // 二元运算,至少要有一个关键字或者一个中间结果,不能两个都是常量
1320                            if left.is_const_token() && right.is_const_token() {
1321                                let msg = format!(
1322                                    "binary operator not support two const token: exp={}, op='{}'",
1323                                    exp,
1324                                    op.to_str()
1325                                );
1326                                error!("{}", msg);
1327                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1328                            }
1329
1330                            // 确保左操作数不是常量
1331                            let (left, _left_index, right, right_index) = if left.is_eval_token() {
1332                                (left, left_index, right, right_index)
1333                            } else {
1334                                (right, right_index, left, left_index)
1335                            };
1336
1337                            assert!(!left.is_const_token());
1338
1339                            let left_value = left.into_eval_value();
1340                            // 检查是否支持运算符
1341                            if !left_value.is_support_op(op) {
1342                                let msg = format!("operand not support operator: exp={}, operator={}, operand={:?}", 
1343                                    exp, op.to_str(), left_value);
1344                                error!("{}", msg);
1345                                return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
1346                            }
1347
1348                            // 如果右侧也是中间结果,那么需要检查类型是否相同
1349                            if right.is_eval_token() {
1350                                let right_value = right.into_eval_value();
1351
1352                                // 现在要求类型必须严格匹配
1353                                if !left_value.is_none()
1354                                    && !right_value.is_none()
1355                                    && left_value != right_value
1356                                {
1357                                    let msg = format!("binary operator left type and right type not equal: exp={}, op='{}', left={:?}, right={:?}", 
1358                                        exp, op.to_str(), left_value, right_value);
1359                                    error!("{}", msg);
1360                                    return Err(BuckyError::new(
1361                                        BuckyErrorCode::InvalidFormat,
1362                                        msg,
1363                                    ));
1364                                }
1365                            } else {
1366                                assert!(right.is_const_token());
1367
1368                                // 右侧是常量,那么尝试转换成左侧相同类型并更新表达式
1369                                let right_token = right.into_const_token();
1370                                let right_value = ExpTokenEvalValue::new_from_const_token(
1371                                    &left_value,
1372                                    &right_token,
1373                                )?;
1374
1375                                // 更新rpn序列
1376                                assert!(right_index != usize::MAX);
1377                                result.push((ExpEvalItem::EvalToken(right_value), right_index));
1378                            }
1379
1380                            // 结果直接压入操作数堆栈
1381                            operands.push((mid_result.clone(), usize::MAX));
1382                        }
1383                    }
1384                }
1385                ExpEvalItem::ReservedToken(v) => {
1386                    // 如果是关键字,这里需要求值
1387                    let value = translator.trans(&v);
1388                    operands.push((ExpEvalItem::EvalToken(value), i));
1389                }
1390                ExpEvalItem::ConstToken(v) => {
1391                    if let Some(value) = ExpTokenEvalValue::try_from_single_const_token(&v) {
1392                        trace!("got const token={}, value={:?}", v, value);
1393
1394                        // 独立常量,直接入栈
1395                        result.push((ExpEvalItem::EvalToken(value), i))
1396                    } else {
1397                        // 常量,需要依赖类型推导
1398                        operands.push((item.clone(), i));
1399                    }
1400                }
1401                ExpEvalItem::EvalToken(_) => {
1402                    // 类型推导过程中,不应该出现中间值
1403                    unreachable!();
1404                }
1405            }
1406        }
1407
1408        // 更新const token的计算结果
1409        for (item, i) in result.into_iter() {
1410            assert!(rpn[i].is_const_token());
1411            rpn[i] = item;
1412        }
1413
1414        Ok(rpn)
1415    }
1416
1417    // 进行一次求值运算
1418    pub fn eval(&self, translator: &impl ExpReservedTokenTranslator) -> BuckyResult<bool> {
1419        let mut operands: Vec<ExpTokenEvalValue> = vec![];
1420
1421        for item in self.rpn.iter() {
1422            match item {
1423                ExpEvalItem::Op(op) => match op.arity() {
1424                    ExpOpArity::Unary => {
1425                        assert!(operands.len() >= 1);
1426                        let operand = operands.pop().unwrap();
1427                        assert!(operand.is_support_op(op));
1428
1429                        // 结果直接压入操作数堆栈
1430                        let result = Self::unary_eval(op, operand);
1431                        operands.push(result);
1432                    }
1433                    ExpOpArity::Binary => {
1434                        assert!(operands.len() >= 2);
1435
1436                        // 右操作数在栈顶
1437                        let right = operands.pop().unwrap();
1438                        let left = operands.pop().unwrap();
1439
1440                        assert!(left.is_support_op(op) && right.is_support_op(op));
1441
1442                        let result = Self::binary_eval(op, left, right);
1443
1444                        // 结果直接压入操作数堆栈
1445                        operands.push(result);
1446                    }
1447                },
1448                ExpEvalItem::ReservedToken(v) => {
1449                    // 如果是关键字,这里需要求值
1450                    let value = translator.trans(&v);
1451                    operands.push(value);
1452                }
1453                ExpEvalItem::EvalToken(v) => {
1454                    operands.push(v.clone());
1455                }
1456                /*
1457                ExpEvalItem::ConstToken(v) => {
1458                    if v == "*" {
1459                        operands.push(ExpTokenEvalValue::Bool(true));
1460                    } else {
1461                        let msg = format!("unknown const token! exp={}, {}", self.exp, v);
1462                        error!("{}", msg);
1463                    }
1464                }
1465                */
1466                _ => unreachable!(),
1467            }
1468        }
1469
1470        assert!(operands.len() == 1);
1471        let result = operands.pop().unwrap();
1472        match result {
1473            ExpTokenEvalValue::Bool(v) => Ok(v),
1474            _ => unreachable!(),
1475        }
1476    }
1477
1478    fn unary_eval(op: &ExpOp, operand: ExpTokenEvalValue) -> ExpTokenEvalValue {
1479        let value = match *op {
1480            ExpOp::NOT => match operand {
1481                ExpTokenEvalValue::Bool(v) => ExpTokenEvalValue::Bool(!v),
1482                ExpTokenEvalValue::I8(v) => ExpTokenEvalValue::Bool(v == 0),
1483                ExpTokenEvalValue::I16(v) => ExpTokenEvalValue::Bool(v == 0),
1484                ExpTokenEvalValue::I32(v) => ExpTokenEvalValue::Bool(v == 0),
1485                ExpTokenEvalValue::I64(v) => ExpTokenEvalValue::Bool(v == 0),
1486                ExpTokenEvalValue::U8(v) => ExpTokenEvalValue::Bool(v == 0),
1487                ExpTokenEvalValue::U16(v) => ExpTokenEvalValue::Bool(v == 0),
1488                ExpTokenEvalValue::U32(v) => ExpTokenEvalValue::Bool(v == 0),
1489                ExpTokenEvalValue::U64(v) => ExpTokenEvalValue::Bool(v == 0),
1490                _ => unreachable!(),
1491            },
1492            _ => {
1493                unreachable!();
1494            }
1495        };
1496
1497        value
1498    }
1499
1500    fn binary_eval(
1501        op: &ExpOp,
1502        left_operand: ExpTokenEvalValue,
1503        right_operand: ExpTokenEvalValue,
1504    ) -> ExpTokenEvalValue {
1505        let value = match *op {
1506            ExpOp::EQ => ExpTokenEvalValue::Bool(left_operand == right_operand),
1507            ExpOp::NE => ExpTokenEvalValue::Bool(left_operand != right_operand),
1508            ExpOp::LT => ExpTokenEvalValue::Bool(left_operand < right_operand),
1509            ExpOp::LE => ExpTokenEvalValue::Bool(left_operand <= right_operand),
1510            ExpOp::GT => ExpTokenEvalValue::Bool(left_operand > right_operand),
1511            ExpOp::GE => ExpTokenEvalValue::Bool(left_operand >= right_operand),
1512
1513            ExpOp::AND => {
1514                let left = left_operand.as_bool().unwrap();
1515                let right = right_operand.as_bool().unwrap();
1516                ExpTokenEvalValue::Bool(left && right)
1517            }
1518            ExpOp::OR => {
1519                let left = left_operand.as_bool().unwrap();
1520                let right = right_operand.as_bool().unwrap();
1521                ExpTokenEvalValue::Bool(left || right)
1522            }
1523
1524            ExpOp::BAND => ExpTokenEvalValue::Bool(left_operand.bitand(&right_operand)),
1525            ExpOp::BOR => ExpTokenEvalValue::Bool(left_operand.bitor(&right_operand)),
1526            ExpOp::BXOR => ExpTokenEvalValue::Bool(left_operand.bitxor(&right_operand)),
1527
1528            _ => unreachable!(),
1529        };
1530
1531        /*
1532        trace!(
1533            "binary eval: {:?} {} {:?} = {:?}",
1534            left_operand,
1535            op.to_str(),
1536            right_operand,
1537            value
1538        );
1539        */
1540        value
1541    }
1542}
1543
1544
1545#[cfg(test)]
1546mod exp_tests {
1547    use super::*;
1548
1549    struct TestTranslator {}
1550
1551    impl ExpReservedTokenTranslator for TestTranslator {
1552        fn trans(&self, token: &str) -> ExpTokenEvalValue {
1553            match token {
1554                "a" => ExpTokenEvalValue::I8(10),
1555                "b" => ExpTokenEvalValue::I32(1),
1556                "b1" => ExpTokenEvalValue::I32(1),
1557                "c" => ExpTokenEvalValue::Bool(true),
1558                "d" => ExpTokenEvalValue::I16(100),
1559                "x" => ExpTokenEvalValue::None,
1560                "req_path" => {
1561                    ExpTokenEvalValue::Glob(ExpGlobToken::new_string("/hello/world.js".to_owned()))
1562                }
1563                "req_path2" => {
1564                    ExpTokenEvalValue::Glob(ExpGlobToken::new_string("/test/some/globs".to_owned()))
1565                }
1566                _ => {
1567                    unreachable!("unknown token {}", token);
1568                }
1569            }
1570        }
1571    }
1572
1573    // 使用 cargo test -- --nocapture 运行测试用例
1574    #[test]
1575    fn test() {
1576        cyfs_base::init_simple_log("test-exp-filter", Some("trace"));
1577
1578        let mut token_list = ExpReservedTokenList::new();
1579        token_list.add_string("object-id");
1580        token_list.add_string("source");
1581        token_list.add_string("target");
1582        token_list.add_glob("req_path");
1583        token_list.add_glob("req_path2");
1584
1585        token_list.add_i8("a");
1586        token_list.add_i32("b");
1587        token_list.add_i32("b1");
1588        token_list.add_bool("c");
1589        token_list.add_u32("d");
1590        token_list.add_u32("x");
1591
1592        let translator = TestTranslator {};
1593
1594        // 空字符串
1595        let ret = ExpEvaluator::new(" ", &token_list);
1596        assert!(ret.is_err());
1597
1598        // *
1599        let exp = ExpEvaluator::new("(* )", &token_list).unwrap();
1600        let result = exp.eval(&translator).unwrap();
1601        assert_eq!(result, true);
1602
1603        // glob
1604        let exp = ExpEvaluator::new("req_path == '/**/*.js'", &token_list).unwrap();
1605        let result = exp.eval(&translator).unwrap();
1606        assert_eq!(result, true);
1607
1608        let exp = ExpEvaluator::new("req_path2 == '/**/*.js'", &token_list).unwrap();
1609        let result = exp.eval(&translator).unwrap();
1610        assert_eq!(result, false);
1611
1612        // x=none
1613        let exp = ExpEvaluator::new("(x != $none)", &token_list).unwrap();
1614        let result = exp.eval(&translator).unwrap();
1615        assert_eq!(result, false);
1616
1617        let exp = ExpEvaluator::new("(a != $none)", &token_list).unwrap();
1618        let result = exp.eval(&translator).unwrap();
1619        assert_eq!(result, true);
1620
1621        let exp = ExpEvaluator::new("(x == $none)", &token_list).unwrap();
1622        let result = exp.eval(&translator).unwrap();
1623        assert_eq!(result, true);
1624
1625        // a=10, b=b1=1, c=true, d=100
1626        let exp = ExpEvaluator::new("(a != 0 && (b == 0 || c))", &token_list).unwrap();
1627        let result = exp.eval(&translator).unwrap();
1628        assert_eq!(result, true);
1629
1630        let exp = ExpEvaluator::new("(a != 0 && (b != 1 || !c))", &token_list).unwrap();
1631        let result = exp.eval(&translator).unwrap();
1632        assert_eq!(result, false);
1633
1634        let exp = ExpEvaluator::new(
1635            "(a != 0 && (a!=1) && a == a && (b != b1 || (!c) || d == 1))",
1636            &token_list,
1637        )
1638        .unwrap();
1639        let result = exp.eval(&translator).unwrap();
1640        assert_eq!(result, false);
1641
1642        let exp = ExpEvaluator::new("(a != 0 && (a!=1) && a <= 10) && c", &token_list).unwrap();
1643        let result = exp.eval(&translator).unwrap();
1644        assert_eq!(result, true);
1645
1646        let exp = ExpEvaluator::new("((a < 11)) && a >= 10", &token_list).unwrap();
1647        let result = exp.eval(&translator).unwrap();
1648        assert_eq!(result, true);
1649        let exp = ExpEvaluator::new("a < 11 && a > 10", &token_list).unwrap();
1650        let result = exp.eval(&translator).unwrap();
1651        assert_eq!(result, false);
1652        let exp = ExpEvaluator::new("a >=10 && a == 10 && a <= 10", &token_list).unwrap();
1653        let result = exp.eval(&translator).unwrap();
1654        assert_eq!(result, true);
1655        let exp = ExpEvaluator::new("a < 11 || (a!=10) && a > 10", &token_list).unwrap();
1656        let result = exp.eval(&translator).unwrap();
1657        assert_eq!(result, true);
1658
1659        let exp = ExpEvaluator::new("a >= 11 || (a==10) && a < 10", &token_list).unwrap();
1660        let result = exp.eval(&translator).unwrap();
1661        assert_eq!(result, false);
1662        let exp = ExpEvaluator::new("(a >= 11 || (a==10)) && a <= 10", &token_list).unwrap();
1663        let result = exp.eval(&translator).unwrap();
1664        assert_eq!(result, true);
1665
1666        let exp = ExpEvaluator::new("!c", &token_list).unwrap();
1667        let result = exp.eval(&translator).unwrap();
1668        assert_eq!(result, false);
1669
1670        let exp = ExpEvaluator::new("!!c", &token_list).unwrap();
1671        let result = exp.eval(&translator).unwrap();
1672        assert_eq!(result, true);
1673
1674        let exp = ExpEvaluator::new("!!!c", &token_list).unwrap();
1675        let result = exp.eval(&translator).unwrap();
1676        assert_eq!(result, false);
1677
1678        let exp = ExpEvaluator::new("!!(a == 10)", &token_list).unwrap();
1679        let result = exp.eval(&translator).unwrap();
1680        assert_eq!(result, true);
1681
1682        let exp = ExpEvaluator::new("c && !!c", &token_list).unwrap();
1683        let result = exp.eval(&translator).unwrap();
1684        assert_eq!(result, true);
1685        let exp = ExpEvaluator::new("!(c && !!c)", &token_list).unwrap();
1686        let result = exp.eval(&translator).unwrap();
1687        assert_eq!(result, false);
1688
1689        let exp = ExpEvaluator::new("(a != 0 && (a!=1) && a <10)", &token_list).unwrap();
1690        let result = exp.eval(&translator).unwrap();
1691        assert_eq!(result, false);
1692
1693        let exp = ExpEvaluator::new("a & 0x10", &token_list).unwrap();
1694        let result = exp.eval(&translator).unwrap();
1695        assert_eq!(result, false);
1696        let exp = ExpEvaluator::new("a & 10", &token_list).unwrap();
1697        let result = exp.eval(&translator).unwrap();
1698        assert_eq!(result, true);
1699    }
1700}