1//! Iterators over a Catalog.
2
3use crate::catalog::Catalog;
4use crate::message::{
5 CatalogMessageMutView, Message, MessageFlags, MessageKey, MessageMutView, MessageView,
6 SingularPluralMismatchError,
7};
8
9pub struct CatalogMessageRef<C> {
10 catalog: C,
11 index: usize,
12}
13
14impl<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.
25pub struct Iter<'a>(CatalogMessageRef<&'a Catalog>);
26
27impl<'a> Iter<'a> {
28 pub(crate) fn begin(catalog: &'a Catalog) -> Self {
29 Self(CatalogMessageRef::begin(catalog))
30 }
31}
32
33impl<'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.
50pub struct IterMut<'a>(CatalogMessageRef<&'a mut Catalog>);
51
52impl<'a> IterMut<'a> {
53 pub(crate) fn begin(catalog: &'a mut Catalog) -> Self {
54 Self(CatalogMessageRef::begin(catalog))
55 }
56}
57
58impl<'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.
81pub struct MessageMutProxy<'a>(CatalogMessageRef<&'a mut Catalog>);
82
83impl<'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
97impl<'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
147impl<'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
214impl<'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