1use core::{
2 convert::Infallible,
3 fmt::{
4 self,
5 Debug,
6 Display,
7 Formatter,
8 },
9 ops::{
10 ControlFlow,
11 FromResidual,
12 Try,
13 },
14};
15
16use crate::{
17 Contexting,
18 ParsedAux,
19 ProvideElement,
20 Split,
21 Streaming,
22 Success,
23};
24
25#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum Parsed<Token, Stream, Context> {
29 Success {
31 token: Token,
33 stream: Stream,
35 },
36 Failure(Context),
39 Error(Context),
44}
45
46impl<Token, Stream, Context> Parsed<Token, Stream, Context> {
47 pub const fn new_success(token: Token, stream: Stream) -> Self {
49 Self::Success { token, stream }
50 }
51
52 pub const fn new_failure(content: Context) -> Self {
54 Self::Failure(content)
55 }
56
57 pub const fn new_error(content: Context) -> Self {
59 Self::Error(content)
60 }
61
62 pub const fn as_ref(&self) -> Parsed<&Token, &Stream, &Context> {
64 match self {
65 Self::Success { token, stream } => Parsed::Success { token, stream },
66 Self::Failure(context) => Parsed::Failure(context),
67 Self::Error(context) => Parsed::Error(context),
68 }
69 }
70
71 pub fn map_success<MappedToken, Map>(self, map: Map) -> Parsed<MappedToken, Stream, Context>
73 where
74 Map: FnOnce(Success<Token, Stream>) -> Success<MappedToken, Stream>,
75 {
76 match self {
77 Parsed::Success { token, stream } => map(Success { token, stream }).into(),
78 Parsed::Failure(context) => Parsed::Failure(context),
79 Parsed::Error(context) => Parsed::Error(context),
80 }
81 }
82
83 pub fn map_token<MappedToken, Map>(self, map: Map) -> Parsed<MappedToken, Stream, Context>
85 where
86 Map: FnOnce(Token) -> MappedToken,
87 {
88 match self {
89 Parsed::Success { token, stream } => Parsed::Success {
90 token: map(token),
91 stream,
92 },
93 Parsed::Failure(context) => Parsed::Failure(context),
94 Parsed::Error(context) => Parsed::Error(context),
95 }
96 }
97
98 pub fn map_stream<Map>(self, map: Map) -> Parsed<Token, Stream, Context>
100 where
101 Map: FnOnce(Stream) -> Stream,
102 {
103 match self {
104 Parsed::Success { token, stream } => Parsed::Success {
105 token,
106 stream: map(stream),
107 },
108 Parsed::Failure(context) => Parsed::Failure(context),
109 Parsed::Error(context) => Parsed::Error(context),
110 }
111 }
112
113 pub fn map_context<MappedAtom, Map>(self, map: Map) -> Parsed<Token, Stream, MappedAtom>
115 where
116 Map: FnOnce(Context) -> MappedAtom,
117 {
118 match self {
119 Parsed::Success { token, stream } => Parsed::Success { token, stream },
120 Parsed::Failure(context) => Parsed::Failure(map(context)),
121 Parsed::Error(context) => Parsed::Error(map(context)),
122 }
123 }
124
125 pub fn add_context<C, Map>(self, map: Map) -> Parsed<Token, Stream, Context>
127 where
128 Map: FnOnce() -> C,
129 Context: Contexting<C>,
130 {
131 match self {
132 Parsed::Success { token, stream } => Parsed::Success { token, stream },
133 Parsed::Failure(content) => Parsed::Failure(content.add(map())),
134 Parsed::Error(content) => Parsed::Error(content.add(map())),
135 }
136 }
137
138 pub fn unwrap(self) -> Success<Token, Stream>
141 where
142 Context: Debug,
143 {
144 match self {
145 Parsed::Success { token, stream } => Success { token, stream },
146 Parsed::Failure(context) => panic!("Call unwrap on Parsed::Failure: {:?}", context),
147 Parsed::Error(context) => panic!("Call unwrap on Parsed::Error: {:?}", context),
148 }
149 }
150
151 pub fn unwrap_context(self) -> Context
154 where
155 Token: Debug,
156 Stream: Debug,
157 {
158 match self {
159 Parsed::Success { token, stream } => {
160 panic!("Call unwrap on Parsed::Success: {:?} {:?}", token, stream)
161 }
162 Parsed::Failure(context) => context,
163 Parsed::Error(context) => context,
164 }
165 }
166
167 pub const fn is_success(&self) -> bool {
169 match self {
170 Parsed::Success { .. } => true,
171 _ => false,
172 }
173 }
174}
175
176impl<Token, Stream, Context> From<Success<Token, Stream>> for Parsed<Token, Stream, Context> {
177 fn from(Success { token, stream }: Success<Token, Stream>) -> Self {
178 Parsed::Success { token, stream }
179 }
180}
181
182impl<Token, Stream, Context> FromResidual for Parsed<Token, Stream, Context> {
183 fn from_residual(residual: Parsed<Infallible, Infallible, Context>) -> Self {
184 match residual {
185 Parsed::Success { .. } => unreachable!(),
186 Parsed::Failure(context) => Parsed::Failure(context),
187 Parsed::Error(context) => Parsed::Error(context),
188 }
189 }
190}
191
192impl<Token, Stream, Context> FromResidual<ParsedAux<Infallible, Context>>
193 for Parsed<Token, Stream, Context>
194{
195 fn from_residual(residual: ParsedAux<Infallible, Context>) -> Self {
196 match residual {
197 ParsedAux::Success(_success) => unreachable!(),
198 ParsedAux::Failure(context) => Parsed::Failure(context),
199 ParsedAux::Error(context) => Parsed::Error(context),
200 }
201 }
202}
203
204impl<Token, Stream, Context> FromResidual<Result<Infallible, Context>>
205 for Parsed<Token, Stream, Context>
206{
207 fn from_residual(residual: Result<Infallible, Context>) -> Self {
208 match residual {
209 Ok(_success) => unreachable!(),
210 Err(context) => Parsed::Failure(context),
211 }
212 }
213}
214
215impl<Token, Stream, Context> Try for Parsed<Token, Stream, Context> {
224 type Output = Success<Token, Stream>;
225 type Residual = Parsed<Infallible, Infallible, Context>;
226
227 fn from_output(output: Self::Output) -> Self {
228 output.into()
229 }
230
231 fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
232 match self {
233 Parsed::Success { token, stream } => ControlFlow::Continue(Success { token, stream }),
234 Parsed::Failure(context) => ControlFlow::Break(Parsed::Failure(context)),
235 Parsed::Error(context) => ControlFlow::Break(Parsed::Error(context)),
236 }
237 }
238}
239
240use owo_colors::OwoColorize;
241
242impl<Token, Stream, Context> Display for Parsed<Token, Stream, Context>
243where
244 Token: Debug,
245 Stream: Streaming,
246 Context: ProvideElement,
247{
248 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
249 match self {
250 Parsed::Success { token, stream } => match stream.clone().split_at(8) {
251 Split::Success {
252 item: stream,
253 stream: _,
254 } => {
255 write!(
256 f,
257 "{}: {:02X?}, stream: {:02X?} ..",
258 "Success".green(),
259 token,
260 stream
261 )
262 }
263 Split::NotEnoughItem(stream) => {
264 write!(
265 f,
266 "{}: {:02X?}, stream: {:02X?}",
267 "Success".green(),
268 token,
269 stream
270 )
271 }
272 Split::Error(error) => {
273 write!(
274 f,
275 "{}: {:02X?}, stream: {:?}",
276 "Success".green(),
277 token,
278 error
279 )
280 }
281 },
282 Parsed::Failure(context) => {
283 write!(f, "{}: {}", "Failure".yellow(), context.last())
284 }
285 Parsed::Error(context) => {
286 write!(f, "{}: {}", "Error".red(), context.last())
287 }
288 }
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use crate::{
295 Parsed,
296 Success,
297 };
298
299 fn multiply_by_42(parsed: Parsed<u8, (), ()>) -> Parsed<u8, (), ()> {
300 let Success { token, .. } = parsed?;
301 Parsed::Success {
302 token: token * 42,
303 stream: (),
304 }
305 }
306
307 #[test]
308 fn parsed() {
309 assert_eq!(
310 multiply_by_42(Parsed::new_success(1, ())),
311 Parsed::new_success(42, ())
312 );
313 assert_eq!(multiply_by_42(Parsed::Failure(())), Parsed::Failure(()));
314 assert_eq!(multiply_by_42(Parsed::Error(())), Parsed::Error(()));
315 }
316}