1 | //! Defines `MessageView` trait. |
2 | |
3 | use std::borrow::{Borrow, ToOwned}; |
4 | use std::error::Error; |
5 | use std::fmt::{Display, Formatter}; |
6 | |
7 | use crate::message::{Message, MessageFlags}; |
8 | |
9 | /// Error type when trying to access a field that is not applicable to the plural type of the message. |
10 | #[derive (Debug)] |
11 | pub struct SingularPluralMismatchError; |
12 | |
13 | impl Display for SingularPluralMismatchError { |
14 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
15 | write!(f, "singular/plural type mismatch" ) |
16 | } |
17 | } |
18 | |
19 | impl Error for SingularPluralMismatchError {} |
20 | |
21 | /// Immutable view of a `Message`. |
22 | pub trait MessageView { |
23 | /// Is this message singular? |
24 | fn is_singular(&self) -> bool; |
25 | |
26 | /// Is this message plural? |
27 | fn is_plural(&self) -> bool; |
28 | |
29 | /// Is this message translated? |
30 | fn is_translated(&self) -> bool; |
31 | |
32 | /// Is this message fuzzy? |
33 | fn is_fuzzy(&self) -> bool; |
34 | |
35 | /// Get comments field of the message. |
36 | fn comments(&self) -> &str; |
37 | |
38 | /// Get source code location field of the message. |
39 | fn source(&self) -> &str; |
40 | |
41 | /// Get flags field of the message. |
42 | fn flags(&self) -> &MessageFlags; |
43 | |
44 | /// Get context field of the message. |
45 | fn msgctxt(&self) -> &str; |
46 | |
47 | /// Get msgid field of the message. |
48 | fn msgid(&self) -> &str; |
49 | |
50 | /// Get msgid_plural field of the message, or error if this is not a plural message. |
51 | fn msgid_plural(&self) -> Result<&str, SingularPluralMismatchError>; |
52 | |
53 | /// Get msgstr field of the message, or error if this is not a singular message. |
54 | fn msgstr(&self) -> Result<&str, SingularPluralMismatchError>; |
55 | |
56 | /// Get msgstr_plural field of the message, or error if this is not a plural message. |
57 | fn msgstr_plural(&self) -> Result<&Vec<String>, SingularPluralMismatchError>; |
58 | } |
59 | |
60 | /// Mutable view of a `Message`. |
61 | pub trait MessageMutView: MessageView { |
62 | /// Get a mutable reference to the comments field of the message. |
63 | fn comments_mut(&mut self) -> &mut String; |
64 | |
65 | /// Get a mutable reference to the source code location field of the message. |
66 | fn source_mut(&mut self) -> &mut String; |
67 | |
68 | /// Get a mutable reference to the flags field of the message. |
69 | fn flags_mut(&mut self) -> &mut MessageFlags; |
70 | |
71 | /// Set the context field of the message. |
72 | fn set_msgctxt(&mut self, msgctxt: String); |
73 | |
74 | /// Set the msgid field of the message. |
75 | fn set_msgid(&mut self, msgid: String); |
76 | |
77 | /// Set the msgid_plural field of the message, or error if this is not a plural message. |
78 | fn set_msgid_plural(&mut self, msgid_plural: String) |
79 | -> Result<(), SingularPluralMismatchError>; |
80 | |
81 | /// Set the msgstr field of the message, or error if this is not a singular message. |
82 | fn set_msgstr(&mut self, msgstr: String) -> Result<(), SingularPluralMismatchError>; |
83 | |
84 | /// Get a mutable reference to the msgstr field of the message, or error if this is not a singular message. |
85 | fn msgstr_mut(&mut self) -> Result<&mut String, SingularPluralMismatchError>; |
86 | |
87 | /// Get a mutable reference to the msgstr_plural field of the message, or error if this is not a plural message. |
88 | fn msgstr_plural_mut(&mut self) -> Result<&mut Vec<String>, SingularPluralMismatchError>; |
89 | } |
90 | |
91 | /// Mutable view of a `Message` that is part of a catalog. |
92 | pub trait CatalogMessageMutView: MessageMutView { |
93 | /// Delete this message from the catalog. |
94 | /// It is undefined behavior to continue access the message object through this proxy afterwards. |
95 | fn delete(&mut self); |
96 | |
97 | /// Detach this message from the catalog and get the message object back. |
98 | /// It is undefined behavior to continue access the message object through this proxy afterwards. |
99 | fn detach(&mut self) -> Message; |
100 | } |
101 | |
102 | impl MessageView for Message { |
103 | fn is_singular(&self) -> bool { |
104 | !self.is_plural |
105 | } |
106 | |
107 | fn is_plural(&self) -> bool { |
108 | self.is_plural |
109 | } |
110 | |
111 | fn is_translated(&self) -> bool { |
112 | if self.is_plural { |
113 | self.msgstr_plural.iter().all(|x| !x.is_empty()) |
114 | } else { |
115 | !self.msgstr.is_empty() |
116 | } |
117 | } |
118 | |
119 | fn is_fuzzy(&self) -> bool { |
120 | self.flags.is_fuzzy() |
121 | } |
122 | |
123 | fn comments(&self) -> &str { |
124 | &self.comments |
125 | } |
126 | |
127 | fn source(&self) -> &str { |
128 | &self.source |
129 | } |
130 | |
131 | fn flags(&self) -> &MessageFlags { |
132 | &self.flags |
133 | } |
134 | |
135 | fn msgctxt(&self) -> &str { |
136 | &self.msgctxt |
137 | } |
138 | |
139 | fn msgid(&self) -> &str { |
140 | &self.msgid |
141 | } |
142 | |
143 | fn msgid_plural(&self) -> Result<&str, SingularPluralMismatchError> { |
144 | if self.is_plural { |
145 | Ok(&self.msgid_plural) |
146 | } else { |
147 | Err(SingularPluralMismatchError) |
148 | } |
149 | } |
150 | |
151 | fn msgstr(&self) -> Result<&str, SingularPluralMismatchError> { |
152 | if self.is_plural { |
153 | Err(SingularPluralMismatchError) |
154 | } else { |
155 | Ok(&self.msgstr) |
156 | } |
157 | } |
158 | |
159 | fn msgstr_plural(&self) -> Result<&Vec<String>, SingularPluralMismatchError> { |
160 | if self.is_plural { |
161 | Ok(&self.msgstr_plural) |
162 | } else { |
163 | Err(SingularPluralMismatchError) |
164 | } |
165 | } |
166 | } |
167 | |
168 | impl MessageMutView for Message { |
169 | fn comments_mut(&mut self) -> &mut String { |
170 | &mut self.comments |
171 | } |
172 | |
173 | fn source_mut(&mut self) -> &mut String { |
174 | &mut self.source |
175 | } |
176 | |
177 | fn flags_mut(&mut self) -> &mut MessageFlags { |
178 | &mut self.flags |
179 | } |
180 | |
181 | fn set_msgctxt(&mut self, msgctxt: String) { |
182 | self.msgctxt = msgctxt |
183 | } |
184 | |
185 | fn set_msgid(&mut self, msgid: String) { |
186 | self.msgid = msgid |
187 | } |
188 | |
189 | fn set_msgid_plural( |
190 | &mut self, |
191 | msgid_plural: String, |
192 | ) -> Result<(), SingularPluralMismatchError> { |
193 | if self.is_plural() { |
194 | self.msgid_plural = msgid_plural; |
195 | Ok(()) |
196 | } else { |
197 | Err(SingularPluralMismatchError) |
198 | } |
199 | } |
200 | |
201 | fn set_msgstr(&mut self, msgstr: String) -> Result<(), SingularPluralMismatchError> { |
202 | if self.is_singular() { |
203 | self.msgstr = msgstr; |
204 | Ok(()) |
205 | } else { |
206 | Err(SingularPluralMismatchError) |
207 | } |
208 | } |
209 | |
210 | fn msgstr_mut(&mut self) -> Result<&mut String, SingularPluralMismatchError> { |
211 | if self.is_singular() { |
212 | Ok(&mut self.msgstr) |
213 | } else { |
214 | Err(SingularPluralMismatchError) |
215 | } |
216 | } |
217 | |
218 | fn msgstr_plural_mut(&mut self) -> Result<&mut Vec<String>, SingularPluralMismatchError> { |
219 | if self.is_plural() { |
220 | Ok(&mut self.msgstr_plural) |
221 | } else { |
222 | Err(SingularPluralMismatchError) |
223 | } |
224 | } |
225 | } |
226 | |
227 | impl<'a> Borrow<dyn MessageView + 'a> for Message { |
228 | fn borrow(&self) -> &(dyn MessageView + 'a) { |
229 | self |
230 | } |
231 | } |
232 | |
233 | impl ToOwned for dyn MessageView { |
234 | type Owned = Message; |
235 | |
236 | fn to_owned(&self) -> Self::Owned { |
237 | if self.is_singular() { |
238 | Self::Owned { |
239 | comments: self.comments().to_string(), |
240 | source: self.source().to_string(), |
241 | flags: self.flags().clone(), |
242 | msgctxt: self.msgctxt().to_string(), |
243 | msgid: self.msgid().to_string(), |
244 | msgid_plural: String::default(), |
245 | msgstr: self.msgstr().unwrap().to_string(), |
246 | msgstr_plural: vec![], |
247 | is_plural: false, |
248 | } |
249 | } else { |
250 | Self::Owned { |
251 | comments: self.comments().to_string(), |
252 | source: self.source().to_string(), |
253 | flags: self.flags().clone(), |
254 | msgctxt: self.msgctxt().to_string(), |
255 | msgid: self.msgid().to_string(), |
256 | msgid_plural: self.msgid_plural().unwrap().to_string(), |
257 | msgstr: String::default(), |
258 | msgstr_plural: self.msgstr_plural().unwrap().to_owned(), |
259 | is_plural: true, |
260 | } |
261 | } |
262 | } |
263 | } |
264 | |