1 | // This file is part of ICU4X. For terms of use, please see the file |
2 | // called LICENSE at the top level of the ICU4X source tree |
3 | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | |
5 | use super::ForkByErrorPredicate; |
6 | use alloc::vec::Vec; |
7 | #[cfg (feature = "datagen" )] |
8 | use icu_provider::datagen; |
9 | use icu_provider::prelude::*; |
10 | |
11 | /// A provider that returns data from one of two child providers based on a predicate function. |
12 | /// |
13 | /// This is an abstract forking provider that must be provided with a type implementing the |
14 | /// [`ForkByErrorPredicate`] trait. |
15 | /// |
16 | /// [`ForkByErrorProvider`] does not support forking between [`DataProvider`]s. However, it |
17 | /// supports forking between [`AnyProvider`], [`BufferProvider`], and [`DynamicDataProvider`]. |
18 | #[derive (Debug, PartialEq, Eq)] |
19 | pub struct ForkByErrorProvider<P0, P1, F>(P0, P1, F); |
20 | |
21 | impl<P0, P1, F> ForkByErrorProvider<P0, P1, F> { |
22 | /// Create a new provider that forks between the two children. |
23 | /// |
24 | /// The `predicate` argument should be an instance of a struct implementing |
25 | /// [`ForkByErrorPredicate`]. |
26 | pub fn new_with_predicate(p0: P0, p1: P1, predicate: F) -> Self { |
27 | Self(p0, p1, predicate) |
28 | } |
29 | |
30 | /// Returns references to the inner providers. |
31 | pub fn inner(&self) -> (&P0, &P1) { |
32 | (&self.0, &self.1) |
33 | } |
34 | |
35 | /// Returns mutable references to the inner providers. |
36 | pub fn inner_mut(&mut self) -> (&mut P0, &mut P1) { |
37 | (&mut self.0, &mut self.1) |
38 | } |
39 | |
40 | /// Returns ownership of the inner providers to the caller. |
41 | pub fn into_inner(self) -> (P0, P1) { |
42 | (self.0, self.1) |
43 | } |
44 | } |
45 | |
46 | impl<P0, P1, F> BufferProvider for ForkByErrorProvider<P0, P1, F> |
47 | where |
48 | P0: BufferProvider, |
49 | P1: BufferProvider, |
50 | F: ForkByErrorPredicate, |
51 | { |
52 | fn load_buffer( |
53 | &self, |
54 | key: DataKey, |
55 | req: DataRequest, |
56 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
57 | let result: Result, …> = self.0.load_buffer(key, req); |
58 | match result { |
59 | Ok(ok: DataResponse) => return Ok(ok), |
60 | Err(err: DataError) if !self.2.test(key, req:Some(req), err) => return Err(err), |
61 | _ => (), |
62 | }; |
63 | self.1.load_buffer(key, req) |
64 | } |
65 | } |
66 | |
67 | impl<P0, P1, F> AnyProvider for ForkByErrorProvider<P0, P1, F> |
68 | where |
69 | P0: AnyProvider, |
70 | P1: AnyProvider, |
71 | F: ForkByErrorPredicate, |
72 | { |
73 | fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> { |
74 | let result: Result = self.0.load_any(key, req); |
75 | match result { |
76 | Ok(ok: AnyResponse) => return Ok(ok), |
77 | Err(err: DataError) if !self.2.test(key, req:Some(req), err) => return Err(err), |
78 | _ => (), |
79 | }; |
80 | self.1.load_any(key, req) |
81 | } |
82 | } |
83 | |
84 | impl<M, P0, P1, F> DynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F> |
85 | where |
86 | M: DataMarker, |
87 | P0: DynamicDataProvider<M>, |
88 | P1: DynamicDataProvider<M>, |
89 | F: ForkByErrorPredicate, |
90 | { |
91 | fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> { |
92 | let result: Result, DataError> = self.0.load_data(key, req); |
93 | match result { |
94 | Ok(ok: DataResponse) => return Ok(ok), |
95 | Err(err: DataError) if !self.2.test(key, req:Some(req), err) => return Err(err), |
96 | _ => (), |
97 | }; |
98 | self.1.load_data(key, req) |
99 | } |
100 | } |
101 | |
102 | #[cfg (feature = "datagen" )] |
103 | impl<M, P0, P1, F> datagen::IterableDynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F> |
104 | where |
105 | M: DataMarker, |
106 | P0: datagen::IterableDynamicDataProvider<M>, |
107 | P1: datagen::IterableDynamicDataProvider<M>, |
108 | F: ForkByErrorPredicate, |
109 | { |
110 | fn supported_locales_for_key(&self, key: DataKey) -> Result<Vec<DataLocale>, DataError> { |
111 | let result = self.0.supported_locales_for_key(key); |
112 | match result { |
113 | Ok(ok) => return Ok(ok), |
114 | Err(err) if !self.2.test(key, None, err) => return Err(err), |
115 | _ => (), |
116 | }; |
117 | self.1.supported_locales_for_key(key) |
118 | } |
119 | } |
120 | |
121 | /// A provider that returns data from the first child provider passing a predicate function. |
122 | /// |
123 | /// This is an abstract forking provider that must be provided with a type implementing the |
124 | /// [`ForkByErrorPredicate`] trait. |
125 | /// |
126 | /// [`MultiForkByErrorProvider`] does not support forking between [`DataProvider`]s. However, it |
127 | /// supports forking between [`AnyProvider`], [`BufferProvider`], and [`DynamicDataProvider`]. |
128 | #[derive (Debug)] |
129 | pub struct MultiForkByErrorProvider<P, F> { |
130 | providers: Vec<P>, |
131 | predicate: F, |
132 | } |
133 | |
134 | impl<P, F> MultiForkByErrorProvider<P, F> { |
135 | /// Create a new provider that forks between the vector of children. |
136 | /// |
137 | /// The `predicate` argument should be an instance of a struct implementing |
138 | /// [`ForkByErrorPredicate`]. |
139 | pub fn new_with_predicate(providers: Vec<P>, predicate: F) -> Self { |
140 | Self { |
141 | providers, |
142 | predicate, |
143 | } |
144 | } |
145 | |
146 | /// Returns a slice of the inner providers. |
147 | pub fn inner(&self) -> &[P] { |
148 | &self.providers |
149 | } |
150 | |
151 | /// Exposes a mutable vector of providers to a closure so it can be mutated. |
152 | pub fn with_inner_mut(&mut self, f: impl FnOnce(&mut Vec<P>)) { |
153 | f(&mut self.providers) |
154 | } |
155 | |
156 | /// Returns ownership of the inner providers to the caller. |
157 | pub fn into_inner(self) -> Vec<P> { |
158 | self.providers |
159 | } |
160 | |
161 | /// Adds an additional child provider. |
162 | pub fn push(&mut self, provider: P) { |
163 | self.providers.push(provider); |
164 | } |
165 | } |
166 | |
167 | impl<P, F> BufferProvider for MultiForkByErrorProvider<P, F> |
168 | where |
169 | P: BufferProvider, |
170 | F: ForkByErrorPredicate, |
171 | { |
172 | fn load_buffer( |
173 | &self, |
174 | key: DataKey, |
175 | req: DataRequest, |
176 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
177 | let mut last_error: DataError = F::UNIT_ERROR.with_key(key); |
178 | for provider: &P in self.providers.iter() { |
179 | let result: Result, …> = provider.load_buffer(key, req); |
180 | match result { |
181 | Ok(ok: DataResponse) => return Ok(ok), |
182 | Err(err: DataError) if !self.predicate.test(key, req:Some(req), err) => return Err(err), |
183 | Err(err: DataError) => last_error = err, |
184 | }; |
185 | } |
186 | Err(last_error) |
187 | } |
188 | } |
189 | |
190 | impl<P, F> AnyProvider for MultiForkByErrorProvider<P, F> |
191 | where |
192 | P: AnyProvider, |
193 | F: ForkByErrorPredicate, |
194 | { |
195 | fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> { |
196 | let mut last_error: DataError = F::UNIT_ERROR.with_key(key); |
197 | for provider: &P in self.providers.iter() { |
198 | let result: Result = provider.load_any(key, req); |
199 | match result { |
200 | Ok(ok: AnyResponse) => return Ok(ok), |
201 | Err(err: DataError) if !self.predicate.test(key, req:Some(req), err) => return Err(err), |
202 | Err(err: DataError) => last_error = err, |
203 | }; |
204 | } |
205 | Err(last_error) |
206 | } |
207 | } |
208 | |
209 | impl<M, P, F> DynamicDataProvider<M> for MultiForkByErrorProvider<P, F> |
210 | where |
211 | M: DataMarker, |
212 | P: DynamicDataProvider<M>, |
213 | F: ForkByErrorPredicate, |
214 | { |
215 | fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> { |
216 | let mut last_error: DataError = F::UNIT_ERROR.with_key(key); |
217 | for provider: &P in self.providers.iter() { |
218 | let result: Result, DataError> = provider.load_data(key, req); |
219 | match result { |
220 | Ok(ok: DataResponse) => return Ok(ok), |
221 | Err(err: DataError) if !self.predicate.test(key, req:Some(req), err) => return Err(err), |
222 | Err(err: DataError) => last_error = err, |
223 | }; |
224 | } |
225 | Err(last_error) |
226 | } |
227 | } |
228 | |
229 | #[cfg (feature = "datagen" )] |
230 | impl<M, P, F> datagen::IterableDynamicDataProvider<M> for MultiForkByErrorProvider<P, F> |
231 | where |
232 | M: DataMarker, |
233 | P: datagen::IterableDynamicDataProvider<M>, |
234 | F: ForkByErrorPredicate, |
235 | { |
236 | fn supported_locales_for_key(&self, key: DataKey) -> Result<Vec<DataLocale>, DataError> { |
237 | let mut last_error = F::UNIT_ERROR.with_key(key); |
238 | for provider in self.providers.iter() { |
239 | let result = provider.supported_locales_for_key(key); |
240 | match result { |
241 | Ok(ok) => return Ok(ok), |
242 | Err(err) if !self.predicate.test(key, None, err) => return Err(err), |
243 | Err(err) => last_error = err, |
244 | }; |
245 | } |
246 | Err(last_error) |
247 | } |
248 | } |
249 | |
250 | #[cfg (feature = "datagen" )] |
251 | impl<P, MFrom, MTo, F> datagen::DataConverter<MFrom, MTo> for MultiForkByErrorProvider<P, F> |
252 | where |
253 | P: datagen::DataConverter<MFrom, MTo>, |
254 | F: ForkByErrorPredicate, |
255 | MFrom: DataMarker, |
256 | MTo: DataMarker, |
257 | { |
258 | fn convert( |
259 | &self, |
260 | key: DataKey, |
261 | mut from: DataPayload<MFrom>, |
262 | ) -> Result<DataPayload<MTo>, (DataPayload<MFrom>, DataError)> { |
263 | let mut last_error = F::UNIT_ERROR.with_key(key); |
264 | for provider in self.providers.iter() { |
265 | let result = provider.convert(key, from); |
266 | match result { |
267 | Ok(ok) => return Ok(ok), |
268 | Err(e) => { |
269 | let (returned, err) = e; |
270 | if !self.predicate.test(key, None, err) { |
271 | return Err((returned, err)); |
272 | } |
273 | from = returned; |
274 | last_error = err; |
275 | } |
276 | }; |
277 | } |
278 | Err((from, last_error)) |
279 | } |
280 | } |
281 | |
282 | #[cfg (feature = "datagen" )] |
283 | impl<P0, P1, F, MFrom, MTo> datagen::DataConverter<MFrom, MTo> for ForkByErrorProvider<P0, P1, F> |
284 | where |
285 | P0: datagen::DataConverter<MFrom, MTo>, |
286 | P1: datagen::DataConverter<MFrom, MTo>, |
287 | F: ForkByErrorPredicate, |
288 | MFrom: DataMarker, |
289 | MTo: DataMarker, |
290 | { |
291 | fn convert( |
292 | &self, |
293 | key: DataKey, |
294 | mut from: DataPayload<MFrom>, |
295 | ) -> Result<DataPayload<MTo>, (DataPayload<MFrom>, DataError)> { |
296 | let result = self.0.convert(key, from); |
297 | match result { |
298 | Ok(ok) => return Ok(ok), |
299 | Err(e) => { |
300 | let (returned, err) = e; |
301 | if !self.2.test(key, None, err) { |
302 | return Err((returned, err)); |
303 | } |
304 | from = returned; |
305 | } |
306 | }; |
307 | self.1.convert(key, from) |
308 | } |
309 | } |
310 | |