neure/re/ctor/map.rs
1use std::fmt::Debug;
2use std::marker::PhantomData;
3
4use crate::ctx::Context;
5use crate::ctx::Match;
6use crate::ctx::Span;
7use crate::err::Error;
8use crate::map::MapSingle;
9use crate::re::def_not;
10use crate::re::Ctor;
11use crate::re::Extract;
12use crate::re::Handler;
13use crate::re::Regex;
14
15///
16/// Map the result to another type.
17///
18/// # Example 1
19///
20/// ```
21/// # use neure::{err::Error, prelude::*};
22/// #
23/// # fn main() -> color_eyre::Result<()> {
24/// # color_eyre::install()?;
25/// let str = neu::ascii_alphabetic()
26/// .repeat_times::<3>()
27/// // map &str to String
28/// .map(|v: &str| Ok(String::from(v)));
29/// let num = neu::digit(10)
30/// .repeat_times::<3>()
31/// // map &str to i32
32/// .map(|v: &str| v.parse::<i32>().map_err(|_| Error::Uid(0)));
33/// let (who, id) = CharsCtx::new("foo777").ctor(&str.then(num))?;
34///
35/// assert_eq!(who, "foo");
36/// assert_eq!(id, 777);
37///
38/// Ok(())
39/// # }
40/// ```
41///
42/// # Exampl 2
43///
44/// ```
45/// # use neure::{err::Error, prelude::*};
46/// #
47/// # fn main() -> color_eyre::Result<()> {
48/// # color_eyre::install()?;
49/// let str = neu::ascii_alphabetic()
50/// .repeat_times::<3>()
51/// // map &str to String
52/// .map(|v: (Span, _)| Ok(v));
53/// let num = neu::digit(10)
54/// .repeat_times::<3>()
55/// // map &str to i32
56/// .map(|(span, v): (Span, &str)| Ok((span, v.parse::<i32>().map_err(|_| Error::Uid(0))?)));
57/// let (who, id) = // you can pass the Span to callback of map
58/// CharsCtx::new("foo777").ctor_with(&str.then(num), &mut |span: Span, v: _| Ok((span, v)))?;
59///
60/// assert_eq!(who, (Span::new(0, 3), "foo"));
61/// assert_eq!(id, (Span::new(3, 3), 777));
62///
63/// Ok(())
64/// # }
65/// ```
66///
67/// # Example 3
68///
69/// ```
70/// # use neure::{err::Error, prelude::*};
71/// #
72/// # fn main() -> color_eyre::Result<()> {
73/// # color_eyre::install()?;
74/// let num = neu::digit(10).repeat_times::<3>();
75/// let id =
76/// CharsCtx::new("777").map(&num, |v: &str| v.parse::<i32>().map_err(|_| Error::Uid(0)))?;
77///
78/// assert_eq!(id, 777);
79///
80/// let (span, id) = CharsCtx::new("777").map_with(&num, |v: &str, span: Span| {
81/// Ok((span, v.parse::<i32>().map_err(|_| Error::Uid(0))?))
82/// })?;
83///
84/// assert_eq!(id, 777);
85/// assert_eq!(span, Span::new(0, 3));
86///
87/// Ok(())
88/// # }
89/// ```
90#[derive(Default, Copy)]
91pub struct Map<C, P, F, O> {
92 pat: P,
93 mapper: F,
94 marker: PhantomData<(C, O)>,
95}
96
97def_not!(Map<C, P, F, O>);
98
99impl<C, P, F, O> Debug for Map<C, P, F, O>
100where
101 P: Debug,
102 F: Debug,
103{
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 f.debug_struct("Map")
106 .field("pat", &self.pat)
107 .field("mapper", &self.mapper)
108 .finish()
109 }
110}
111
112impl<C, P, F, O> Clone for Map<C, P, F, O>
113where
114 P: Clone,
115 F: Clone,
116{
117 fn clone(&self) -> Self {
118 Self {
119 pat: self.pat.clone(),
120 mapper: self.mapper.clone(),
121 marker: self.marker,
122 }
123 }
124}
125
126impl<C, P, F, O> Map<C, P, F, O> {
127 pub fn new(pat: P, func: F) -> Self {
128 Self {
129 pat,
130 mapper: func,
131 marker: PhantomData,
132 }
133 }
134
135 pub fn pat(&self) -> &P {
136 &self.pat
137 }
138
139 pub fn mapper(&self) -> &F {
140 &self.mapper
141 }
142
143 pub fn pat_mut(&mut self) -> &mut P {
144 &mut self.pat
145 }
146
147 pub fn mapper_mut(&mut self) -> &mut F {
148 &mut self.mapper
149 }
150
151 pub fn set_pat(&mut self, pat: P) -> &mut Self {
152 self.pat = pat;
153 self
154 }
155
156 pub fn set_mapper(&mut self, func: F) -> &mut Self {
157 self.mapper = func;
158 self
159 }
160
161 pub fn map_to<H, V>(self, mapper: H) -> Map<C, P, H, O>
162 where
163 H: MapSingle<O, V>,
164 {
165 Map {
166 pat: self.pat,
167 mapper,
168 marker: self.marker,
169 }
170 }
171}
172
173impl<'a, C, M, O, V, P, F, H, A> Ctor<'a, C, M, V, H, A> for Map<C, P, F, O>
174where
175 P: Ctor<'a, C, M, O, H, A>,
176 F: MapSingle<O, V>,
177 C: Context<'a> + Match<C>,
178 H: Handler<A, Out = M, Error = Error>,
179 A: Extract<'a, C, Span, Out<'a> = A, Error = Error>,
180{
181 #[inline(always)]
182 fn construct(&self, ctx: &mut C, func: &mut H) -> Result<V, Error> {
183 self.mapper.map_to(self.pat.construct(ctx, func)?)
184 }
185}
186
187impl<'a, C, P, F, O> Regex<C> for Map<C, P, F, O>
188where
189 P: Regex<C, Ret = Span>,
190 C: Context<'a> + Match<C>,
191{
192 type Ret = P::Ret;
193
194 #[inline(always)]
195 fn try_parse(&self, ctx: &mut C) -> Result<Self::Ret, Error> {
196 ctx.try_mat(&self.pat)
197 }
198}