neure/re/regex/
dthen.rs

1use std::fmt::Debug;
2use std::marker::PhantomData;
3
4use crate::ctx::Context;
5use crate::ctx::CtxGuard;
6use crate::ctx::Match;
7use crate::ctx::Ret;
8use crate::ctx::Span;
9use crate::err::Error;
10use crate::map::Select0;
11use crate::map::Select1;
12use crate::map::SelectEq;
13use crate::re::ctor::Map;
14use crate::re::def_not;
15use crate::re::trace;
16use crate::re::Regex;
17
18#[derive(Default, Copy)]
19pub struct DynamicCreateRegexThen<C, P, F> {
20    pat: P,
21    func: F,
22    marker: PhantomData<C>,
23}
24
25def_not!(DynamicCreateRegexThen<C, P, F>);
26
27impl<C, P, F> Debug for DynamicCreateRegexThen<C, P, F>
28where
29    P: Debug,
30    F: Debug,
31{
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.debug_struct("DynamicCreateRegexThen")
34            .field("pat", &self.pat)
35            .field("func", &self.func)
36            .finish()
37    }
38}
39
40impl<C, P, F> Clone for DynamicCreateRegexThen<C, P, F>
41where
42    P: Clone,
43    F: Clone,
44{
45    fn clone(&self) -> Self {
46        Self {
47            pat: self.pat.clone(),
48            func: self.func.clone(),
49            marker: self.marker,
50        }
51    }
52}
53
54impl<C, P, F> DynamicCreateRegexThen<C, P, F> {
55    pub fn new(pat: P, func: F) -> Self {
56        Self {
57            pat,
58            func,
59            marker: PhantomData,
60        }
61    }
62
63    pub fn pat(&self) -> &P {
64        &self.pat
65    }
66
67    pub fn pat_mut(&mut self) -> &mut P {
68        &mut self.pat
69    }
70
71    pub fn func(&self) -> &F {
72        &self.func
73    }
74
75    pub fn func_mut(&mut self) -> &mut F {
76        &mut self.func
77    }
78
79    pub fn set_pat(&mut self, pat: P) -> &mut Self {
80        self.pat = pat;
81        self
82    }
83
84    pub fn set_func(&mut self, func: F) -> &mut Self {
85        self.func = func;
86        self
87    }
88
89    pub fn _0<O>(self) -> Map<C, Self, Select0, O> {
90        Map::new(self, Select0)
91    }
92
93    pub fn _1<O>(self) -> Map<C, Self, Select1, O> {
94        Map::new(self, Select1)
95    }
96
97    pub fn _eq<I1, I2>(self) -> Map<C, Self, SelectEq, (I1, I2)> {
98        Map::new(self, SelectEq)
99    }
100}
101
102impl<'a, C, P, F, T> Regex<C> for DynamicCreateRegexThen<C, P, F>
103where
104    P: Regex<C, Ret = Span>,
105    T: Regex<C, Ret = Span>,
106    C: Context<'a> + Match<C>,
107    F: Fn(&Span) -> Result<T, Error>,
108{
109    type Ret = P::Ret;
110
111    #[inline(always)]
112    fn try_parse(&self, ctx: &mut C) -> Result<Self::Ret, Error> {
113        let mut g = CtxGuard::new(ctx);
114        let beg = g.beg();
115        let mut ret = trace!("dynamic_create_regex_then", beg @ "pat", g.try_mat(&self.pat)?);
116
117        ret.add_assign(
118            trace!("dynamic_create_regex_then", beg @ "dynamic regex", g.try_mat(&(self.func)(&ret)?)?)
119        );
120        trace!("dynamic_create_regex_then", beg => g.end(), Ok(ret))
121    }
122}
123
124pub trait DynamicCreateRegexThenHelper<'a, C>
125where
126    Self: Sized,
127    C: Context<'a> + Match<C>,
128{
129    fn dyn_then_regex<F>(self, func: F) -> DynamicCreateRegexThen<C, Self, F>;
130}
131
132impl<'a, C, T> DynamicCreateRegexThenHelper<'a, C> for T
133where
134    Self: Sized,
135    C: Context<'a> + Match<C>,
136{
137    fn dyn_then_regex<F>(self, func: F) -> DynamicCreateRegexThen<C, Self, F> {
138        DynamicCreateRegexThen::new(self, func)
139    }
140}