Skip to main content

wpl/parser/
parse_code.rs

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