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;
15pub 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#[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 ..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 #[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}