icu_provider_adapters/fork/
by_error.rs

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 = self.0.load_buffer(key, req);
58        match result {
59            Ok(ok) => return Ok(ok),
60            Err(err) if !self.2.test(key, 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 = self.0.load_any(key, req);
75        match result {
76            Ok(ok) => return Ok(ok),
77            Err(err) if !self.2.test(key, 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 = self.0.load_data(key, req);
93        match result {
94            Ok(ok) => return Ok(ok),
95            Err(err) if !self.2.test(key, 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 = F::UNIT_ERROR.with_key(key);
178        for provider in self.providers.iter() {
179            let result = provider.load_buffer(key, req);
180            match result {
181                Ok(ok) => return Ok(ok),
182                Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
183                Err(err) => 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 = F::UNIT_ERROR.with_key(key);
197        for provider in self.providers.iter() {
198            let result = provider.load_any(key, req);
199            match result {
200                Ok(ok) => return Ok(ok),
201                Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
202                Err(err) => 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 = F::UNIT_ERROR.with_key(key);
217        for provider in self.providers.iter() {
218            let result = provider.load_data(key, req);
219            match result {
220                Ok(ok) => return Ok(ok),
221                Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
222                Err(err) => 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}