1 | //! Iterators over a Catalog. |
2 | |
3 | use crate::catalog::Catalog; |
4 | use crate::message::{ |
5 | CatalogMessageMutView, Message, MessageFlags, MessageKey, MessageMutView, MessageView, |
6 | SingularPluralMismatchError, |
7 | }; |
8 | |
9 | pub struct CatalogMessageRef<C> { |
10 | catalog: C, |
11 | index: usize, |
12 | } |
13 | |
14 | impl<C> CatalogMessageRef<C> { |
15 | fn begin(catalog: C) -> Self { |
16 | Self { catalog, index: 0 } |
17 | } |
18 | |
19 | fn at(catalog: C, index: usize) -> Self { |
20 | Self { catalog, index } |
21 | } |
22 | } |
23 | |
24 | /// An immutable iterator over messages in a catalog. |
25 | pub struct Iter<'a>(CatalogMessageRef<&'a Catalog>); |
26 | |
27 | impl<'a> Iter<'a> { |
28 | pub(crate) fn begin(catalog: &'a Catalog) -> Self { |
29 | Self(CatalogMessageRef::begin(catalog)) |
30 | } |
31 | } |
32 | |
33 | impl<'a> Iterator for Iter<'a> { |
34 | type Item = &'a dyn MessageView; |
35 | |
36 | fn next(&mut self) -> Option<Self::Item> { |
37 | while self.0.index < self.0.catalog.messages.len() { |
38 | if let Some(m: &Message) = self.0.catalog.messages[self.0.index].as_ref() { |
39 | self.0.index += 1; |
40 | return Some(m); |
41 | } else { |
42 | self.0.index += 1 |
43 | } |
44 | } |
45 | None |
46 | } |
47 | } |
48 | |
49 | /// A mutable iterator over messages in a catalog that allows mutating a message in-place. |
50 | pub struct IterMut<'a>(CatalogMessageRef<&'a mut Catalog>); |
51 | |
52 | impl<'a> IterMut<'a> { |
53 | pub(crate) fn begin(catalog: &'a mut Catalog) -> Self { |
54 | Self(CatalogMessageRef::begin(catalog)) |
55 | } |
56 | } |
57 | |
58 | impl<'a> Iterator for IterMut<'a> { |
59 | type Item = MessageMutProxy<'a>; |
60 | |
61 | fn next(&mut self) -> Option<Self::Item> { |
62 | while self.0.index < self.0.catalog.messages.len() { |
63 | if self.0.catalog.messages[self.0.index].is_some() { |
64 | let current_index: usize = self.0.index; |
65 | self.0.index += 1; |
66 | return Some(MessageMutProxy::at( |
67 | catalog:unsafe { &mut *(self.0.catalog as *mut Catalog) }, |
68 | current_index, |
69 | )); |
70 | } else { |
71 | self.0.index += 1; |
72 | } |
73 | } |
74 | None |
75 | } |
76 | } |
77 | |
78 | /// Proxy object for mutating a message that belongs to a catalog. |
79 | /// Mutating a message in a catalog has to go through this proxy object, otherwise modifying data |
80 | /// directly on the `Message` object may cause internal data inconsistencies in the catalog. |
81 | pub struct MessageMutProxy<'a>(CatalogMessageRef<&'a mut Catalog>); |
82 | |
83 | impl<'a> MessageMutProxy<'a> { |
84 | pub(crate) fn at(catalog: &'a mut Catalog, index: usize) -> Self { |
85 | Self(CatalogMessageRef::at(catalog, index)) |
86 | } |
87 | |
88 | fn message(&self) -> &Message { |
89 | self.0.catalog.messages[self.0.index].as_ref().unwrap() |
90 | } |
91 | |
92 | fn message_mut(&mut self) -> &mut Message { |
93 | self.0.catalog.messages[self.0.index].as_mut().unwrap() |
94 | } |
95 | } |
96 | |
97 | impl<'a> MessageView for MessageMutProxy<'a> { |
98 | fn is_singular(&self) -> bool { |
99 | self.message().is_singular() |
100 | } |
101 | |
102 | fn is_plural(&self) -> bool { |
103 | self.message().is_plural() |
104 | } |
105 | |
106 | fn is_translated(&self) -> bool { |
107 | self.message().is_translated() |
108 | } |
109 | |
110 | fn is_fuzzy(&self) -> bool { |
111 | self.message().is_fuzzy() |
112 | } |
113 | |
114 | fn comments(&self) -> &str { |
115 | self.message().comments() |
116 | } |
117 | |
118 | fn source(&self) -> &str { |
119 | self.message().source() |
120 | } |
121 | |
122 | fn flags(&self) -> &MessageFlags { |
123 | self.message().flags() |
124 | } |
125 | |
126 | fn msgctxt(&self) -> &str { |
127 | self.message().msgctxt() |
128 | } |
129 | |
130 | fn msgid(&self) -> &str { |
131 | self.message().msgid() |
132 | } |
133 | |
134 | fn msgid_plural(&self) -> Result<&str, SingularPluralMismatchError> { |
135 | self.message().msgid_plural() |
136 | } |
137 | |
138 | fn msgstr(&self) -> Result<&str, SingularPluralMismatchError> { |
139 | self.message().msgstr() |
140 | } |
141 | |
142 | fn msgstr_plural(&self) -> Result<&Vec<String>, SingularPluralMismatchError> { |
143 | self.message().msgstr_plural() |
144 | } |
145 | } |
146 | |
147 | impl<'a> MessageMutView for MessageMutProxy<'a> { |
148 | fn comments_mut(&mut self) -> &mut String { |
149 | &mut self.message_mut().comments |
150 | } |
151 | |
152 | fn source_mut(&mut self) -> &mut String { |
153 | &mut self.message_mut().source |
154 | } |
155 | |
156 | fn flags_mut(&mut self) -> &mut MessageFlags { |
157 | &mut self.message_mut().flags |
158 | } |
159 | |
160 | fn set_msgctxt(&mut self, msgctxt: String) { |
161 | let original_key = MessageKey::from(self.message()); |
162 | self.0.catalog.map.remove(&original_key); |
163 | self.message_mut().msgctxt = msgctxt; |
164 | let new_key = MessageKey::from(self.message()); |
165 | self.0.catalog.map.insert(new_key, self.0.index); |
166 | } |
167 | |
168 | fn set_msgid(&mut self, msgid: String) { |
169 | let original_key = MessageKey::from(self.message()); |
170 | self.0.catalog.map.remove(&original_key); |
171 | self.message_mut().msgctxt = msgid; |
172 | let new_key = MessageKey::from(self.message()); |
173 | self.0.catalog.map.insert(new_key, self.0.index); |
174 | } |
175 | |
176 | fn set_msgid_plural( |
177 | &mut self, |
178 | msgid_plural: String, |
179 | ) -> Result<(), SingularPluralMismatchError> { |
180 | if self.message_mut().is_plural() { |
181 | self.message_mut().msgid_plural = msgid_plural; |
182 | Ok(()) |
183 | } else { |
184 | Err(SingularPluralMismatchError) |
185 | } |
186 | } |
187 | |
188 | fn set_msgstr(&mut self, msgstr: String) -> Result<(), SingularPluralMismatchError> { |
189 | if self.message_mut().is_plural() { |
190 | Err(SingularPluralMismatchError) |
191 | } else { |
192 | self.message_mut().msgstr = msgstr; |
193 | Ok(()) |
194 | } |
195 | } |
196 | |
197 | fn msgstr_mut(&mut self) -> Result<&mut String, SingularPluralMismatchError> { |
198 | if self.message_mut().is_plural() { |
199 | Err(SingularPluralMismatchError) |
200 | } else { |
201 | Ok(&mut self.message_mut().msgstr) |
202 | } |
203 | } |
204 | |
205 | fn msgstr_plural_mut(&mut self) -> Result<&mut Vec<String>, SingularPluralMismatchError> { |
206 | if self.message_mut().is_plural() { |
207 | Ok(&mut self.message_mut().msgstr_plural) |
208 | } else { |
209 | Err(SingularPluralMismatchError) |
210 | } |
211 | } |
212 | } |
213 | |
214 | impl<'a> CatalogMessageMutView for MessageMutProxy<'a> { |
215 | fn delete(&mut self) { |
216 | let key: MessageKey = MessageKey::from(self.message()); |
217 | self.0.catalog.map.remove(&key); |
218 | self.0.catalog.messages[self.0.index] = None; |
219 | } |
220 | |
221 | fn detach(&mut self) -> Message { |
222 | let key: MessageKey = MessageKey::from(self.message()); |
223 | self.0.catalog.map.remove(&key); |
224 | self.0.catalog.messages[self.0.index].take().unwrap() |
225 | } |
226 | } |
227 | |