1use crate::ast::WplPipe;
2use crate::ast::group::{WplGroup, WplGroupType};
3use crate::ast::{WplExpress, WplStatementType};
4use crate::ast::{WplField, WplSep};
5use crate::compat::New3;
6use crate::eval::builtins::{self, PipeLineResult, raw_to_utf8_string};
7use crate::eval::runtime::field::FieldEvalUnit;
8use crate::eval::runtime::field_pipe::PipeEnum;
9use crate::eval::runtime::group::WplEvalGroup;
10use std::borrow::Cow;
11use wp_model_core::raw::RawData;
12use wp_parse_api::{PipeHold, WparseError, WparseReason};
13
14use crate::parser::error::{WplCodeError, WplCodeReason};
15use crate::parser::wpl_rule::wpl_rule;
16use anyhow::Result;
17use orion_error::{ErrorWith, ToStructError, UvsFrom};
18use wp_log::debug_edata;
19use wp_model_core::model::DataRecord;
20use wp_primitives::Parser;
21use wp_primitives::WResult as ModalResult;
22
23pub type DataResult = Result<(DataRecord, String), WparseError>;
26pub const OPTIMIZE_TIMES: usize = 10000;
27
28pub trait IntoRawData {
29 fn into_raw(self) -> RawData;
30}
31
32impl IntoRawData for RawData {
33 fn into_raw(self) -> RawData {
34 self
35 }
36}
37
38impl IntoRawData for String {
39 fn into_raw(self) -> RawData {
40 RawData::from_string(self)
41 }
42}
43
44impl IntoRawData for &String {
45 fn into_raw(self) -> RawData {
46 RawData::from_string(self.as_str())
47 }
48}
49
50impl IntoRawData for &str {
51 fn into_raw(self) -> RawData {
52 RawData::from_string(self)
53 }
54}
55
56#[derive(Default, Clone)]
57pub struct WplEvaluator {
58 preorder: Vec<PipeHold>,
59 group_units: Vec<WplEvalGroup>,
60}
61unsafe impl Send for WplEvaluator {}
62
63impl WplEvaluator {
64 pub fn preorder_proc(&self, data: RawData) -> Result<Vec<PipeLineResult>, WparseError> {
65 let mut pipe_obj = Vec::new();
66 let mut target = data;
67 for proc_unit in &self.preorder {
68 target = proc_unit.process(target)?;
69 pipe_obj.push(PipeLineResult {
70 name: proc_unit.name().to_string(),
71 result: raw_to_utf8_string(&target),
72 });
73 }
74 Ok(pipe_obj)
75 }
76
77 fn pipe_proc(&self, e_id: u64, data: RawData) -> Result<RawData, WparseError> {
78 let mut target = data;
79 for proc_unit in &self.preorder {
80 target = proc_unit
81 .process(target)
82 .want("pipe convert")
83 .with(e_id.to_string())
84 .with(proc_unit.name())?;
85
86 debug_edata!(
87 e_id,
88 "pipe {} out:{}",
89 proc_unit.name(),
90 raw_to_utf8_string(&target)
91 );
92 }
93 Ok(target)
94 }
95
96 pub fn proc<D>(&self, e_id: u64, data: D, oth_suc_len: usize) -> DataResult
97 where
98 D: IntoRawData,
99 {
100 let mut working_raw: RawData = data.into_raw();
101 if !self.preorder.is_empty() {
102 working_raw = self.pipe_proc(e_id, working_raw)?;
103 }
104
105 let input_holder: Cow<'_, str> = match &working_raw {
106 RawData::String(s) => Cow::Borrowed(s.as_str()),
107 RawData::Bytes(b) => Cow::Owned(String::from_utf8_lossy(b).into_owned()),
108 RawData::ArcBytes(b) => Cow::Owned(String::from_utf8_lossy(b).into_owned()),
109 };
110 let mut input: &str = input_holder.as_ref();
111
112 let ori_len = input.len();
113 match self.parse_groups(e_id, &mut input) {
114 Ok(log) => Ok((log, input.to_string())),
115 Err(e) => {
116 let cur_pos = input.len();
117 let pos = ori_len - cur_pos;
118 if pos >= oth_suc_len {
119 Err(WparseReason::from_data()
120 .to_err()
121 .with_detail(format!("{input} @ {pos}"))
122 .with_detail(e.to_string()))
123 } else {
124 Err(WparseError::from(WparseReason::NotMatch))
125 }
126 }
127 }
128 }
129 pub fn from_code(code: &str) -> Result<Self, WplCodeError> {
130 let mut cur_code = code;
131 let rule = wpl_rule.parse_next(&mut cur_code).map_err(
132 |err| {
133 WplCodeReason::from_data()
134 .to_err()
135 .with_detail(cur_code.to_string())
136 .with_detail(err.to_string())
137 }, )?;
139 let WplStatementType::Express(rule_define) = rule.statement;
140 Self::from(&rule_define, None)
141 }
142 pub fn from(dy_lang: &WplExpress, inject: Option<&WplExpress>) -> Result<Self, WplCodeError> {
143 let mut target_dpl = WplEvaluator {
144 ..Default::default()
145 };
146 if let Some(inject) = inject {
147 Self::assemble_ins(inject, &mut target_dpl)?;
148 }
149 Self::assemble_ins(dy_lang, &mut target_dpl)?;
150 Ok(target_dpl)
151 }
152
153 fn assemble_ins(
154 express: &WplExpress,
155 target_dpl: &mut WplEvaluator,
156 ) -> Result<(), WplCodeError> {
157 builtins::ensure_builtin_pipe_units();
158 for proc in &express.pipe_process {
159 if let Some(pipe_unit) = builtins::registry::create_pipe_unit(proc) {
160 target_dpl.preorder.push(pipe_unit);
161 } else {
162 return Err(WplCodeError::from(WplCodeReason::UnSupport(format!(
163 "Pipe processor '{}' not registered",
164 proc
165 ))));
166 }
167 }
168 for (i, group) in express.group.iter().enumerate() {
169 let p_group = Self::assemble_group(i + 1, group)?;
170 target_dpl.group_units.push(p_group);
171 }
172 Ok(())
173 }
174 fn assemble_group(index: usize, group: &WplGroup) -> Result<WplEvalGroup, WplCodeError> {
175 let mut p_group =
176 WplEvalGroup::new(index, group.meta.clone(), group.base_group_sep.clone());
177 for (idx, conf) in group.fields.iter().enumerate() {
178 let fpu = Self::assemble_fpu(idx + 1, conf, group.meta.clone())?;
179 p_group.field_units.push(fpu)
180 }
181 Ok(p_group)
182 }
183 fn assemble_pipe(parent_idx: usize, pipe: &WplPipe) -> Result<PipeEnum, WplCodeError> {
184 match pipe {
185 WplPipe::Fun(fun) => Ok(PipeEnum::Fun(fun.clone())),
186 WplPipe::Group(group) => {
187 let mut p_group = WplEvalGroup::new(
188 parent_idx * 10,
189 group.meta.clone(),
190 group.base_group_sep.clone(),
191 );
192 for conf in &group.fields {
193 let fpu = Self::assemble_fpu(0, conf, group.meta.clone())?;
194 p_group.field_units.push(fpu)
195 }
196 Ok(PipeEnum::Group(p_group))
197 }
198 }
199 }
200
201 pub fn assemble_fpu(
202 idx: usize,
203 conf: &WplField,
204 grp: WplGroupType,
205 ) -> Result<FieldEvalUnit, WplCodeError> {
206 let mut fpu = Self::build_fpu(idx, &grp, conf)?;
207 if let Some(subs) = conf.sub_fields() {
208 for (k, conf) in subs.conf_items().exact_iter() {
209 let sub_fpu = Self::build_fpu(0, &grp, conf)?;
210 fpu.add_sub_fpu(k.clone(), sub_fpu);
211 }
212 for (k, _, conf) in subs.conf_items().wild_iter() {
213 let sub_fpu = Self::build_fpu(0, &grp, conf)?;
214 fpu.add_sub_fpu(k.clone(), sub_fpu);
215 }
216 }
217 Ok(fpu)
218 }
219
220 fn build_fpu(
221 idx: usize,
222 grp: &WplGroupType,
223 conf: &WplField,
224 ) -> Result<FieldEvalUnit, WplCodeError> {
225 let mut fpu = FieldEvalUnit::create(idx, conf.clone(), grp.clone())?;
226 for pipe_conf in conf.pipe.clone() {
227 let pipe = Self::assemble_pipe(idx, &pipe_conf)?;
228 fpu.add_pipe(pipe);
229 }
230 Ok(fpu)
231 }
232 pub fn parse_groups(&self, e_id: u64, data: &mut &str) -> ModalResult<DataRecord> {
234 let mut result = Vec::with_capacity(100);
235
236 let sep = WplSep::default();
237 for group_unit in self.group_units.iter() {
238 match group_unit.proc(e_id, &sep, data, &mut result) {
239 Ok(_) => {}
240 Err(e) => {
241 return Err(e);
242 }
243 }
244 }
245 let storage_items: Vec<_> = result
246 .into_iter()
247 .map(wp_model_core::model::FieldStorage::from_owned)
248 .collect();
249 Ok(DataRecord::from(storage_items))
250 }
251}
252
253pub struct StopWatch {
254 continuous: bool,
255 run_cnt: Option<usize>,
256}
257
258impl StopWatch {
259 pub fn tag_used(&mut self) {
260 if self.continuous
261 && let Some(cnt) = &mut self.run_cnt
262 {
263 *cnt -= 1;
264 }
265 }
266 pub fn is_stop(&self) -> bool {
267 if !self.continuous {
268 true
269 } else {
270 self.run_cnt == Some(0)
271 }
272 }
273 pub fn allow_try(&self) -> bool {
274 self.continuous && self.run_cnt.is_none()
275 }
276 pub fn new(continuous: bool, run_cnt: Option<usize>) -> Self {
277 Self {
278 continuous,
279 run_cnt,
280 }
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use crate::ast::fld_fmt::for_test::{fdc2, fdc2_1, fdc3, fdc4_1};
287 use crate::ast::{WplField, WplFieldFmt};
288 use crate::compat::New1;
289 use crate::eval::builtins::raw_to_utf8_string;
290 use crate::eval::runtime::vm_unit::WplEvaluator;
291 use crate::eval::value::parse_def::Hold;
292 use crate::types::AnyResult;
293 use crate::{WparseResult, WplExpress, register_wpl_pipe};
294 use orion_error::TestAssert;
295 use smol_str::SmolStr;
296 use wp_model_core::raw::RawData;
297 use wp_parse_api::PipeProcessor;
298
299 #[test]
300 fn log_test_ty() -> AnyResult<()> {
301 let mut data = r#"<158> May 15 14:19:16 skyeye SyslogClient[1]: 2023-05-15 14:19:16|10.180.8.8|alarm| {"_origin": 1}"#;
302
303 let conf = WplExpress::new(vec![fdc3("auto", " ", true)?]);
304 let ppl = WplEvaluator::from(&conf, None)?;
305
306 let result = ppl.parse_groups(0, &mut data).assert();
307 result.items.iter().for_each(|f| println!("{}", f));
308 Ok(())
309 }
310
311 #[test]
312 fn log_test_ips() -> AnyResult<()> {
313 let conf = WplExpress::new(vec![fdc3("auto", " ", true)?]);
314 let ppl = WplEvaluator::from(&conf, None)?;
315 let mut data = r#"id=tos time="2023-05-15 09:11:53" fw=OS pri=5 type=mgmt user=superman src=10.111.233.51 op="Modify pwd of manager" result=0 recorder=manager_so msg="null""#;
316 let result = ppl.parse_groups(0, &mut data).assert();
317 result.items.iter().for_each(|f| println!("{}", f));
318 let mut data = r#"id=tos time="2023-05-15 09:11:53" fw=OS pri=5 type=mgmt user=superman src=10.111.233.51 op="system admininfo modify name zhaolei new_password QXF5dW53ZWleMDIwNw== privilege config login_type local comment 安全管理员 add" result=0 recorder=config msg="nuid=tos time="2023-05-15 09:11:53" fw=OS pri=5 type=mgmt user=superman src=10.111.233.51 op="webtr webadmin show" result=-1 recorder=config msg="error -8010 : 无效输入,分析" "#;
319 let result = ppl.parse_groups(0, &mut data).assert();
320 result.items.iter().for_each(|f| println!("{}", f));
321 Ok(())
322 }
323
324 #[test]
326 fn log_test_nginx() -> AnyResult<()> {
327 let conf = WplExpress::new(vec![fdc3("auto", " ", true)?]);
328 let ppl = WplEvaluator::from(&conf, None)?;
329 let mut data = r#"192.168.1.2 - - [06/Aug/2019:12:12:19 +0800] "GET /nginx-logo.png HTTP/1.1" 200 368 "http://119.122.1.4/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-""#;
330
331 let result = ppl.parse_groups(0, &mut data).assert();
332 assert_eq!(data, "");
333 result.items.iter().for_each(|f| println!("{}", f));
334 Ok(())
335 }
336
337 #[test]
338 fn test_huawei_default() -> AnyResult<()> {
339 let mut data = r#"<190>May 15 2023 07:09:12 KM-KJY-DC-USG12004-B02 %%01POLICY/6/POLICYPERMIT(l):CID=0x814f041e;vsys=CSG_Security, protocol=6, source-ip=10.111.117.49, source-port=34616, destination-ip=10.111.48.230, destination-port=50051, time=2023/5/15 15:09:12, source-zone=untrust, destination-zone=trust, application-name=, line-name=HO202212080377705-1.%"#;
340
341 let conf = WplExpress::new(vec![fdc3("auto", " ", true)?]);
342 let ppl = WplEvaluator::from(&conf, None)?;
343 let result = ppl.parse_groups(0, &mut data).assert();
344
345 assert_eq!(data, "");
346 result.items.iter().for_each(|f| println!("{}", f));
347 Ok(())
348 }
349
350 #[test]
351 fn test_huawei_detail() -> AnyResult<()> {
352 let mut data = r#"<190>May 15 2023 07:09:12 KM-KJY-DC-USG12004-B02 %%01POLICY/6/POLICYPERMIT(l):CID=0x814f041e;vsys=CSG_Security, protocol=6"#;
354 let fmt = WplFieldFmt {
355 scope_beg: Some("<".to_string()),
357 scope_end: Some(">".to_string()),
358 field_cnt: None,
359 sub_fmt: None,
360 };
361 let conf = WplExpress::new(vec![
362 fdc2_1("digit", fmt)?,
363 fdc2("auto", " ")?,
364 fdc2("chars", " ")?,
365 fdc2("chars", ":")?,
366 fdc2("kv", ";")?,
367 fdc2("auto", ",")?,
368 fdc2("auto", ",")?,
369 ]);
370
371 let ppl = WplEvaluator::from(&conf, None)?;
372 let result = ppl.parse_groups(0, &mut data).assert();
373 assert_eq!(data, "");
374 result.items.iter().for_each(|f| println!("{}", f));
375 Ok(())
376 }
377
378 #[test]
379 fn test_huawei_simple() -> AnyResult<()> {
380 let mut data = r#"<190>May 15 2023 07:09:12 KM-KJY-DC-USG12004-B02 %%01POLICY/6/POLICYPERMIT(l):CID=0x814f041e;vsys=CSG_Security, protocol=6"#;
382 let conf = WplExpress::new(vec![
383 fdc3("auto", " ", true)?,
384 fdc2("chars", ":")?,
385 fdc3("auto", ";", false)?,
386 fdc3("auto", ",", true)?,
387 ]);
388 let ppl = WplEvaluator::from(&conf, None)?;
389 let result = ppl.parse_groups(0, &mut data).assert();
390 assert_eq!(data, "");
391 result.items.iter().for_each(|f| println!("{:?}", f));
392 Ok(())
393 }
394
395 #[test]
396 fn test_huawei_simple2() -> AnyResult<()> {
397 let mut data = r#"<190>May 15 2023 07:09:12 KM-KJY-DC-USG12004-B02 %%01POLICY/6/POLICYPERMIT(l):CID=0x814f041e;vsys=CSG_Security, protocol=6"#;
398 let conf = WplExpress::new(vec![
399 WplField::try_parse("symbol(<190>)[5]").assert(),
400 fdc3("time", " ", false)?,
401 WplField::try_parse("symbol(KM)[2]").assert(),
402 fdc2("chars", ":")?,
403 fdc3("auto", ";", false)?,
404 fdc3("auto", ",", true)?,
405 ]);
406 let ppl = WplEvaluator::from(&conf, None)?;
407 let result = ppl.parse_groups(0, &mut data).assert();
408 assert_eq!(data, "");
409 result.items.iter().for_each(|f| println!("{:?}", f));
410 Ok(())
411 }
412
413 #[test]
414 fn test_gen() -> AnyResult<()> {
415 let mut data = r#"2345,2021-7-15 7:50:32,9OPP-MU-JME2-YGUW,chars_740,2022-1-18 19:30:30,jki=BkRzBo0f,138.11.13.43,tEu=GRcCwKkR,chars_493,Mrc=EskxskU3,sYp=jfKkn7th,UBa=eKhcfd9h,nXa=ZQSta6Je"#;
416 let conf = WplExpress::new(vec![
417 fdc3("digit", ",", false)?,
418 fdc3("time", ",", false)?,
419 fdc3("sn", ",", false)?,
420 fdc3("chars", ",", false)?,
421 fdc3("time", ",", false)?,
422 fdc3("auto", ",", true)?,
423 ]);
424 let ppl = WplEvaluator::from(&conf, None)?;
425 let result = ppl.parse_groups(0, &mut data).assert();
426 assert_eq!(data, "");
427 result.items.iter().for_each(|f| println!("{}", f));
428 Ok(())
429 }
430
431 #[test]
432 fn test_gen2() -> AnyResult<()> {
433 let mut data = r#"7106,2020-6-10 2:54:9,U5BH-UC-UQVY-MMKU,chars_472,2020-9-22 13:4:6,Emm=LXJDV5DC,22.161.67.67,nsL=LvVRv5uf,chars_1534,DNw=0xCQKTaQ,UFh=dMPbabRG,q29=aMsZTj83,oUi=ywMsKT2G"#;
434 let conf = WplExpress::new(vec![
435 fdc3("digit", ",", false)?,
436 fdc3("time", ",", false)?,
437 fdc3("sn", ",", false)?,
438 fdc3("chars", ",", false)?,
439 fdc3("time", ",", false)?,
440 fdc3("kv", ",", false)?,
441 fdc3("ip", ",", false)?,
442 fdc3("kv", ",", false)?,
443 fdc3("chars", ",", false)?,
444 fdc3("kv", ",", false)?,
445 fdc3("kv", ",", false)?,
446 fdc3("kv", ",", false)?,
447 fdc3("kv", ",", false)?,
448 ]);
449 let ppl = WplEvaluator::from(&conf, None)?;
450 let result = ppl.parse_groups(0, &mut data).assert();
451 assert_eq!(data, "");
452 result.items.iter().for_each(|f| println!("{}", f));
453
454 let mut data = r#"1857,2021-4-10 0:46:8,R2IP-IF-06UT-7KUU,chars_1914,2021-4-15 2:19:43,u6s=TNSAlucV,228.211.38.109,k02=doYanSlf,chars_276,SIw=nu8atSqT,84e=e6qUb2k7,aVs=pk8M8rQU,5An=9upLU8aa"#;
455 let result = ppl.parse_groups(0, &mut data).assert();
456 assert_eq!(data, "");
457 result.items.iter().for_each(|f| println!("{}", f));
458 Ok(())
459 }
460
461 #[test]
462 fn preorder_plg_pipe_unit_executes() -> AnyResult<()> {
463 #[derive(Debug)]
464 struct MockStage;
465
466 impl PipeProcessor for MockStage {
467 fn process(&self, data: RawData) -> WparseResult<RawData> {
468 let mut value = raw_to_utf8_string(&data);
469 value.push_str("-mock");
470 Ok(RawData::from_string(value))
471 }
472
473 fn name(&self) -> &'static str {
474 "mock_stage"
475 }
476 }
477
478 register_wpl_pipe!("plg_pipe/MOCK-STAGE", || Hold::new(MockStage));
479
480 let mut expr = WplExpress::new(vec![fdc3("auto", " ", true)?]);
481 expr.pipe_process = vec![SmolStr::from("plg_pipe/MOCK-STAGE")];
482
483 let evaluator = WplEvaluator::from(&expr, None)?;
484 let results = evaluator.preorder_proc(RawData::from_string("data".to_string()))?;
485 assert_eq!(results.len(), 1);
486 assert_eq!(results[0].result, "data-mock");
487 assert_eq!(results[0].name, "mock_stage");
488 Ok(())
489 }
490
491 #[test]
492 fn test_ignore() -> AnyResult<()> {
493 let mut data = r#"2345,2021-7-15 7:50:32,9OPP-MU-JME2-YGUW,chars_740"#;
494 let conf = WplExpress::new(vec![
495 fdc3("_", ",", false)?,
496 fdc3("_", ",", false)?,
497 fdc3("_", ",", false)?,
498 fdc3("_", ",", false)?,
499 ]);
500 let ppl = WplEvaluator::from(&conf, None)?;
501 let result = ppl.parse_groups(0, &mut data).assert();
502 assert_eq!(data, "");
503 result.items.iter().for_each(|f| println!("{}", f));
504 Ok(())
505 }
506
507 #[test]
508 fn test_ignore_cnt() -> AnyResult<()> {
509 let mut data = r#"2345,2021-7-15 7:50:32,9OPP-MU-JME2-YGUW,chars_740"#;
510 let conf = WplExpress::new(vec![fdc4_1("_", ",", true, 4)?]);
511 let ppl = WplEvaluator::from(&conf, None)?;
512 let result = ppl.parse_groups(0, &mut data).assert();
513 assert_eq!(data, "");
514 assert_eq!(result.items.len(), 4);
515 result.items.iter().for_each(|f| println!("{}", f));
516
517 let mut data = r#"2345,2021-7-15 7:50:32,9OPP-MU-JME2-YGUW,chars_740"#;
518 let conf = WplExpress::new(vec![fdc4_1("_", ",", true, 3)?]);
519 let ppl = WplEvaluator::from(&conf, None)?;
520 let result = ppl.parse_groups(0, &mut data).assert();
521 assert_eq!(data, "chars_740");
522 assert_eq!(result.items.len(), 3);
523 Ok(())
524 }
525
526 #[test]
527 fn test_pipe_unit_direct_lookup() -> AnyResult<()> {
528 use crate::eval::builtins::raw_to_utf8_string;
529 use crate::{create_preorder_pipe_unit, list_preorder_pipe_units};
530
531 #[derive(Debug)]
533 struct TestMockStage;
534
535 impl PipeProcessor for TestMockStage {
536 fn process(&self, data: RawData) -> WparseResult<RawData> {
537 let mut value = raw_to_utf8_string(&data);
538 value.push_str("-mock");
539 Ok(RawData::from_string(value))
540 }
541
542 fn name(&self) -> &'static str {
543 "test_mock_stage"
544 }
545 }
546
547 register_wpl_pipe!("direct-test", || Hold::new(TestMockStage));
550 register_wpl_pipe!("plg_pipe/mock-prefix", || Hold::new(TestMockStage));
551
552 let processor = create_preorder_pipe_unit("direct-test");
554 assert!(processor.is_some(), "Should find direct-test processor");
555
556 let processor = create_preorder_pipe_unit("plg_pipe/mock-prefix");
558 assert!(
559 processor.is_some(),
560 "Should find plg_pipe/with-prefix processor"
561 );
562
563 let test_data = RawData::from_string("hello".to_string());
565
566 if let Some(processor) = create_preorder_pipe_unit("direct-test") {
567 let result = processor.process(test_data.clone())?;
568 assert_eq!(raw_to_utf8_string(&result), "hello-mock");
569 }
570
571 if let Some(processor) = create_preorder_pipe_unit("plg_pipe/mock-prefix") {
572 let result = processor.process(test_data)?;
573 assert_eq!(raw_to_utf8_string(&result), "hello-mock");
574 }
575
576 let processors = list_preorder_pipe_units();
578 println!("All registered processors: {:?}", processors);
579
580 assert!(processors.contains(&"DIRECT-TEST".into()));
582 assert!(processors.contains(&"PLG_PIPE/MOCK-PREFIX".into()));
583
584 Ok(())
585 }
586
587 #[test]
588 fn test_simplified_assemble_ins_logic() -> AnyResult<()> {
589 use crate::eval::builtins::raw_to_utf8_string;
590 use crate::{create_preorder_pipe_unit, list_preorder_pipe_units};
591
592 #[derive(Debug)]
594 struct SimplifiedTestStage;
595
596 impl PipeProcessor for SimplifiedTestStage {
597 fn process(&self, data: RawData) -> WparseResult<RawData> {
598 let mut value = raw_to_utf8_string(&data);
599 value.push_str("-simplified");
600 Ok(RawData::from_string(value))
601 }
602
603 fn name(&self) -> &'static str {
604 "simplified_test"
605 }
606 }
607
608 register_wpl_pipe!("simple-test", || Hold::new(SimplifiedTestStage));
610 register_wpl_pipe!("plg_pipe/simple-prefix", || Hold::new(SimplifiedTestStage));
611
612 let processor1 = create_preorder_pipe_unit("simple-test");
614 assert!(processor1.is_some(), "Should find simple-test");
615
616 let processor2 = create_preorder_pipe_unit("plg_pipe/simple-prefix");
617 assert!(processor2.is_some(), "Should find plg_pipe/with-prefix");
618
619 let processor3 = create_preorder_pipe_unit("simple-prefix");
622 assert!(
623 processor3.is_none(),
624 "Should NOT find with-prefix (was registered as plg_pipe/with-prefix)"
625 );
626
627 let processors = list_preorder_pipe_units();
629 println!("All processors: {:?}", processors);
630
631 Ok(())
632 }
633}