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::dev::testing::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                .map_err(|e| {
91                    WplCodeError::builder(WplCodeReason::core_conf())
92                        .detail(e.to_string())
93                        .finish()
94                })?
95                .to_string(),
96            r#"package test {
97  rule test {
98    (
99      digit<<,>>,
100      digit,
101      time_3339:recv_time,
102      5*_
103    )
104  }
105}
106"#
107        );
108
109        let data = r#"
110    package test {
111            rule /service/for_test/wplab_1 {
112                (digit<<,>>,digit,time_3339:recv_time,5*_),
113                (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")
114            }
115    }
116        "#;
117
118        assert_eq!(
119            wpl_package.parse(data).assert().to_string(),
120            r#"package test {
121  rule /service/for_test/wplab_1 {
122    (
123      digit<<,>>,
124      digit,
125      time_3339:recv_time,
126      5*_
127    ),
128    (
129      digit:id,
130      digit:len,
131      time,
132      sn,
133      chars:dev_name,
134      time,
135      kv,
136      sn,
137      chars:dev_name,
138      time,
139      time,
140      ip,
141      kv,
142      chars,
143      kv,
144      kv,
145      chars,
146      kv,
147      kv,
148      chars,
149      chars,
150      ip,
151      chars,
152      http/request<[,]>,
153      http/agent"
154    )
155  }
156}
157"#
158        );
159
160        let data = r#"
161    package test {
162            rule /service/for_test/wplab_1 {
163                (time_3339:recv_time,5*_)\!\|
164            }
165            rule /service/for_test/wplab_2 {
166                (time_3339:recv_time,5*_)
167            }
168    }
169        "#;
170
171        let result = wpl_package.parse(data).assert();
172        assert_eq!(
173            result.to_string(),
174            r#"package test {
175  rule /service/for_test/wplab_1 {
176    (
177      time_3339:recv_time,
178      5*_
179    )\!\|
180  }
181  rule /service/for_test/wplab_2 {
182    (
183      time_3339:recv_time,
184      5*_
185    )
186  }
187}
188"#
189        );
190        Ok(())
191    }
192    #[test]
193    fn test_parse_block2() {
194        let data = r#"(kv(digit@message_type),kv(chars@serial_num))\!\|"#;
195        let result = wpl_express.parse(data).assert();
196        assert_eq!(
197            result.to_string(),
198            r#"  (
199    kv(digit@message_type),
200    kv(@serial_num)
201  )\!\|"#,
202        );
203    }
204
205    #[test]
206    fn test_parse_block() {
207        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<},|>)";
208        assert_eq!(
209            wpl_express.parse(data).assert().to_string(),
210            r#"  (
211    kv(digit@message_type),
212    chars<skyeye_abnormal {,|>,
213    kv(@serial_num),
214    kv(time@access_time),
215    kv(@type),
216    kv(ip@sip),
217    kv(digit@sport),
218    kv(ip@dip),
219    kv(digit@dport),
220    kv(@data),
221    kv(digit@datalen),
222    kv(@info),
223    kv(@vendor_id),
224    kv(ip@device_ip),
225    chars<},|>
226  )"#,
227        );
228
229        let data = r#"(json(_@_origin,_@payload/packet_data))"#;
230        assert_eq!(
231            wpl_express.parse(data).assert().to_string(),
232            "  (
233    json(_@_origin,_@payload/packet_data,)
234  )"
235        );
236    }
237
238    #[test]
239    fn test_pip_proc() {
240        assert_eq!(
241            pip_proc.parse_peek("|decode/base64|"),
242            Ok(("", vec![SmolStr::from("decode/base64")]))
243        );
244
245        assert_eq!(
246            pip_proc.parse_peek("|decode/hex|"),
247            Ok(("", vec![SmolStr::from("decode/hex")]))
248        );
249
250        assert_eq!(
251            pip_proc.parse_peek("|unquote/unescape|"),
252            Ok(("", vec![SmolStr::from("unquote/unescape")]))
253        );
254        assert_eq!(
255            pip_proc.parse_peek("|decode/base64|zip|"),
256            Ok((
257                "",
258                vec![SmolStr::from("decode/base64"), SmolStr::from("zip")]
259            ))
260        );
261        assert_eq!(
262            pip_proc.parse_peek("|decode/base64|zip |"),
263            Ok((
264                "",
265                vec![SmolStr::from("decode/base64"), SmolStr::from("zip")]
266            ))
267        );
268        assert_eq!(
269            pip_proc.parse_peek("|   base64  |zip |"),
270            Ok(("", vec![SmolStr::from("base64"), SmolStr::from("zip")]))
271        );
272        assert_eq!(
273            pip_proc.parse_peek("|   base      |"),
274            Ok(("", vec![SmolStr::from("base")]))
275        );
276        assert_eq!(
277            pip_proc
278                .parse(&LocatingSlice::new("| !!!|"))
279                .err()
280                .unwrap()
281                .offset(),
282            2
283        );
284        assert_eq!(
285            pip_proc
286                .parse(&LocatingSlice::new("|"))
287                .err()
288                .unwrap()
289                .offset(),
290            1
291        );
292        assert_eq!(
293            pip_proc
294                .parse(&LocatingSlice::new("|2222 |34333| 444   "))
295                .err()
296                .unwrap()
297                .offset(),
298            20
299        );
300    }
301
302    #[test]
303    fn test_conf_map() -> WplCodeResult<()> {
304        let data = r#"(json(base64@a:x,@b:y))"#;
305        let conf = wpl_express.parse(data).assert();
306        let map = conf.group[0].fields[0].sub_fields.as_ref().unwrap();
307        let expect = WplField {
308            name: Some("x".into()),
309            meta_name: "base64".into(),
310            meta_type: DataType::Base64,
311            desc: "base64:x".to_string(),
312            fmt_conf: WplFieldFmt {
313                //separator: PrioSep::infer_low("0"),
314                //patten_first: Some(true),
315                ..Default::default()
316            },
317            ..Default::default()
318        };
319        assert_eq!(map.get("a"), Some(&expect));
320        Ok(())
321    }
322
323    #[test]
324    fn test_conf_vec() {
325        let data = "(ip,ip)";
326        wpl_group.parse(data).assert();
327        wpl_group.parse("(http/method,ip)").assert();
328        wpl_group.parse("(*ip,ip:src)").assert();
329
330        let group = wpl_group.parse("(*ip,ip:src)[100]\\,").assert();
331        group
332            .fields
333            .iter()
334            .for_each(|x| assert_eq!(x.separator, None));
335        assert!(group.base_group_sep.is_some());
336
337        let data = "(chars<-[,]*>)";
338        let group = wpl_group.parse(data).assert();
339        assert_eq!(group.fields[0].fmt_conf.scope_beg, Some("-[".to_string()));
340        assert_eq!(group.fields[0].fmt_conf.scope_end, Some("]*".to_string()));
341
342        wpl_group.parse("(chars<http://,/>)").assert();
343        wpl_group.parse("(chars<http://,/>)").assert();
344        wpl_group.parse("\n(\nip,\nip\n)").assert();
345    }
346
347    #[test]
348    fn test_rules() -> WplCodeResult<()> {
349        let data = r#" rule wparse_1 { |decode/base64|zip|unquote/unescape|(digit,time) }"#;
350        wpl_pkg_body(&mut WplPackage::default())
351            .parse(data)
352            .assert();
353
354        let data = r#"
355         rule wparse_1 { |base64|zip|(digit,time) }
356
357        rule wparse_2 { |base64|zip|(digit,time) } "#;
358        let mut package = WplPackage::default();
359        wpl_pkg_body(&mut package).parse(data).assert();
360        assert_eq!(package.rules.len(), 2);
361        Ok(())
362    }
363
364    /*
365        #[test]
366        fn test_muti_package() {
367            let data = r#"
368    package test {
369            rule /service/for_test/wplab_1 {
370                (digit<<,>>,digit,time_3339:recv_time2,5*_),
371                (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")\,
372            }
373    }
374
375    package test1 {
376            rule /service/for_test/wplab_1 {
377                (digit<<,>>,digit,time_3339:recv_time2,5*_),
378                (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")\,
379            }
380    }
381        "#;
382
383            let packages = wpl_codes.parse(data).assert();
384            assert_eq!(packages.len(), 2);
385        }
386    */
387    #[test]
388    fn test_package_annotation1() {
389        let data = r#"
390#[tag(t1:"id",t2:"sn"),copy_raw(hello:"ll")]
391package test {
392        rule /service/for_test/wplab_1 {
393            (digit<<,>>,digit,time_3339:recv_time2,5*_),
394            (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")\,
395        }
396}
397    "#;
398
399        let expect = r#"#[tag(t1:"id", t2:"sn"), copy_raw(hello:"ll")]
400package test {
401  #[tag(t1:"id", t2:"sn"), copy_raw(hello:"ll")]
402  rule /service/for_test/wplab_1 {
403    (
404      digit<<,>>,
405      digit,
406      time_3339:recv_time2,
407      5*_
408    ),
409    (
410      digit:id,
411      digit:len,
412      time,
413      sn,
414      chars:dev_name,
415      time,
416      kv,
417      sn,
418      chars:dev_name,
419      time,
420      time,
421      ip,
422      kv,
423      chars,
424      kv,
425      kv,
426      chars,
427      kv,
428      kv,
429      chars,
430      chars,
431      ip,
432      chars,
433      http/request<[,]>,
434      http/agent"
435    )\,
436  }
437}
438"#;
439
440        let packages = wpl_package.parse(data).assert();
441        assert_eq!(packages.to_string(), expect);
442    }
443
444    #[test]
445    fn test_annotation2() {
446        let data = r#"
447#[tag(t1:"id",t2:"sn"),copy_raw(name:"ok")]
448package test {
449        #[tag(t1:"id",t3:"sn2"),copy_raw(name:"yes")]
450        rule /service/for_test/wplab_1 {
451            (digit<<,>>,digit,time_3339:recv_time2,5*_),
452            (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")\,
453        }
454}
455    "#;
456
457        let expect = r#"#[tag(t1:"id", t2:"sn"), copy_raw(name:"ok")]
458package test {
459  #[tag(t1:"id", t2:"sn", t3:"sn2"), copy_raw(name:"yes")]
460  rule /service/for_test/wplab_1 {
461    (
462      digit<<,>>,
463      digit,
464      time_3339:recv_time2,
465      5*_
466    ),
467    (
468      digit:id,
469      digit:len,
470      time,
471      sn,
472      chars:dev_name,
473      time,
474      kv,
475      sn,
476      chars:dev_name,
477      time,
478      time,
479      ip,
480      kv,
481      chars,
482      kv,
483      kv,
484      chars,
485      kv,
486      kv,
487      chars,
488      chars,
489      ip,
490      chars,
491      http/request<[,]>,
492      http/agent"
493    )\,
494  }
495}
496"#;
497
498        let packages = wpl_package.parse(data).assert();
499        assert_eq!(packages.to_string(), expect);
500    }
501
502    #[test]
503    fn test_annotation3() {
504        let data = r#"
505#[tag(t1:"id")]
506package test {
507        #[tag(t1:"hello",t3:"sn2"),copy_raw(hello:"ll")]
508        rule /service/for_test/wplab_1 {
509            (digit<<,>>,digit,time_3339:recv_time2,5*_),
510            (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")\,
511        }
512}
513    "#;
514
515        let expect = r#"#[tag(t1:"id")]
516package test {
517  #[tag(t1:"hello", t3:"sn2"), copy_raw(hello:"ll")]
518  rule /service/for_test/wplab_1 {
519    (
520      digit<<,>>,
521      digit,
522      time_3339:recv_time2,
523      5*_
524    ),
525    (
526      digit:id,
527      digit:len,
528      time,
529      sn,
530      chars:dev_name,
531      time,
532      kv,
533      sn,
534      chars:dev_name,
535      time,
536      time,
537      ip,
538      kv,
539      chars,
540      kv,
541      kv,
542      chars,
543      kv,
544      kv,
545      chars,
546      chars,
547      ip,
548      chars,
549      http/request<[,]>,
550      http/agent"
551    )\,
552  }
553}
554"#;
555
556        let packages = wpl_package.parse(data).assert();
557        assert_eq!(packages.to_string(), expect);
558    }
559}