mit_commit/
comment.rs

1use std::borrow::Cow;
2
3const LEGAL_CHARACTERS: [char; 10] = ['#', ';', '@', '!', '$', '%', '^', '&', '|', ':'];
4
5/// A single comment from a `CommitMessage`
6#[derive(Debug, PartialEq, Eq, Clone)]
7pub struct Comment<'a> {
8    comment: Cow<'a, str>,
9}
10
11impl Comment<'_> {
12    /// Append one [`Comment`] onto another
13    ///
14    /// # Arguments
15    ///
16    /// * `additional` - The comment to append to this one
17    ///
18    /// # Returns
19    ///
20    /// A new comment with the content of both comments separated by a newline
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use indoc::indoc;
26    /// use mit_commit::Comment;
27    ///
28    /// assert_eq!(
29    ///     Comment::from(indoc!(
30    ///         "
31    ///         Example 1
32    ///         Example 2"
33    ///     )),
34    ///     Comment::from("Example 1").append(&Comment::from("Example 2"))
35    /// )
36    /// ```
37    #[must_use]
38    pub fn append(&self, additional: &Self) -> Self {
39        Self::from(format!("{}\n{}", self.comment, additional.comment))
40    }
41
42    /// Checks if a given character is a valid comment character
43    ///
44    /// # Arguments
45    ///
46    /// * `character` - The character to check
47    ///
48    /// # Returns
49    ///
50    /// `true` if the character is a valid comment character, `false` otherwise
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// use mit_commit::Comment;
56    ///
57    /// assert!(!Comment::is_legal_comment_char('?'));
58    /// assert!(Comment::is_legal_comment_char('#'));
59    /// ```
60    #[must_use]
61    pub fn is_legal_comment_char(character: char) -> bool {
62        LEGAL_CHARACTERS.contains(&character)
63    }
64}
65
66impl<'a> From<Cow<'a, str>> for Comment<'a> {
67    /// Create a Comment from a Cow<_, str>
68    ///
69    /// # Arguments
70    ///
71    /// * `comment` - The string content to create the comment from
72    ///
73    /// # Returns
74    ///
75    /// A new Comment containing the provided string
76    fn from(comment: Cow<'a, str>) -> Self {
77        Self { comment }
78    }
79}
80
81impl From<String> for Comment<'_> {
82    /// Create a Comment from a String
83    ///
84    /// # Arguments
85    ///
86    /// * `comment` - The string to create the comment from
87    ///
88    /// # Returns
89    ///
90    /// A new Comment containing the provided string
91    fn from(comment: String) -> Self {
92        Self {
93            comment: comment.into(),
94        }
95    }
96}
97
98impl<'a> From<&'a str> for Comment<'a> {
99    /// Create a Comment from a string slice
100    ///
101    /// # Arguments
102    ///
103    /// * `comment` - The string slice to create the comment from
104    ///
105    /// # Returns
106    ///
107    /// A new Comment containing the provided string
108    fn from(comment: &'a str) -> Self {
109        Self {
110            comment: comment.into(),
111        }
112    }
113}
114
115impl<'a> From<Comment<'a>> for String {
116    /// Convert a Comment to a String
117    ///
118    /// # Arguments
119    ///
120    /// * `comment` - The comment to convert
121    ///
122    /// # Returns
123    ///
124    /// A String containing the comment's text
125    fn from(comment: Comment<'a>) -> Self {
126        comment.comment.into()
127    }
128}
129
130#[cfg(test)]
131mod tests {
132    use indoc::indoc;
133
134    use super::*;
135
136    #[test]
137    fn test_creation_from_str() {
138        let comment = Comment::from("# Example Comment");
139
140        assert_eq!(
141            String::from(comment),
142            String::from("# Example Comment"),
143            "Comment should convert to the correct string when created from a str"
144        );
145    }
146
147    #[test]
148    fn test_creation_from_string() {
149        let comment = Comment::from(String::from("# Example Comment"));
150
151        assert_eq!(
152            String::from(comment),
153            String::from("# Example Comment"),
154            "Comment should convert to the correct string when created from a String"
155        );
156    }
157
158    #[test]
159    fn test_legal_comment_char_detection() {
160        assert!(
161            Comment::is_legal_comment_char('#'),
162            "# should be recognized as a legal comment character"
163        );
164    }
165
166    #[test]
167    fn test_illegal_comment_char_detection() {
168        assert!(
169            !Comment::is_legal_comment_char('?'),
170            "? should not be recognized as a legal comment character"
171        );
172    }
173
174    #[test]
175    fn test_append_comment_fragments() {
176        assert_eq!(
177            Comment::from(indoc!(
178                "
179                Example 1
180                Example 2"
181            )),
182            Comment::from("Example 1").append(&Comment::from("Example 2")),
183            "Appending comments should create a new comment with content separated by newline"
184        );
185    }
186}