1 | //! Defines `MessageFlags` struct. |
2 | |
3 | use std::fmt::{Display, Formatter}; |
4 | use std::str::FromStr; |
5 | |
6 | /// Represents the set of flags in a message |
7 | #[derive (Debug, Clone)] |
8 | pub struct MessageFlags { |
9 | /// Vector of individual flags |
10 | pub entries: Vec<String>, |
11 | } |
12 | |
13 | impl Default for MessageFlags { |
14 | fn default() -> Self { |
15 | Self::new() |
16 | } |
17 | } |
18 | |
19 | impl 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 | |
35 | impl 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 | |
45 | impl 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)] |
98 | mod 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 | |