plantuml_parser/dsl/line/
end.rs

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