| 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 | |