nom_xml/
misc.rs

1// misc.rs
2use crate::{
3    parse::Parse, processing_instruction::ProcessingInstruction, Document, Error, IResult,
4};
5use nom::{branch::alt, combinator::map};
6
7#[derive(Clone, PartialEq, Eq)]
8pub enum MiscState {
9    BeforeDoctype,
10    AfterDoctype,
11}
12
13#[derive(Clone, PartialEq, Eq)]
14pub struct Misc {
15    pub content: Box<Document>, // Document::Comment | Document::ProcessingInstruction>
16    pub state: MiscState,
17}
18
19impl<'a> Parse<'a> for Misc {
20    type Args = MiscState;
21    type Output = IResult<&'a str, Self>;
22
23    //[27] Misc ::= Comment | PI | S
24    fn parse(input: &'a str, args: Self::Args) -> Self::Output {
25        let mut input_remaining = input;
26        let mut content_vec: Vec<Document> = vec![];
27        loop {
28            let parse_result = alt((
29                Document::parse_comment,
30                map(
31                    |i| ProcessingInstruction::parse(i, ()),
32                    Document::ProcessingInstruction,
33                ),
34                map(Self::parse_multispace1, |_| Document::Empty),
35            ))(input_remaining);
36
37            match parse_result {
38                Ok((remaining, document)) => {
39                    match document {
40                        Document::Empty => {} // Don't add Document::Empty types to content_vec
41                        _ => content_vec.push(document),
42                    }
43                    input_remaining = remaining;
44                }
45
46                Err(_) => {
47                    if !content_vec.is_empty() {
48                        break;
49                    } else {
50                        return Err(nom::Err::Error(Error::NomError(nom::error::Error::new(
51                            input.to_string(),
52                            nom::error::ErrorKind::Many0,
53                        ))));
54                    }
55                }
56            }
57        }
58
59        let content = Box::new(Document::Nested(content_vec));
60        Ok((
61            input_remaining,
62            Misc {
63                content,
64                state: args,
65            },
66        ))
67    }
68}