1//! Defines `MessageFlags` struct.
2
3use std::fmt::{Display, Formatter};
4use std::str::FromStr;
5
6/// Represents the set of flags in a message
7#[derive(Debug, Clone)]
8pub struct MessageFlags {
9 /// Vector of individual flags
10 pub entries: Vec<String>,
11}
12
13impl Default for MessageFlags {
14 fn default() -> Self {
15 Self::new()
16 }
17}
18
19impl FromStr for MessageFlags {
20 type Err = ();
21
22 fn from_str(s: &str) -> Result<Self, Self::Err> {
23 let flags: String = s.replace(from:'\n', to:"");
24 let segments: Split<'_, char> = flags.split(',');
25 let mut result: MessageFlags = Self::new();
26 for x: &str in segments {
27 if !x.is_empty() {
28 result.entries.push(String::from(x.trim()));
29 }
30 }
31 Ok(result)
32 }
33}
34
35impl Display for MessageFlags {
36 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37 if self.is_empty() {
38 write!(f, "")
39 } else {
40 write!(f, "{}", self.entries.join(", "))
41 }
42 }
43}
44
45impl MessageFlags {
46 /// Create an empty set of flags
47 pub fn new() -> Self {
48 MessageFlags { entries: vec![] }
49 }
50
51 /// Count number of flags
52 pub fn count(&self) -> usize {
53 self.entries.len()
54 }
55
56 /// Is the set of flags empty?
57 pub fn is_empty(&self) -> bool {
58 self.entries.is_empty()
59 }
60
61 /// Is a flag present?
62 pub fn contains(&self, flag: &str) -> bool {
63 let flag = flag.to_string();
64 self.entries.contains(&flag)
65 }
66
67 /// Is fuzzy flag present?
68 pub fn is_fuzzy(&self) -> bool {
69 self.contains("fuzzy")
70 }
71
72 /// Add a flag.
73 pub fn add_flag(&mut self, flag: &str) {
74 if !self.contains(flag) {
75 self.entries.push(flag.to_string());
76 }
77 }
78
79 /// Remove a flag.
80 pub fn remove_flag(&mut self, flag: &str) {
81 if let Some(index) = self.entries.iter().position(|x| *x == flag) {
82 self.entries.remove(index);
83 }
84 }
85
86 /// Get an immutable iterator over flags.
87 pub fn iter(&self) -> std::slice::Iter<String> {
88 self.entries.iter()
89 }
90
91 /// Get a mutable iterator over flags.
92 pub fn iter_mut(&mut self) -> std::slice::IterMut<String> {
93 self.entries.iter_mut()
94 }
95}
96
97#[cfg(test)]
98mod test {
99 use crate::message::MessageFlags;
100 use std::str::FromStr;
101
102 #[test]
103 fn test_flags_from_string() {
104 assert_eq!(
105 MessageFlags::from_str("").unwrap().entries,
106 Vec::<String>::new()
107 );
108 assert_eq!(
109 MessageFlags::from_str("fuzzy").unwrap().entries,
110 vec!["fuzzy"]
111 );
112 assert_eq!(
113 MessageFlags::from_str("c-format, fuzzy").unwrap().entries,
114 vec!["c-format", "fuzzy"]
115 );
116 }
117
118 #[test]
119 fn test_flags_to_string() {
120 assert_eq!(MessageFlags { entries: vec![] }.to_string(), "");
121 assert_eq!(
122 MessageFlags {
123 entries: vec![String::from("fuzzy")]
124 }
125 .to_string(),
126 "fuzzy"
127 );
128 assert_eq!(
129 MessageFlags {
130 entries: vec![String::from("c-format"), String::from("fuzzy")]
131 }
132 .to_string(),
133 "c-format, fuzzy"
134 );
135 }
136}
137