kalosm_sample/structured_parser/
or.rs

1use std::{
2    borrow::Cow,
3    error::Error,
4    fmt::{Display, Formatter},
5};
6
7use crate::{CreateParserState, ParseResult, ParseStatus, Parser};
8
9/// State of a choice parser.
10#[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    /// Create a new choice parser state.
18    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/// A parser for a choice of two parsers.
36#[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    /// Create a new choice parser.
44    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/// A value that can be one of two types.
67#[derive(Debug, PartialEq, Eq, Copy, Clone)]
68pub enum Either<L, R> {
69    /// The value is the left type.
70    Left(L),
71    /// The value is the right type.
72    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                    // If one parser finishes, we return the result of that parser
106                    (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                    // If either parser is incomplete, we return the incomplete state
119                    (
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                    // If both parsers fail, we return the error from the first parser
190                    (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}