1use wp_model_core::model::DataType;
2
3use crate::ParserFactory;
4use crate::ast::{WplRule, WplSep, WplStatementType};
5use crate::generator::{FmtField, FmtFieldVec, GenChannel, NamedFieldGF};
6use crate::types::AnyResult;
7
8type FieldGenFn = Box<dyn Fn(&mut GenChannel) -> AnyResult<FmtField> + Send + Sync>;
9
10pub struct CompiledRule {
12 fields: Vec<FieldGenFn>,
13}
14
15impl CompiledRule {
16 pub(crate) fn new(fields: Vec<FieldGenFn>) -> Self {
17 Self { fields }
18 }
19 pub fn gen_one(&self) -> AnyResult<FmtFieldVec> {
21 let mut ch = GenChannel::new();
22 let mut out = FmtFieldVec::new();
23 for f in &self.fields {
24 out.push(f(&mut ch)?);
25 }
26 Ok(out)
27 }
28 pub fn gen_batch(&self, _idx_begin: usize, count: usize) -> AnyResult<Vec<FmtFieldVec>> {
30 let mut v = Vec::with_capacity(count);
31 for _ in 0..count {
32 v.push(self.gen_one()?);
33 }
34 Ok(v)
35 }
36}
37
38pub fn compile_rule(
40 rule: &WplRule,
41 fields: &NamedFieldGF,
42) -> crate::parser::error::WplCodeResult<CompiledRule> {
43 match &rule.statement {
44 WplStatementType::Express(expr) => {
45 let mut items: Vec<FieldGenFn> = Vec::new();
46 let ups_sep = WplSep::default();
47 for group in &expr.group {
48 let sep = group.resolve_sep(&ups_sep);
49 for f_conf in &group.fields {
50 let gconf = f_conf
51 .name
52 .as_ref()
53 .and_then(|n| fields.get(n.as_str()))
54 .cloned();
55 let f_conf_cloned = f_conf.clone();
56 let sep_cloned = sep.clone();
57 let field_fn: FieldGenFn = Box::new(move |ch: &mut GenChannel| {
58 let meta = DataType::from(f_conf_cloned.meta_name.as_str())?;
59 let parser = ParserFactory::create(&meta)?;
60 let f = parser.generate(ch, &sep_cloned, &f_conf_cloned, gconf.as_ref())?;
61 Ok(f)
62 });
63 items.push(field_fn);
64 }
65 }
66 Ok(CompiledRule::new(items))
67 }
68 }
69}