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}