kalosm_sample/structured_parser/
one_line.rs1use crate::{CreateParserState, ParseResult, ParseStatus, Parser};
2
3#[derive(Debug, Clone, Copy)]
5pub struct OneLine;
6
7#[derive(Debug, Clone)]
9pub struct OneLineState {
10 all_whitespace: bool,
11 bytes: Vec<u8>,
12}
13
14impl CreateParserState for OneLine {
15 fn create_parser_state(&self) -> <Self as Parser>::PartialState {
16 OneLineState {
17 all_whitespace: true,
18 bytes: Vec::new(),
19 }
20 }
21}
22
23#[derive(Debug, Clone)]
25pub struct OneLineError;
26
27impl std::fmt::Display for OneLineError {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "OneLineError")
30 }
31}
32
33impl std::error::Error for OneLineError {}
34
35impl Parser for OneLine {
36 type Output = String;
37 type PartialState = OneLineState;
38
39 fn parse<'a>(
40 &self,
41 state: &Self::PartialState,
42 input: &'a [u8],
43 ) -> ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
44 if input.is_empty() {
45 return Ok(ParseStatus::Incomplete {
46 new_state: state.clone(),
47 required_next: Default::default(),
48 });
49 }
50 let mut state = state.clone();
51 let mut iter = input.iter();
52 while let Some(&c) = iter.next() {
53 if !c.is_ascii_alphanumeric() || matches!(c, b' ' | b'.' | b'\n') {
54 crate::bail!(OneLineError);
55 }
56 if state.all_whitespace {
57 let c = char::from(c);
58 if !c.is_whitespace() {
59 state.all_whitespace = false;
60 }
61 }
62 if c == b'\n' {
63 if state.all_whitespace {
64 crate::bail!(OneLineError);
65 } else {
66 return Ok(ParseStatus::Finished {
67 result: String::from_utf8_lossy(&state.bytes).to_string(),
68 remaining: iter.as_slice(),
69 });
70 }
71 }
72 state.bytes.push(c);
73 }
74 Ok(ParseStatus::Incomplete {
75 new_state: state,
76 required_next: Default::default(),
77 })
78 }
79}