Skip to main content

wpl/parser/
parse_code.rs

1use crate::ast::WplExpress;
2use crate::parser::utils::is_sep_next;
3use crate::parser::wpl_group::wpl_group;
4use crate::parser::wpl_rule;
5use crate::types::AnyResult;
6use anyhow::anyhow;
7use winnow::ascii::multispace0;
8use winnow::combinator::{cut_err, delimited, opt};
9use winnow::token::literal;
10use wp_primitives::Parser;
11use wp_primitives::WResult;
12use wp_primitives::symbol::ctx_desc;
13
14use super::wpl_anno::ann_fun;
15//parentheses
16
17pub fn wpl_express(input: &mut &str) -> WResult<WplExpress> {
18    let mut rule = WplExpress::default();
19    if let Some(mut pipe) = opt(wpl_rule::pip_proc).parse_next(input)? {
20        rule.pipe_process.append(&mut pipe);
21    }
22    loop {
23        wpl_group
24            .context(ctx_desc("group"))
25            .map(|x| rule.group.push(x))
26            .parse_next(input)?;
27        if !is_sep_next(input) {
28            break;
29        }
30    }
31    Ok(rule)
32}
33
34pub(crate) fn segment(input: &mut &str) -> WResult<WplExpress> {
35    let tags = opt(ann_fun).parse_next(input)?;
36    let mut define = delimited(
37        (multispace0, literal('{'), multispace0),
38        cut_err(wpl_express),
39        (multispace0, literal('}'), multispace0),
40    )
41    .parse_next(input)?;
42    define.tags = tags;
43    Ok(define)
44}
45
46pub fn source_segment(code: &str) -> AnyResult<WplExpress> {
47    segment
48        .parse(code)
49        .map_err(|e| anyhow!("parse source_prefix error: {:?}", e))
50}
51
52/*
53fn wpl_codes(input: &mut &str) -> ModalResult<Vec<WPLPackage>> {
54    let multi_package = opt(repeat(1.., wpl_package)).parse_next(input)?;
55    if let Some(packages) = multi_package {
56        return Ok(packages);
57    }
58    let mut default_package = WPLPackage::new("/", vec![]);
59    wpl_pkg_body(&mut default_package).parse_next(input)?;
60    Ok(vec![default_package])
61}
62
63 */
64
65#[cfg(test)]
66mod tests {
67    use smol_str::SmolStr;
68    use winnow::LocatingSlice;
69
70    use super::*;
71    use crate::ast::fld_fmt::WplFieldFmt;
72    use crate::ast::{WplField, WplPackage};
73    use crate::parser::error::WplCodeError;
74    use crate::parser::wpl_pkg::{wpl_package, wpl_pkg_body};
75    use crate::parser::wpl_rule::pip_proc;
76    use crate::types::AnyResult;
77    use orion_error::{ErrorOwe, TestAssert};
78    use wp_model_core::model::DataType;
79
80    #[test]
81    fn test_package() -> Result<(), WplCodeError> {
82        let input = r#"    package test {
83                rule test { (digit<<,>>,digit,time_3339:recv_time,5*_) }
84        }
85    "#;
86
87        assert_eq!(
88            wpl_package
89                .parse(&LocatingSlice::new(input))
90                .owe_conf()?
91                .to_string(),
92            r#"package test {
93  rule test {
94    (
95      digit<<,>>,
96      digit,
97      time_3339:recv_time,
98      5*_
99    )
100  }
101}
102"#
103        );
104
105        let data = r#"
106    package test {
107            rule /service/for_test/wplab_1 {
108                (digit<<,>>,digit,time_3339:recv_time,5*_),
109                (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")
110            }
111    }
112        "#;
113
114        assert_eq!(
115            wpl_package.parse(data).assert().to_string(),
116            r#"package test {
117  rule /service/for_test/wplab_1 {
118    (
119      digit<<,>>,
120      digit,
121      time_3339:recv_time,
122      5*_
123    ),
124    (
125      digit:id,
126      digit:len,
127      time,
128      sn,
129      chars:dev_name,
130      time,
131      kv,
132      sn,
133      chars:dev_name,
134      time,
135      time,
136      ip,
137      kv,
138      chars,
139      kv,
140      kv,
141      chars,
142      kv,
143      kv,
144      chars,
145      chars,
146      ip,
147      chars,
148      http/request<[,]>,
149      http/agent"
150    )
151  }
152}
153"#
154        );
155
156        let data = r#"
157    package test {
158            rule /service/for_test/wplab_1 {
159                (time_3339:recv_time,5*_)\!\|
160            }
161            rule /service/for_test/wplab_2 {
162                (time_3339:recv_time,5*_)
163            }
164    }
165        "#;
166
167        let result = wpl_package.parse(data).assert();
168        assert_eq!(
169            result.to_string(),
170            r#"package test {
171  rule /service/for_test/wplab_1 {
172    (
173      time_3339:recv_time,
174      5*_
175    )\!\|
176  }
177  rule /service/for_test/wplab_2 {
178    (
179      time_3339:recv_time,
180      5*_
181    )
182  }
183}
184"#
185        );
186        Ok(())
187    }
188    #[test]
189    fn test_parse_block2() {
190        let data = r#"(kv(digit@message_type),kv(chars@serial_num))\!\|"#;
191        let result = wpl_express.parse(data).assert();
192        assert_eq!(
193            result.to_string(),
194            r#"  (
195    kv(digit@message_type),
196    kv(@serial_num)
197  )\!\|"#,
198        );
199    }
200
201    #[test]
202    fn test_parse_block() {
203        let data = "(kv(digit@message_type),chars<skyeye_abnormal {,|>,kv(chars@serial_num),kv(time@access_time),kv(@type),kv(ip@sip),kv(digit@sport),kv(ip@dip),kv(digit@dport),kv(chars@data),kv(digit@datalen),kv(chars@info),kv(chars@vendor_id),kv(ip@device_ip),chars<},|>)";
204        assert_eq!(
205            wpl_express.parse(data).assert().to_string(),
206            r#"  (
207    kv(digit@message_type),
208    chars<skyeye_abnormal {,|>,
209    kv(@serial_num),
210    kv(time@access_time),
211    kv(@type),
212    kv(ip@sip),
213    kv(digit@sport),
214    kv(ip@dip),
215    kv(digit@dport),
216    kv(@data),
217    kv(digit@datalen),
218    kv(@info),
219    kv(@vendor_id),
220    kv(ip@device_ip),
221    chars<},|>
222  )"#,
223        );
224
225        let data = r#"(json(_@_origin,_@payload/packet_data))"#;
226        assert_eq!(
227            wpl_express.parse(data).assert().to_string(),
228            "  (
229    json(_@_origin,_@payload/packet_data,)
230  )"
231        );
232    }
233
234    #[test]
235    fn test_pip_proc() {
236        assert_eq!(
237            pip_proc.parse_peek("|decode/base64|"),
238            Ok(("", vec![SmolStr::from("decode/base64")]))
239        );
240
241        assert_eq!(
242            pip_proc.parse_peek("|decode/hex|"),
243            Ok(("", vec![SmolStr::from("decode/hex")]))
244        );
245
246        assert_eq!(
247            pip_proc.parse_peek("|unquote/unescape|"),
248            Ok(("", vec![SmolStr::from("unquote/unescape")]))
249        );
250        assert_eq!(
251            pip_proc.parse_peek("|decode/base64|zip|"),
252            Ok((
253                "",
254                vec![SmolStr::from("decode/base64"), SmolStr::from("zip")]
255            ))
256        );
257        assert_eq!(
258            pip_proc.parse_peek("|decode/base64|zip |"),
259            Ok((
260                "",
261                vec![SmolStr::from("decode/base64"), SmolStr::from("zip")]
262            ))
263        );
264        assert_eq!(
265            pip_proc.parse_peek("|   base64  |zip |"),
266            Ok(("", vec![SmolStr::from("base64"), SmolStr::from("zip")]))
267        );
268        assert_eq!(
269            pip_proc.parse_peek("|   base      |"),
270            Ok(("", vec![SmolStr::from("base")]))
271        );
272        assert_eq!(
273            pip_proc
274                .parse(&LocatingSlice::new("| !!!|"))
275                .err()
276                .unwrap()
277                .offset(),
278            2
279        );
280        assert_eq!(
281            pip_proc
282                .parse(&LocatingSlice::new("|"))
283                .err()
284                .unwrap()
285                .offset(),
286            1
287        );
288        assert_eq!(
289            pip_proc
290                .parse(&LocatingSlice::new("|2222 |34333| 444   "))
291                .err()
292                .unwrap()
293                .offset(),
294            20
295        );
296    }
297
298    #[test]
299    fn test_conf_map() -> AnyResult<()> {
300        let data = r#"(json(base64@a:x,@b:y))"#;
301        let conf = wpl_express.parse(data).assert();
302        let map = conf.group[0].fields[0].sub_fields.as_ref().unwrap();
303        let expect = WplField {
304            name: Some("x".into()),
305            meta_name: "base64".into(),
306            meta_type: DataType::Base64,
307            desc: "base64:x".to_string(),
308            fmt_conf: WplFieldFmt {
309                //separator: PrioSep::infer_low("0"),
310                //patten_first: Some(true),
311                ..Default::default()
312            },
313            ..Default::default()
314        };
315        assert_eq!(map.get("a"), Some(&expect));
316        Ok(())
317    }
318
319    #[test]
320    fn test_conf_vec() {
321        let data = "(ip,ip)";
322        wpl_group.parse(data).assert();
323        wpl_group.parse("(http/method,ip)").assert();
324        wpl_group.parse("(*ip,ip:src)").assert();
325
326        let group = wpl_group.parse("(*ip,ip:src)[100]\\,").assert();
327        group
328            .fields
329            .iter()
330            .for_each(|x| assert_eq!(x.separator, None));
331        assert!(group.base_group_sep.is_some());
332
333        let data = "(chars<-[,]*>)";
334        let group = wpl_group.parse(data).assert();
335        assert_eq!(group.fields[0].fmt_conf.scope_beg, Some("-[".to_string()));
336        assert_eq!(group.fields[0].fmt_conf.scope_end, Some("]*".to_string()));
337
338        wpl_group.parse("(chars<http://,/>)").assert();
339        wpl_group.parse("(chars<http://,/>)").assert();
340        wpl_group.parse("\n(\nip,\nip\n)").assert();
341    }
342
343    #[test]
344    fn test_rules() -> AnyResult<()> {
345        let data = r#" rule wparse_1 { |decode/base64|zip|unquote/unescape|(digit,time) }"#;
346        wpl_pkg_body(&mut WplPackage::default())
347            .parse(data)
348            .assert();
349
350        let data = r#"
351         rule wparse_1 { |base64|zip|(digit,time) }
352
353        rule wparse_2 { |base64|zip|(digit,time) } "#;
354        let mut package = WplPackage::default();
355        wpl_pkg_body(&mut package).parse(data).assert();
356        assert_eq!(package.rules.len(), 2);
357        Ok(())
358    }
359
360    /*
361        #[test]
362        fn test_muti_package() {
363            let data = r#"
364    package test {
365            rule /service/for_test/wplab_1 {
366                (digit<<,>>,digit,time_3339:recv_time2,5*_),
367                (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")\,
368            }
369    }
370
371    package test1 {
372            rule /service/for_test/wplab_1 {
373                (digit<<,>>,digit,time_3339:recv_time2,5*_),
374                (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")\,
375            }
376    }
377        "#;
378
379            let packages = wpl_codes.parse(data).assert();
380            assert_eq!(packages.len(), 2);
381        }
382    */
383    #[test]
384    fn test_package_annotation1() {
385        let data = r#"
386#[tag(t1:"id",t2:"sn"),copy_raw(hello:"ll")]
387package test {
388        rule /service/for_test/wplab_1 {
389            (digit<<,>>,digit,time_3339:recv_time2,5*_),
390            (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")\,
391        }
392}
393    "#;
394
395        let expect = r#"#[tag(t1:"id", t2:"sn"), copy_raw(hello:"ll")]
396package test {
397  #[tag(t1:"id", t2:"sn"), copy_raw(hello:"ll")]
398  rule /service/for_test/wplab_1 {
399    (
400      digit<<,>>,
401      digit,
402      time_3339:recv_time2,
403      5*_
404    ),
405    (
406      digit:id,
407      digit:len,
408      time,
409      sn,
410      chars:dev_name,
411      time,
412      kv,
413      sn,
414      chars:dev_name,
415      time,
416      time,
417      ip,
418      kv,
419      chars,
420      kv,
421      kv,
422      chars,
423      kv,
424      kv,
425      chars,
426      chars,
427      ip,
428      chars,
429      http/request<[,]>,
430      http/agent"
431    )\,
432  }
433}
434"#;
435
436        let packages = wpl_package.parse(data).assert();
437        assert_eq!(packages.to_string(), expect);
438    }
439
440    #[test]
441    fn test_annotation2() {
442        let data = r#"
443#[tag(t1:"id",t2:"sn"),copy_raw(name:"ok")]
444package test {
445        #[tag(t1:"id",t3:"sn2"),copy_raw(name:"yes")]
446        rule /service/for_test/wplab_1 {
447            (digit<<,>>,digit,time_3339:recv_time2,5*_),
448            (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")\,
449        }
450}
451    "#;
452
453        let expect = r#"#[tag(t1:"id", t2:"sn"), copy_raw(name:"ok")]
454package test {
455  #[tag(t1:"id", t2:"sn", t3:"sn2"), copy_raw(name:"yes")]
456  rule /service/for_test/wplab_1 {
457    (
458      digit<<,>>,
459      digit,
460      time_3339:recv_time2,
461      5*_
462    ),
463    (
464      digit:id,
465      digit:len,
466      time,
467      sn,
468      chars:dev_name,
469      time,
470      kv,
471      sn,
472      chars:dev_name,
473      time,
474      time,
475      ip,
476      kv,
477      chars,
478      kv,
479      kv,
480      chars,
481      kv,
482      kv,
483      chars,
484      chars,
485      ip,
486      chars,
487      http/request<[,]>,
488      http/agent"
489    )\,
490  }
491}
492"#;
493
494        let packages = wpl_package.parse(data).assert();
495        assert_eq!(packages.to_string(), expect);
496    }
497
498    #[test]
499    fn test_annotation3() {
500        let data = r#"
501#[tag(t1:"id")]
502package test {
503        #[tag(t1:"hello",t3:"sn2"),copy_raw(hello:"ll")]
504        rule /service/for_test/wplab_1 {
505            (digit<<,>>,digit,time_3339:recv_time2,5*_),
506            (digit:id,digit:len,time,sn,chars:dev_name,time,kv,sn,chars:dev_name,time,time,ip,kv,chars,kv,kv,chars,kv,kv,chars,chars,ip,chars,http/request<[,]>,http/agent")\,
507        }
508}
509    "#;
510
511        let expect = r#"#[tag(t1:"id")]
512package test {
513  #[tag(t1:"hello", t3:"sn2"), copy_raw(hello:"ll")]
514  rule /service/for_test/wplab_1 {
515    (
516      digit<<,>>,
517      digit,
518      time_3339:recv_time2,
519      5*_
520    ),
521    (
522      digit:id,
523      digit:len,
524      time,
525      sn,
526      chars:dev_name,
527      time,
528      kv,
529      sn,
530      chars:dev_name,
531      time,
532      time,
533      ip,
534      kv,
535      chars,
536      kv,
537      kv,
538      chars,
539      kv,
540      kv,
541      chars,
542      chars,
543      ip,
544      chars,
545      http/request<[,]>,
546      http/agent"
547    )\,
548  }
549}
550"#;
551
552        let packages = wpl_package.parse(data).assert();
553        assert_eq!(packages.to_string(), expect);
554    }
555}