dialogue_rs/script/
comment.rs

1//! # Comments
2//!
3//! Comments start with a `//` and continue until the end of the line. They can be used to annotate a script.
4//!
5//! ```text
6//! // This is a comment
7//! ```
8
9use crate::script::parser::{Parser, Rule};
10use anyhow::bail;
11use pest::iterators::Pair;
12use pest::Parser as PestParser;
13use std::fmt;
14
15/// A comment in a script.
16#[derive(Debug, PartialEq, Eq, Clone)]
17pub struct Comment {
18    text: String,
19}
20
21impl fmt::Display for Comment {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        writeln!(f, "// {}", self.text)
24    }
25}
26
27impl Comment {
28    /// Create a new [Comment] from a string.
29    pub fn new(text: String) -> Self {
30        Self { text }
31    }
32
33    /// Parse a [Comment] from a string.
34    pub fn parse(comment_str: &str) -> Result<Self, anyhow::Error> {
35        let mut pairs = Parser::parse(Rule::Comment, comment_str)?;
36        let pair = pairs.next().expect("a pair exists");
37        assert_eq!(pairs.next(), None);
38
39        pair.try_into()
40    }
41}
42
43impl TryFrom<Pair<'_, Rule>> for Comment {
44    type Error = anyhow::Error;
45
46    fn try_from(pair: Pair<'_, Rule>) -> Result<Self, Self::Error> {
47        match pair.as_rule() {
48            Rule::Comment => {
49                let mut inner_pairs = pair.into_inner();
50                let pair = inner_pairs.next().expect("a pair exists");
51                assert!(inner_pairs.next().is_none(), "no other pairs exist");
52                let text = pair.as_str().trim().to_owned();
53
54                Ok(Self::new(text))
55            }
56            _ => bail!("Pair is not a comment: {:#?}", pair),
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::Comment;
64
65    #[test]
66    fn test_comment_parse() {
67        let comment = Comment::parse("// This is a comment\n").unwrap();
68        assert_eq!(comment.text, "This is a comment");
69    }
70
71    #[test]
72    fn test_round_trip() {
73        let input = "// This is a comment\n";
74        let output = Comment::parse(input).unwrap().to_string();
75        assert_eq!(input, output);
76    }
77}