use super::ForkByErrorPredicate;
use alloc::{collections::BTreeSet, vec::Vec};
#[cfg(feature = "export")]
use icu_provider::export::ExportableProvider;
use icu_provider::prelude::*;
#[derive(Debug, PartialEq, Eq)]
pub struct ForkByErrorProvider<P0, P1, F>(P0, P1, F);
impl<P0, P1, F> ForkByErrorProvider<P0, P1, F> {
pub fn new_with_predicate(p0: P0, p1: P1, predicate: F) -> Self {
Self(p0, p1, predicate)
}
pub fn inner(&self) -> (&P0, &P1) {
(&self.0, &self.1)
}
pub fn inner_mut(&mut self) -> (&mut P0, &mut P1) {
(&mut self.0, &mut self.1)
}
pub fn into_inner(self) -> (P0, P1) {
(self.0, self.1)
}
}
impl<M, P0, P1, F> DataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
M: DataMarker,
P0: DataProvider<M>,
P1: DataProvider<M>,
F: ForkByErrorPredicate,
{
fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
let result = self.0.load(req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(M::INFO, Some(req), err) => return Err(err),
_ => (),
};
self.1.load(req)
}
}
impl<M, P0, P1, F> DryDataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
M: DataMarker,
P0: DryDataProvider<M>,
P1: DryDataProvider<M>,
F: ForkByErrorPredicate,
{
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
let result = self.0.dry_load(req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(M::INFO, Some(req), err) => return Err(err),
_ => (),
};
self.1.dry_load(req)
}
}
impl<P0, P1, F> AnyProvider for ForkByErrorProvider<P0, P1, F>
where
P0: AnyProvider,
P1: AnyProvider,
F: ForkByErrorPredicate,
{
fn load_any(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<AnyResponse, DataError> {
let result = self.0.load_any(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(marker, Some(req), err) => return Err(err),
_ => (),
};
self.1.load_any(marker, req)
}
}
impl<M, P0, P1, F> DynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
M: DynamicDataMarker,
P0: DynamicDataProvider<M>,
P1: DynamicDataProvider<M>,
F: ForkByErrorPredicate,
{
fn load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponse<M>, DataError> {
let result = self.0.load_data(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(marker, Some(req), err) => return Err(err),
_ => (),
};
self.1.load_data(marker, req)
}
}
impl<M, P0, P1, F> DynamicDryDataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
M: DynamicDataMarker,
P0: DynamicDryDataProvider<M>,
P1: DynamicDryDataProvider<M>,
F: ForkByErrorPredicate,
{
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
let result = self.0.dry_load_data(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(marker, Some(req), err) => return Err(err),
_ => (),
};
self.1.dry_load_data(marker, req)
}
}
impl<M, P0, P1, F> IterableDynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
M: DynamicDataMarker,
P0: IterableDynamicDataProvider<M>,
P1: IterableDynamicDataProvider<M>,
F: ForkByErrorPredicate,
{
fn iter_ids_for_marker(
&self,
marker: DataMarkerInfo,
) -> Result<BTreeSet<DataIdentifierCow>, DataError> {
let result = self.0.iter_ids_for_marker(marker);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.2.test(marker, None, err) => return Err(err),
_ => (),
};
self.1.iter_ids_for_marker(marker)
}
}
#[cfg(feature = "export")]
impl<P0, P1, F> ExportableProvider for ForkByErrorProvider<P0, P1, F>
where
P0: ExportableProvider,
P1: ExportableProvider,
F: ForkByErrorPredicate + Sync,
{
fn supported_markers(&self) -> std::collections::HashSet<DataMarkerInfo> {
let mut markers = self.0.supported_markers();
markers.extend(self.1.supported_markers());
markers
}
}
#[derive(Debug)]
pub struct MultiForkByErrorProvider<P, F> {
providers: Vec<P>,
predicate: F,
}
impl<P, F> MultiForkByErrorProvider<P, F> {
pub fn new_with_predicate(providers: Vec<P>, predicate: F) -> Self {
Self {
providers,
predicate,
}
}
pub fn inner(&self) -> &[P] {
&self.providers
}
pub fn with_inner_mut(&mut self, f: impl FnOnce(&mut Vec<P>)) {
f(&mut self.providers)
}
pub fn into_inner(self) -> Vec<P> {
self.providers
}
pub fn push(&mut self, provider: P) {
self.providers.push(provider);
}
}
impl<M, P, F> DataProvider<M> for MultiForkByErrorProvider<P, F>
where
M: DataMarker,
P: DataProvider<M>,
F: ForkByErrorPredicate,
{
fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(M::INFO);
for provider in self.providers.iter() {
let result = provider.load(req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(M::INFO, Some(req), err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
impl<M, P, F> DryDataProvider<M> for MultiForkByErrorProvider<P, F>
where
M: DataMarker,
P: DryDataProvider<M>,
F: ForkByErrorPredicate,
{
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(M::INFO);
for provider in self.providers.iter() {
let result = provider.dry_load(req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(M::INFO, Some(req), err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
impl<P, F> AnyProvider for MultiForkByErrorProvider<P, F>
where
P: AnyProvider,
F: ForkByErrorPredicate,
{
fn load_any(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<AnyResponse, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(marker);
for provider in self.providers.iter() {
let result = provider.load_any(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(marker, Some(req), err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
impl<M, P, F> DynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
where
M: DynamicDataMarker,
P: DynamicDataProvider<M>,
F: ForkByErrorPredicate,
{
fn load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponse<M>, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(marker);
for provider in self.providers.iter() {
let result = provider.load_data(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(marker, Some(req), err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
impl<M, P, F> DynamicDryDataProvider<M> for MultiForkByErrorProvider<P, F>
where
M: DynamicDataMarker,
P: DynamicDryDataProvider<M>,
F: ForkByErrorPredicate,
{
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(marker);
for provider in self.providers.iter() {
let result = provider.dry_load_data(marker, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(marker, Some(req), err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
impl<M, P, F> IterableDynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
where
M: DynamicDataMarker,
P: IterableDynamicDataProvider<M>,
F: ForkByErrorPredicate,
{
fn iter_ids_for_marker(
&self,
marker: DataMarkerInfo,
) -> Result<BTreeSet<DataIdentifierCow>, DataError> {
let mut last_error = F::UNIT_ERROR.with_marker(marker);
for provider in self.providers.iter() {
let result = provider.iter_ids_for_marker(marker);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(marker, None, err) => return Err(err),
Err(err) => last_error = err,
};
}
Err(last_error)
}
}
#[cfg(feature = "export")]
impl<P, F> ExportableProvider for MultiForkByErrorProvider<P, F>
where
P: ExportableProvider,
F: ForkByErrorPredicate + Sync,
{
fn supported_markers(&self) -> std::collections::HashSet<DataMarkerInfo> {
self.providers
.iter()
.flat_map(|p| p.supported_markers())
.collect()
}
}