esre/re/
repeat.rs

1use std::mem;
2use std::rc::Rc;
3
4use serde_json::value::to_value;
5use serde_json::{Map, Value};
6
7use crate::entities::re::{
8    ApplyError, ApplyResponse, ApplyResult, ParseJsonError, PossibleBegin, ReType, State,
9};
10use crate::js_tools::{FieldGetter, UsizeFieldGetter, ValueFieldGetter};
11use crate::proto::builders::IJsonParser;
12use crate::proto::into_re::IntoRe;
13use crate::proto::re::{compile_if_required, IRe};
14
15const PRIMARY_KEY: &str = "repeat";
16const MIN_KEY: &str = "min";
17const MAX_KEY: &str = "max";
18
19pub struct Re {
20    re: Rc<dyn IRe>,
21    min: Option<usize>,
22    max: Option<usize>,
23    next_re: Option<Rc<dyn IRe>>,
24}
25
26struct LoopState {
27    begin: usize,
28    count: usize,
29    result: Option<ApplyResponse>,
30    stop_flag: bool,
31}
32
33impl Re {
34    pub fn one_or_more<T: IntoRe>(re: T) -> Re {
35        Re {
36            re: re.into_ire(),
37            min: Some(1),
38            max: None,
39            next_re: None,
40        }
41    }
42
43    pub fn zero_or_more<T: IntoRe>(re: T) -> Re {
44        Re {
45            re: re.into_ire(),
46            min: None,
47            max: None,
48            next_re: None,
49        }
50    }
51
52    pub fn custom<T: IntoRe>(re: T, min: Option<usize>, max: Option<usize>) -> Re {
53        Re {
54            re: re.into_ire(),
55            min,
56            max,
57            next_re: None,
58        }
59    }
60
61    pub fn parse_dict(
62        parser: &dyn IJsonParser,
63        dict: &Map<String, Value>,
64    ) -> Result<Option<Rc<dyn IRe>>, ParseJsonError> {
65        let opt_re = ValueFieldGetter::with_primary_field(dict, PRIMARY_KEY, &|val| {
66            parser.parse_json(val)
67        })?;
68        let re = match opt_re {
69            Some(val) => val,
70            _ => return Ok(None),
71        };
72        let min = UsizeFieldGetter::with_param_nullable_field(dict, MIN_KEY, &|val| {
73            Ok(val.cloned())
74        })?;
75        let max = UsizeFieldGetter::with_param_nullable_field(dict, MAX_KEY, &|val| {
76            Ok(val.cloned())
77        })?;
78        Ok(Some(
79            Re {
80                re,
81                min,
82                max,
83                next_re: None,
84            }
85            .into_ire(),
86        ))
87    }
88
89    fn try_finalize_seq(
90        &self,
91        accum: Option<ApplyResponse>,
92        count: usize,
93    ) -> Result<ApplyResponse, ApplyError> {
94        match self.min {
95            Some(ref val) if count < *val => return Err(ApplyError::NotMatched),
96            _ => (),
97        };
98        if count == 0 {
99            return Err(ApplyError::Empty);
100        }
101        Ok(accum.unwrap())
102    }
103
104    fn apply_iteration(
105        &self,
106        global_state: &mut State,
107        loop_state: &mut LoopState,
108    ) -> Result<(), ApplyError> {
109        match self.re.apply(global_state, loop_state.begin) {
110            Ok(applied) => {
111                let begin = applied.index;
112                let acc = mem::replace(&mut loop_state.result, None);
113                let joined = ApplyResponse::join_acc(acc, applied);
114                loop_state.result = Some(joined);
115                loop_state.count += 1;
116                loop_state.begin = begin;
117                Ok(())
118            }
119            Err(ApplyError::NotMatched) => {
120                let acc = mem::replace(&mut loop_state.result, None);
121                let result = self.try_finalize_seq(acc, loop_state.count)?;
122                loop_state.result = Some(result);
123                loop_state.stop_flag = true;
124                Ok(())
125            }
126            Err(err) => Err(err),
127        }
128    }
129
130    fn try_next_re(&self, state: &mut State, begin: usize) -> bool {
131        if let Some(ref re) = self.next_re {
132            re.apply(state, begin).is_ok()
133        } else {
134            false
135        }
136    }
137}
138
139impl IRe for Re {
140    fn get_type(&self) -> ReType {
141        ReType::Repeat
142    }
143
144    fn apply(&self, global_state: &mut State, begin: usize) -> ApplyResult {
145        let min_count = self.min.unwrap_or(0);
146        let mut loop_state = LoopState {
147            begin,
148            count: 0,
149            result: None,
150            stop_flag: false,
151        };
152        while Some(loop_state.count) != self.max {
153            if loop_state.count >= min_count
154                && self.next_re.is_some()
155                && self.try_next_re(global_state, loop_state.begin)
156            {
157                return self.try_finalize_seq(loop_state.result, loop_state.count);
158            }
159            self.apply_iteration(global_state, &mut loop_state)?;
160            if loop_state.stop_flag {
161                return Ok(loop_state.result.unwrap());
162            }
163        }
164        Ok(loop_state.result.unwrap())
165    }
166
167    fn show(&self) -> String {
168        format!(
169            "{}{},{}>{},{}{}",
170            '{',
171            self.re.show(),
172            self.min
173                .as_ref()
174                .map_or("_".to_string(), |x| { x.to_string() }),
175            self.max
176                .as_ref()
177                .map_or("_".to_string(), |x| { x.to_string() }),
178            self.next_re.is_some(),
179            '}'
180        )
181    }
182
183    fn to_json(&self) -> Value {
184        Value::Object(
185            vec![
186                ("repeat".to_string(), self.re.to_json()),
187                ("min".to_string(), to_value(self.min).unwrap()),
188                ("max".to_string(), to_value(self.max).unwrap()),
189            ]
190            .into_iter()
191            .collect(),
192        )
193    }
194
195    fn is_any(&self) -> bool {
196        self.re.is_any()
197    }
198
199    fn get_children(&self) -> Vec<Rc<dyn IRe>> {
200        vec![self.re.clone()]
201    }
202
203    fn compilation_required(&self) -> bool {
204        if matches!(self.re.get_type(), ReType::Repeat) {
205            panic!("Repeat is direct child of repeat")
206        }
207        self.re.compilation_required() || self.max.is_none()
208    }
209
210    fn possible_begin(&self) -> PossibleBegin {
211        if self.min.unwrap_or(0) > 0 {
212            self.re.possible_begin()
213        } else {
214            PossibleBegin::Any
215        }
216    }
217
218    fn compile(&self, mut next_re: Option<Rc<dyn IRe>>) -> Rc<dyn IRe> {
219        let re = compile_if_required(self.re.clone(), next_re.clone());
220        let probe_required = if let Some(ref next) = next_re {
221            re.possible_begin().has_intersection(&next.possible_begin())
222        } else {
223            false
224        };
225        if self.max.is_some() || !probe_required {
226            next_re = None;
227        }
228        Re {
229            re,
230            next_re,
231            min: self.min,
232            max: self.max,
233        }
234        .into_ire()
235    }
236}