Skip to main content

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::{collections::BTreeSet, vec::Vec};
7#[cfg(feature = "export")]
8use icu_provider::export::ExportableProvider;
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 [`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<M, P0, P1, F> DataProvider<M> for ForkByErrorProvider<P0, P1, F>
47where
48    M: DataMarker,
49    P0: DataProvider<M>,
50    P1: DataProvider<M>,
51    F: ForkByErrorPredicate,
52{
53    fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
54        let result = self.0.load(req);
55        match result {
56            Ok(ok) => return Ok(ok),
57            Err(err) if !self.2.test(M::INFO, Some(req), err) => return Err(err),
58            _ => (),
59        };
60        self.1.load(req)
61    }
62}
63
64impl<M, P0, P1, F> DryDataProvider<M> for ForkByErrorProvider<P0, P1, F>
65where
66    M: DataMarker,
67    P0: DryDataProvider<M>,
68    P1: DryDataProvider<M>,
69    F: ForkByErrorPredicate,
70{
71    fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
72        let result = self.0.dry_load(req);
73        match result {
74            Ok(ok) => return Ok(ok),
75            Err(err) if !self.2.test(M::INFO, Some(req), err) => return Err(err),
76            _ => (),
77        };
78        self.1.dry_load(req)
79    }
80}
81
82impl<M, P0, P1, F> DynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
83where
84    M: DynamicDataMarker,
85    P0: DynamicDataProvider<M>,
86    P1: DynamicDataProvider<M>,
87    F: ForkByErrorPredicate,
88{
89    fn load_data(
90        &self,
91        marker: DataMarkerInfo,
92        req: DataRequest,
93    ) -> Result<DataResponse<M>, DataError> {
94        let result = self.0.load_data(marker, req);
95        match result {
96            Ok(ok) => return Ok(ok),
97            Err(err) if !self.2.test(marker, Some(req), err) => return Err(err),
98            _ => (),
99        };
100        self.1.load_data(marker, req)
101    }
102}
103
104impl<M, P0, P1, F> DynamicDryDataProvider<M> for ForkByErrorProvider<P0, P1, F>
105where
106    M: DynamicDataMarker,
107    P0: DynamicDryDataProvider<M>,
108    P1: DynamicDryDataProvider<M>,
109    F: ForkByErrorPredicate,
110{
111    fn dry_load_data(
112        &self,
113        marker: DataMarkerInfo,
114        req: DataRequest,
115    ) -> Result<DataResponseMetadata, DataError> {
116        let result = self.0.dry_load_data(marker, req);
117        match result {
118            Ok(ok) => return Ok(ok),
119            Err(err) if !self.2.test(marker, Some(req), err) => return Err(err),
120            _ => (),
121        };
122        self.1.dry_load_data(marker, req)
123    }
124}
125
126impl<M, P0, P1, F> IterableDynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
127where
128    M: DynamicDataMarker,
129    P0: IterableDynamicDataProvider<M>,
130    P1: IterableDynamicDataProvider<M>,
131    F: ForkByErrorPredicate,
132{
133    fn iter_ids_for_marker(
134        &self,
135        marker: DataMarkerInfo,
136    ) -> Result<BTreeSet<DataIdentifierCow<'_>>, DataError> {
137        let result = self.0.iter_ids_for_marker(marker);
138        match result {
139            Ok(ok) => return Ok(ok),
140            Err(err) if !self.2.test(marker, None, err) => return Err(err),
141            _ => (),
142        };
143        self.1.iter_ids_for_marker(marker)
144    }
145}
146
147#[cfg(feature = "export")]
148impl<P0, P1, F> ExportableProvider for ForkByErrorProvider<P0, P1, F>
149where
150    P0: ExportableProvider,
151    P1: ExportableProvider,
152    F: ForkByErrorPredicate + Sync,
153{
154    fn supported_markers(&self) -> alloc::collections::BTreeSet<DataMarkerInfo> {
155        let mut markers = self.0.supported_markers();
156        markers.extend(self.1.supported_markers());
157        markers
158    }
159}
160
161/// A provider that returns data from the first child provider passing a predicate function.
162///
163/// This is an abstract forking provider that must be provided with a type implementing the
164/// [`ForkByErrorPredicate`] trait.
165///
166/// [`MultiForkByErrorProvider`] does not support forking between [`DataProvider`]s. However, it
167/// supports forking between [`BufferProvider`], and [`DynamicDataProvider`].
168#[derive(Debug)]
169pub struct MultiForkByErrorProvider<P, F> {
170    providers: Vec<P>,
171    predicate: F,
172}
173
174impl<P, F> MultiForkByErrorProvider<P, F> {
175    /// Create a new provider that forks between the vector of children.
176    ///
177    /// The `predicate` argument should be an instance of a struct implementing
178    /// [`ForkByErrorPredicate`].
179    pub fn new_with_predicate(providers: Vec<P>, predicate: F) -> Self {
180        Self {
181            providers,
182            predicate,
183        }
184    }
185
186    /// Returns a slice of the inner providers.
187    pub fn inner(&self) -> &[P] {
188        &self.providers
189    }
190
191    /// Exposes a mutable vector of providers to a closure so it can be mutated.
192    pub fn with_inner_mut(&mut self, f: impl FnOnce(&mut Vec<P>)) {
193        f(&mut self.providers)
194    }
195
196    /// Returns ownership of the inner providers to the caller.
197    pub fn into_inner(self) -> Vec<P> {
198        self.providers
199    }
200
201    /// Adds an additional child provider.
202    pub fn push(&mut self, provider: P) {
203        self.providers.push(provider);
204    }
205}
206
207impl<M, P, F> DataProvider<M> for MultiForkByErrorProvider<P, F>
208where
209    M: DataMarker,
210    P: DataProvider<M>,
211    F: ForkByErrorPredicate,
212{
213    fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
214        let mut last_error = F::UNIT_ERROR.with_marker(M::INFO);
215        for provider in self.providers.iter() {
216            let result = provider.load(req);
217            match result {
218                Ok(ok) => return Ok(ok),
219                Err(err) if !self.predicate.test(M::INFO, Some(req), err) => return Err(err),
220                Err(err) => last_error = err,
221            };
222        }
223        Err(last_error)
224    }
225}
226
227impl<M, P, F> DryDataProvider<M> for MultiForkByErrorProvider<P, F>
228where
229    M: DataMarker,
230    P: DryDataProvider<M>,
231    F: ForkByErrorPredicate,
232{
233    fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
234        let mut last_error = F::UNIT_ERROR.with_marker(M::INFO);
235        for provider in self.providers.iter() {
236            let result = provider.dry_load(req);
237            match result {
238                Ok(ok) => return Ok(ok),
239                Err(err) if !self.predicate.test(M::INFO, Some(req), err) => return Err(err),
240                Err(err) => last_error = err,
241            };
242        }
243        Err(last_error)
244    }
245}
246
247impl<M, P, F> DynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
248where
249    M: DynamicDataMarker,
250    P: DynamicDataProvider<M>,
251    F: ForkByErrorPredicate,
252{
253    fn load_data(
254        &self,
255        marker: DataMarkerInfo,
256        req: DataRequest,
257    ) -> Result<DataResponse<M>, DataError> {
258        let mut last_error = F::UNIT_ERROR.with_marker(marker);
259        for provider in self.providers.iter() {
260            let result = provider.load_data(marker, req);
261            match result {
262                Ok(ok) => return Ok(ok),
263                Err(err) if !self.predicate.test(marker, Some(req), err) => return Err(err),
264                Err(err) => last_error = err,
265            };
266        }
267        Err(last_error)
268    }
269}
270
271impl<M, P, F> DynamicDryDataProvider<M> for MultiForkByErrorProvider<P, F>
272where
273    M: DynamicDataMarker,
274    P: DynamicDryDataProvider<M>,
275    F: ForkByErrorPredicate,
276{
277    fn dry_load_data(
278        &self,
279        marker: DataMarkerInfo,
280        req: DataRequest,
281    ) -> Result<DataResponseMetadata, DataError> {
282        let mut last_error = F::UNIT_ERROR.with_marker(marker);
283        for provider in self.providers.iter() {
284            let result = provider.dry_load_data(marker, req);
285            match result {
286                Ok(ok) => return Ok(ok),
287                Err(err) if !self.predicate.test(marker, Some(req), err) => return Err(err),
288                Err(err) => last_error = err,
289            };
290        }
291        Err(last_error)
292    }
293}
294
295impl<M, P, F> IterableDynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
296where
297    M: DynamicDataMarker,
298    P: IterableDynamicDataProvider<M>,
299    F: ForkByErrorPredicate,
300{
301    fn iter_ids_for_marker(
302        &self,
303        marker: DataMarkerInfo,
304    ) -> Result<BTreeSet<DataIdentifierCow<'_>>, DataError> {
305        let mut last_error = F::UNIT_ERROR.with_marker(marker);
306        for provider in self.providers.iter() {
307            let result = provider.iter_ids_for_marker(marker);
308            match result {
309                Ok(ok) => return Ok(ok),
310                Err(err) if !self.predicate.test(marker, None, err) => return Err(err),
311                Err(err) => last_error = err,
312            };
313        }
314        Err(last_error)
315    }
316}
317
318#[cfg(feature = "export")]
319impl<P, F> ExportableProvider for MultiForkByErrorProvider<P, F>
320where
321    P: ExportableProvider,
322    F: ForkByErrorPredicate + Sync,
323{
324    fn supported_markers(&self) -> alloc::collections::BTreeSet<DataMarkerInfo> {
325        self.providers
326            .iter()
327            .flat_map(|p| p.supported_markers())
328            .collect()
329    }
330}