Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
f

d
  • Loading branch information
robertbastian committed Jul 1, 2024
1 parent 39034cd commit 518bf21
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 40 deletions.
30 changes: 30 additions & 0 deletions provider/adapters/src/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ impl<M: DynamicDataMarker, P0: DynamicDataProvider<M>, P1: DynamicDataProvider<M
}
}

impl<M: DynamicDataMarker, P0: DynamicDryDataProvider<M>, P1: DynamicDryDataProvider<M>>
DynamicDryDataProvider<M> for EitherProvider<P0, P1>
{
#[inline]
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
use EitherProvider::*;
match self {
A(p) => p.dry_load_data(marker, req),
B(p) => p.dry_load_data(marker, req),
}
}
}

impl<M: DataMarker, P0: DataProvider<M>, P1: DataProvider<M>> DataProvider<M>
for EitherProvider<P0, P1>
{
Expand All @@ -60,6 +77,19 @@ impl<M: DataMarker, P0: DataProvider<M>, P1: DataProvider<M>> DataProvider<M>
}
}

impl<M: DataMarker, P0: DryDataProvider<M>, P1: DryDataProvider<M>> DryDataProvider<M>
for EitherProvider<P0, P1>
{
#[inline]
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
use EitherProvider::*;
match self {
A(p) => p.dry_load(req),
B(p) => p.dry_load(req),
}
}
}

#[cfg(feature = "std")]
impl<
M: DynamicDataMarker,
Expand Down
76 changes: 71 additions & 5 deletions provider/adapters/src/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use icu_locale::provider::*;
use icu_locale::LocaleFallbacker;
use icu_provider::prelude::*;
use icu_provider::DryDataProvider;
use icu_provider::DynamicDryDataProvider;

/// A data provider wrapper that performs locale fallback. This enables arbitrary locales to be
/// handled at runtime.
Expand Down Expand Up @@ -244,11 +245,7 @@ impl<P> AnyProvider for LocaleFallbackProvider<P>
where
P: AnyProvider,
{
fn load_any(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<AnyResponse, DataError> {
fn load_any(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<AnyResponse, DataError> {
self.run_fallback(
marker,
req,
Expand Down Expand Up @@ -277,6 +274,25 @@ where
}
}

impl<P, M> DynamicDryDataProvider<M> for LocaleFallbackProvider<P>
where
P: DynamicDryDataProvider<M>,
M: DynamicDataMarker,
{
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
self.run_fallback(
marker,
req,
|req| self.inner.dry_load_data(marker, req),
|m| m,
)
}
}

impl<P, M> DataProvider<M> for LocaleFallbackProvider<P>
where
P: DataProvider<M>,
Expand All @@ -301,3 +317,53 @@ where
self.run_fallback(M::INFO, req, |req| self.inner.dry_load(req), |m| m)
}
}

#[test]
fn dry_test() {
use icu_provider::hello_world::*;

struct TestProvider;
impl DataProvider<HelloWorldV1Marker> for TestProvider {
fn load(&self, _: DataRequest) -> Result<DataResponse<HelloWorldV1Marker>, DataError> {
panic!("pretend this is super expensive")
}
}

impl DryDataProvider<HelloWorldV1Marker> for TestProvider {
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
// We support all languages but no regional variants. This is cheap to check.
if req.id.locale.region().is_some() || req.id.locale.language().as_str() == "en" {
Err(DataErrorKind::IdentifierNotFound.into_error())
} else {
Ok(Default::default())
}
}
}

let provider = LocaleFallbackProvider::new_with_fallbacker(
TestProvider,
LocaleFallbacker::new().static_to_owned(),
);

assert_eq!(
provider
.dry_load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&"de-CH".parse().unwrap()),
..Default::default()
})
.unwrap()
.locale,
"de".parse::<DataLocale>().ok()
);

assert_eq!(
provider
.dry_load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&"en-GB".parse().unwrap()),
..Default::default()
})
.unwrap()
.locale,
Some(DataLocale::default())
);
}
68 changes: 47 additions & 21 deletions provider/adapters/src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ where
pub filter_name: &'static str,
}

impl<D, F> FilterDataProvider<D, F>
where
F: Fn(DataIdentifierBorrowed) -> bool,
{
fn check(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<(), DataError> {
if !(self.predicate)(req.id) {
return Err(DataErrorKind::IdentifierNotFound
.with_str_context(self.filter_name)
.with_req(marker, req));
}
Ok(())
}
}

impl<D, F, M> DynamicDataProvider<M> for FilterDataProvider<D, F>
where
F: Fn(DataIdentifierBorrowed) -> bool,
Expand All @@ -60,13 +74,23 @@ where
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponse<M>, DataError> {
if (self.predicate)(req.id) {
self.inner.load_data(marker, req)
} else {
Err(DataErrorKind::IdentifierNotFound
.with_str_context(self.filter_name)
.with_req(marker, req))
}
self.inner.load_data(marker, req)
}
}

impl<D, F, M> DynamicDryDataProvider<M> for FilterDataProvider<D, F>
where
F: Fn(DataIdentifierBorrowed) -> bool,
M: DynamicDataMarker,
D: DynamicDryDataProvider<M>,
{
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
self.check(marker, req)?;
self.inner.dry_load_data(marker, req)
}
}

Expand All @@ -77,13 +101,20 @@ where
D: DataProvider<M>,
{
fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
if (self.predicate)(req.id) {
self.inner.load(req)
} else {
Err(DataErrorKind::IdentifierNotFound
.with_str_context(self.filter_name)
.with_req(M::INFO, req))
}
self.check(M::INFO, req)?;
self.inner.load(req)
}
}

impl<D, F, M> DryDataProvider<M> for FilterDataProvider<D, F>
where
F: Fn(DataIdentifierBorrowed) -> bool,
M: DataMarker,
D: DryDataProvider<M>,
{
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
self.check(M::INFO, req)?;
self.inner.dry_load(req)
}
}

Expand All @@ -93,13 +124,8 @@ where
D: AnyProvider,
{
fn load_any(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<AnyResponse, DataError> {
if (self.predicate)(req.id) {
self.inner.load_any(marker, req)
} else {
Err(DataErrorKind::IdentifierNotFound
.with_str_context(self.filter_name)
.with_req(marker, req))
}
self.check(marker, req)?;
self.inner.load_any(marker, req)
}
}

Expand Down
84 changes: 84 additions & 0 deletions provider/adapters/src/fork/by_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ where
}
}

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,
Expand Down Expand Up @@ -98,6 +116,28 @@ where
}
}

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

#[cfg(feature = "std")]
impl<M, P0, P1, F> IterableDynamicDataProvider<M> for ForkByErrorProvider<P0, P1, F>
where
Expand Down Expand Up @@ -186,6 +226,26 @@ where
}
}

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,
Expand Down Expand Up @@ -229,6 +289,30 @@ where
}
}

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

#[cfg(feature = "std")]
impl<M, P, F> IterableDynamicDataProvider<M> for MultiForkByErrorProvider<P, F>
where
Expand Down
10 changes: 7 additions & 3 deletions provider/core/src/buf/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,12 @@ where
// Necessary workaround bound (see `yoke::trait_hack` docs):
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
{
fn dry_load_data(&self, marker: DataMarkerInfo, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
// Avoids deserialization, deserialization cannot produce `DataErrorKind::MissingLocale`
// TODO: this does not return deserialization errors (which load_data does), which the trait in its current form requires
fn dry_load_data(
&self,
marker: DataMarkerInfo,
req: DataRequest,
) -> Result<DataResponseMetadata, DataError> {
self.0.dry_load_data(marker, req)
}
}
Expand Down Expand Up @@ -232,8 +236,8 @@ where
// Necessary workaround bound (see `yoke::trait_hack` docs):
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
{
// TODO: this does not return deserialization errors (which load does), which the trait in its current form requires
fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
// Avoids deserialization, deserialization cannot produce `DataErrorKind::MissingLocale`
self.0.dry_load_data(M::INFO, req)
}
}
Expand Down
Loading

0 comments on commit 518bf21

Please sign in to comment.