kalosm_sample/structured_parser/
index.rs1use std::borrow::Cow;
2
3use crate::{CreateParserState, ParseResult, ParseStatus, Parser};
4
5#[derive(Debug, Clone)]
7pub struct IndexParserState<PA> {
8 states: Vec<ParseResult<PA>>,
9}
10
11#[derive(Debug, Clone)]
13pub struct IndexParser<S: Parser> {
14 parsers: Vec<S>,
15}
16
17impl<S: Parser> IndexParser<S> {
18 pub fn new(parsers: Vec<S>) -> Self {
20 Self { parsers }
21 }
22}
23
24impl<S: CreateParserState> CreateParserState for IndexParser<S> {
25 fn create_parser_state(&self) -> Self::PartialState {
26 IndexParserState {
27 states: self
28 .parsers
29 .iter()
30 .map(|s| Ok(s.create_parser_state()))
31 .collect(),
32 }
33 }
34}
35
36impl<S: Parser> Parser for IndexParser<S> {
37 type Output = (usize, S::Output);
38 type PartialState = IndexParserState<S::PartialState>;
39
40 fn parse<'a>(
41 &self,
42 state: &Self::PartialState,
43 input: &'a [u8],
44 ) -> ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
45 let mut states = state.states.clone();
46 let mut has_incomplete_option = false;
47 let mut required_next: Option<Cow<'static, str>> = None;
48 let last_index = self.parsers.len() - 1;
49 for (i, parser) in self.parsers.iter().enumerate() {
50 match &states[i] {
51 Ok(state) => {
52 let result = parser.parse(state, input);
53 match result {
54 Ok(ParseStatus::Finished {
55 result,
56 remaining: r,
57 }) => {
58 return Ok(ParseStatus::Finished {
59 result: (i, result),
60 remaining: r,
61 })
62 }
63 Ok(ParseStatus::Incomplete {
64 new_state: s,
65 required_next: new_required_next,
66 }) => {
67 states[i] = Ok(s);
68 has_incomplete_option = true;
69 match required_next {
70 Some(r) => {
71 let mut common_bytes = 0;
72 for (byte1, byte2) in r.bytes().zip(new_required_next.bytes()) {
73 if byte1 != byte2 {
74 break;
75 }
76 common_bytes += 1;
77 }
78 required_next = Some(match (r, new_required_next) {
79 (Cow::Borrowed(required_next), _) => {
80 Cow::Borrowed(&required_next[common_bytes..])
81 }
82 (_, Cow::Borrowed(required_next)) => {
83 Cow::Borrowed(&required_next[common_bytes..])
84 }
85 (Cow::Owned(mut required_next), _) => {
86 required_next.truncate(common_bytes);
87 Cow::Owned(required_next)
88 }
89 });
90 }
91 None => {
92 required_next = Some(new_required_next);
93 }
94 }
95 }
96 Err(e) => {
97 if !has_incomplete_option && i == last_index {
98 return Err(e);
99 }
100 states[i] = Err(e);
101 }
102 }
103 }
104 Err(err) => {
105 if !has_incomplete_option && i == last_index {
106 return Err(err.clone());
107 }
108 }
109 }
110 }
111 Ok(ParseStatus::Incomplete {
112 new_state: IndexParserState { states },
113 required_next: required_next.unwrap_or_default(),
114 })
115 }
116}