plantuml_parser/dsl/line/
header.rs

1use crate::HeaderToken;
2use crate::dsl::line::LineWithComment;
3use crate::{InlineBlockCommentToken, ParseContainer, ParseResult, wr, wr2};
4use nom::character::complete::space0;
5use nom::combinator::map;
6use nom::{IResult, Parser};
7
8/// A token sequence that is a line containing a [`HeaderToken`]. (like `"\theader EXAMPLE HEADER  \n"`.)
9///
10/// # Examples
11///
12/// ```
13/// use plantuml_parser::{HeaderLine, ParseContainer};
14///
15/// # fn main() -> anyhow::Result<()> {
16/// let input = " header EXAMPLE HEADER\n";
17/// let (rest, (raws, token)) = HeaderLine::parse(input.into())?;
18/// let combined_raw: ParseContainer = raws.into();
19/// assert_eq!(rest, "");
20/// assert_eq!(combined_raw, " header EXAMPLE HEADER\n");
21/// assert_eq!(token.header(), "EXAMPLE HEADER");
22/// # Ok(())
23/// # }
24/// ```
25#[derive(Clone, Debug)]
26pub struct HeaderLine {
27    token: HeaderToken,
28    ibc: Option<InlineBlockCommentToken>,
29}
30
31impl HeaderLine {
32    /// Tries to parse [`HeaderLine`]. (e.g. `" header EXAMPLE HEADER\n"`.)
33    pub fn parse(input: ParseContainer) -> ParseResult<Self> {
34        let (rest, (parsed, lwc)) = LineWithComment::parse(inner_parser, input)?;
35
36        let (token, ibc) = lwc.into();
37
38        let ret0 = ParseContainer::from(parsed);
39        let ret1 = Self { token, ibc };
40
41        Ok((rest, (ret0, ret1)))
42    }
43
44    pub fn inline_block_comment(&self) -> Option<&InlineBlockCommentToken> {
45        self.ibc.as_ref()
46    }
47}
48
49impl std::ops::Deref for HeaderLine {
50    type Target = HeaderToken;
51    fn deref(&self) -> &Self::Target {
52        &self.token
53    }
54}
55
56fn inner_parser(
57    input: ParseContainer,
58) -> IResult<ParseContainer, (Vec<ParseContainer>, HeaderToken)> {
59    map(
60        (wr!(space0), wr2!(HeaderToken::parse), wr!(space0)),
61        |(p0, (p1, token), p2)| (vec![p0, p1, p2], token),
62    )
63    .parse(input)
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_parse_header_line() -> anyhow::Result<()> {
72        let testdata = [
73            ("header HEADER\n", None),
74            (" \theader HEADER\n", None),
75            ("header HEADER \t\n", None),
76            (" \theader HEADER \t\n", None),
77            ("Header HEADER\n", None),
78            ("HEADER HEADER\n", None),
79            ("heaDer HEADER\n", None),
80            (" /' comment '/ header HEADER\n", Some(" /' comment '/ ")),
81            ("header HEADER /' comment '/ \n", Some("/' comment '/ ")),
82        ];
83
84        for (testdata, expected_comment) in testdata.into_iter() {
85            let (rest, (parsed, HeaderLine { token, ibc })) = HeaderLine::parse(testdata.into())?;
86            assert_eq!(rest, "");
87            assert_eq!(testdata, parsed);
88            assert_eq!(token.header(), "HEADER");
89            assert_eq!(ibc.as_ref().map(|x| x.comment()), expected_comment);
90        }
91
92        Ok(())
93    }
94}