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}