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
5use super::ForkByErrorPredicate;
6use alloc::vec::Vec;
7#[cfg(feature = "datagen")]
8use icu_provider::datagen;
9use 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)]
19pub struct ForkByErrorProvider<P0, P1, F>(P0, P1, F);
20
21impl<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
46impl<P0, P1, F> BufferProvider for ForkByErrorProvider<P0, P1, F>
47where
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
67impl<P0, P1, F> AnyProvider for ForkByErrorProvider<P0, P1, F>
68where
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
84impl<M, P0, P1, F> DynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
85where
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")]
103impl<M, P0, P1, F> datagen::IterableDynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
104where
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)]
129pub struct MultiForkByErrorProvider<P, F> {
130 providers: Vec<P>,
131 predicate: F,
132}
133
134impl<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
167impl<P, F> BufferProvider for MultiForkByErrorProvider<P, F>
168where
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
190impl<P, F> AnyProvider for MultiForkByErrorProvider<P, F>
191where
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
209impl<M, P, F> DynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
210where
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")]
230impl<M, P, F> datagen::IterableDynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
231where
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")]
251impl<P, MFrom, MTo, F> datagen::DataConverter<MFrom, MTo> for MultiForkByErrorProvider<P, F>
252where
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")]
283impl<P0, P1, F, MFrom, MTo> datagen::DataConverter<MFrom, MTo> for ForkByErrorProvider<P0, P1, F>
284where
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