chrono_node/common/
abstract_refiners.rs1use crate::core::chrono::Refiner;
7use crate::core::context::ParsingContext;
8use crate::core::result::ParsingResult;
9
10pub trait FilterRefiner: Send + Sync {
12 fn is_valid(&self, context: &ParsingContext, result: &ParsingResult) -> bool;
13}
14
15pub struct Filtering<F>(pub F);
16
17impl<F: FilterRefiner> Filtering<F> {
18 pub fn new(inner: F) -> Filtering<F> {
19 Filtering(inner)
20 }
21}
22
23impl<F: FilterRefiner> Refiner for Filtering<F> {
24 fn refine(&self, context: &ParsingContext, results: Vec<ParsingResult>) -> Vec<ParsingResult> {
25 results.into_iter().filter(|r| self.0.is_valid(context, r)).collect()
26 }
27}
28
29pub trait MergingRefiner: Send + Sync {
31 fn should_merge_results(
32 &self,
33 text_between: &str,
34 current: &ParsingResult,
35 next: &ParsingResult,
36 context: &ParsingContext,
37 ) -> bool;
38
39 fn merge_results(
41 &self,
42 text_between: &str,
43 current: ParsingResult,
44 next: ParsingResult,
45 context: &ParsingContext,
46 ) -> ParsingResult;
47}
48
49pub struct Merging<M>(pub M);
50
51impl<M: MergingRefiner> Merging<M> {
52 pub fn new(inner: M) -> Merging<M> {
53 Merging(inner)
54 }
55}
56
57fn floor_char_boundary(text: &str, i: usize) -> usize {
58 let mut i = i.min(text.len());
59 while !text.is_char_boundary(i) {
60 i -= 1;
61 }
62 i
63}
64
65pub fn js_substring(text: &str, start: usize, end: usize) -> &str {
67 let (a, b) = if start <= end { (start, end) } else { (end, start) };
68 &text[floor_char_boundary(text, a)..floor_char_boundary(text, b)]
69}
70
71impl<M: MergingRefiner> Refiner for Merging<M> {
72 fn refine(&self, context: &ParsingContext, results: Vec<ParsingResult>) -> Vec<ParsingResult> {
73 if results.len() < 2 {
74 return results;
75 }
76 let mut merged = Vec::new();
77 let mut iter = results.into_iter();
78 let mut current = iter.next().expect("at least two results");
79 for next in iter {
80 let text_between = js_substring(&context.text, current.index + current.text.len(), next.index).to_string();
81 if !self.0.should_merge_results(&text_between, ¤t, &next, context) {
82 merged.push(current);
83 current = next;
84 } else {
85 current = self.0.merge_results(&text_between, current, next, context);
86 }
87 }
88 merged.push(current);
89 merged
90 }
91}