1use std::{
2 borrow::Cow,
3 error::Error,
4 fmt::{Display, Formatter},
5};
6
7use crate::{CreateParserState, ParseResult, ParseStatus, Parser};
8
9#[derive(Debug, PartialEq, Eq, Clone)]
11pub struct ChoiceParserState<P1, P2> {
12 pub(crate) state1: ParseResult<P1>,
13 pub(crate) state2: ParseResult<P2>,
14}
15
16impl<P1, P2> ChoiceParserState<P1, P2> {
17 pub fn new(state1: P1, state2: P2) -> Self {
19 Self {
20 state1: Ok(state1),
21 state2: Ok(state2),
22 }
23 }
24}
25
26impl<P1: Default, P2: Default> Default for ChoiceParserState<P1, P2> {
27 fn default() -> Self {
28 ChoiceParserState {
29 state1: Ok(Default::default()),
30 state2: Ok(Default::default()),
31 }
32 }
33}
34
35#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
37pub struct ChoiceParser<P1, P2> {
38 pub(crate) parser1: P1,
39 pub(crate) parser2: P2,
40}
41
42impl<P1, P2> ChoiceParser<P1, P2> {
43 pub fn new(parser1: P1, parser2: P2) -> Self {
45 Self { parser1, parser2 }
46 }
47}
48
49impl<
50 O1,
51 O2,
52 PA1,
53 PA2,
54 P1: Parser<Output = O1, PartialState = PA1> + CreateParserState,
55 P2: Parser<Output = O2, PartialState = PA2> + CreateParserState,
56 > CreateParserState for ChoiceParser<P1, P2>
57{
58 fn create_parser_state(&self) -> <Self as Parser>::PartialState {
59 ChoiceParserState {
60 state1: Ok(self.parser1.create_parser_state()),
61 state2: Ok(self.parser2.create_parser_state()),
62 }
63 }
64}
65
66#[derive(Debug, PartialEq, Eq, Copy, Clone)]
68pub enum Either<L, R> {
69 Left(L),
71 Right(R),
73}
74
75impl<L: Display, R: Display> Display for Either<L, R> {
76 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Either::Left(l) => l.fmt(f),
79 Either::Right(r) => r.fmt(f),
80 }
81 }
82}
83
84impl<L: Error + 'static, R: Error + 'static> Error for Either<L, R> {
85 fn source(&self) -> Option<&(dyn Error + 'static)> {
86 match self {
87 Either::Left(l) => Some(l),
88 Either::Right(r) => Some(r),
89 }
90 }
91}
92
93impl<P1: Parser, P2: Parser> Parser for ChoiceParser<P1, P2> {
94 type Output = Either<P1::Output, P2::Output>;
95 type PartialState = ChoiceParserState<P1::PartialState, P2::PartialState>;
96
97 fn parse<'a>(
98 &self,
99 state: &Self::PartialState,
100 input: &'a [u8],
101 ) -> crate::ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
102 match (&state.state1, &state.state2) {
103 (Ok(p1), Ok(p2)) => {
104 match (self.parser1.parse(p1, input), self.parser2.parse(p2, input)) {
105 (Ok(ParseStatus::Finished { result, remaining }), _) => {
107 Ok(ParseStatus::Finished {
108 result: Either::Left(result),
109 remaining,
110 })
111 }
112 (_, Ok(ParseStatus::Finished { result, remaining })) => {
113 Ok(ParseStatus::Finished {
114 result: Either::Right(result),
115 remaining,
116 })
117 }
118 (
120 Ok(ParseStatus::Incomplete {
121 new_state: p1,
122 required_next: required_next1,
123 }),
124 Ok(ParseStatus::Incomplete {
125 new_state: p2,
126 required_next: required_next2,
127 }),
128 ) => {
129 let new_state = ChoiceParserState {
130 state1: Ok(p1),
131 state2: Ok(p2),
132 };
133 let mut common_bytes = 0;
134 for (byte1, byte2) in required_next1.bytes().zip(required_next2.bytes()) {
135 if byte1 != byte2 {
136 break;
137 }
138 common_bytes += 1;
139 }
140 Ok(ParseStatus::Incomplete {
141 new_state,
142 required_next: match (required_next1, required_next2) {
143 (Cow::Borrowed(required_next), _) => {
144 Cow::Borrowed(&required_next[..common_bytes])
145 }
146 (_, Cow::Borrowed(required_next)) => {
147 Cow::Borrowed(&required_next[..common_bytes])
148 }
149 (Cow::Owned(mut required_next), _) => {
150 required_next.truncate(common_bytes);
151 Cow::Owned(required_next)
152 }
153 },
154 })
155 }
156 (
157 Ok(ParseStatus::Incomplete {
158 new_state: p1,
159 required_next,
160 }),
161 Err(err2),
162 ) => {
163 let new_state = ChoiceParserState {
164 state1: Ok(p1),
165 state2: Err(err2),
166 };
167 Ok(ParseStatus::Incomplete {
168 new_state,
169 required_next,
170 })
171 }
172 (
173 Err(err1),
174 Ok(ParseStatus::Incomplete {
175 new_state: p2,
176 required_next,
177 }),
178 ) => {
179 let new_state = ChoiceParserState {
180 state1: Err(err1),
181 state2: Ok(p2),
182 };
183 Ok(ParseStatus::Incomplete {
184 new_state,
185 required_next,
186 })
187 }
188
189 (Err(err1), Err(_)) => Err(err1),
191 }
192 }
193 (Ok(p1), Err(err2)) => {
194 let result = self.parser1.parse(p1, input)?;
195 match result {
196 ParseStatus::Finished { result, remaining } => Ok(ParseStatus::Finished {
197 result: Either::Left(result),
198 remaining,
199 }),
200 ParseStatus::Incomplete {
201 new_state: p1,
202 required_next,
203 } => {
204 let new_state = ChoiceParserState {
205 state1: Ok(p1),
206 state2: Err(err2.clone()),
207 };
208 Ok(ParseStatus::Incomplete {
209 new_state,
210 required_next,
211 })
212 }
213 }
214 }
215 (Err(err1), Ok(p2)) => {
216 let result = self.parser2.parse(p2, input)?;
217 match result {
218 ParseStatus::Finished { result, remaining } => Ok(ParseStatus::Finished {
219 result: Either::Right(result),
220 remaining,
221 }),
222 ParseStatus::Incomplete {
223 new_state: p2,
224 required_next,
225 } => {
226 let new_state = ChoiceParserState {
227 state1: Err(err1.clone()),
228 state2: Ok(p2),
229 };
230 Ok(ParseStatus::Incomplete {
231 new_state,
232 required_next,
233 })
234 }
235 }
236 }
237 (Err(_), Err(_)) => {
238 unreachable!()
239 }
240 }
241 }
242}
243
244#[test]
245fn choice_parser() {
246 use crate::{LiteralParser, LiteralParserOffset};
247 let parser = ChoiceParser {
248 parser1: LiteralParser::new("Hello, "),
249 parser2: LiteralParser::new("world!"),
250 };
251 let state = ChoiceParserState::default();
252 assert_eq!(
253 parser.parse(&state, b"Hello, ").unwrap(),
254 ParseStatus::Finished {
255 result: Either::Left(()),
256 remaining: &[]
257 }
258 );
259 assert_eq!(
260 parser.parse(&state, b"Hello, ").unwrap(),
261 ParseStatus::Finished {
262 result: Either::Left(()),
263 remaining: &[]
264 }
265 );
266 assert_eq!(
267 parser.parse(&state, b"world!").unwrap(),
268 ParseStatus::Finished {
269 result: Either::Right(()),
270 remaining: &[]
271 }
272 );
273 assert!(parser.parse(&state, b"Goodbye, world!").is_err());
274
275 let parser = ChoiceParser::new(
276 LiteralParser::new("This isn't a test"),
277 LiteralParser::new("This is a test"),
278 );
279 let state = ChoiceParserState::default();
280 assert!(matches!(
281 parser.parse(&state, b"This isn").unwrap(),
282 ParseStatus::Incomplete {
283 new_state: ChoiceParserState {
284 state1: Ok(LiteralParserOffset { offset: 8 }),
285 state2: Err(_),
286 },
287 required_next: Cow::Borrowed("'t a test")
288 },
289 ));
290
291 let parser = ChoiceParser::new(
292 LiteralParser::new("Hello world"),
293 LiteralParser::new("Hi world"),
294 );
295 let state = ChoiceParserState::default();
296 assert!(matches!(
297 parser.parse(&state, b"H").unwrap(),
298 ParseStatus::Incomplete {
299 new_state: ChoiceParserState {
300 state1: Ok(LiteralParserOffset { offset: 1 }),
301 state2: Ok(LiteralParserOffset { offset: 1 }),
302 },
303 required_next: Cow::Borrowed("")
304 },
305 ));
306}