Struct icu_provider::filter::RequestFilterDataProvider
source · [−]pub struct RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool, {
pub inner: D,
pub predicate: F,
pub filter_name: &'static str,
}
Expand description
A data provider that selectively filters out data requests.
Data requests that are rejected by the filter will return a DataError
with kind
FilteredResource
, and they will not be returned
by IterableProvider::supported_options_for_key
.
Although this struct can be created directly, the traits in this module provide helper functions for common filtering patterns.
Fields
inner: D
The data provider to which we delegate requests.
predicate: F
The predicate function. A return value of true
indicates that the request should
proceed as normal; a return value of false
will reject the request.
filter_name: &'static str
A name for this filter, used in error messages.
Implementations
pub fn filter_by_langid<'a>(
self,
predicate: impl Fn(&LanguageIdentifier) -> bool + 'a
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
pub fn filter_by_langid<'a>(
self,
predicate: impl Fn(&LanguageIdentifier) -> bool + 'a
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
Filter out data requests with certain langids according to the predicate function. The
predicate should return true
to allow a langid and false
to reject a langid.
Data requests with no langid will be allowed. To reject data requests without a langid,
chain this with Self::require_langid
.
Examples
use icu_provider::prelude::*;
use icu_provider::hello_world::*;
use icu_provider::filter::Filterable;
use icu_provider::iter::IterableProvider;
use icu_locid::LanguageIdentifier;
use icu_locid_macros::{language, langid};
let provider = HelloWorldProvider::new_with_placeholder_data()
.filterable("Demo no-English filter")
.filter_by_langid(|langid| langid.language != language!("en"));
// German requests should succeed:
let req_de = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: langid!("de").into(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_de);
assert!(matches!(response, Ok(_)));
// English requests should fail:
let req_en = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: langid!("en-US").into(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_en);
assert!(matches!(
response,
Err(DataError { kind: DataErrorKind::FilteredResource, .. })
));
// English should not appear in the iterator result:
let supported_langids = provider.supported_options_for_key(&key::HELLO_WORLD_V1)
.expect("Should successfully make an iterator of supported locales")
.filter_map(|options| options.langid)
.collect::<Vec<LanguageIdentifier>>();
assert!(supported_langids.contains(&langid!("de")));
assert!(!supported_langids.contains(&langid!("en")));
pub fn filter_by_langid_allowlist_strict<'a>(
self,
allowlist: &'a [LanguageIdentifier]
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
pub fn filter_by_langid_allowlist_strict<'a>(
self,
allowlist: &'a [LanguageIdentifier]
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
Filter out data request except those having a language identifier that exactly matches one in the allowlist.
This will be replaced with a smarter algorithm for locale filtering; see https://github.com/unicode-org/icu4x/issues/834
Data requests with no langid will be allowed. To reject data requests without a langid,
chain this with Self::require_langid
.
Examples
use icu_provider::prelude::*;
use icu_provider::hello_world::*;
use icu_provider::filter::Filterable;
use icu_locid_macros::langid;
let allowlist = vec![langid!("de"), langid!("zh")];
let provider = HelloWorldProvider::new_with_placeholder_data()
.filterable("Demo German+Chinese filter")
.filter_by_langid_allowlist_strict(&allowlist);
// German requests should succeed:
let req_de = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: langid!("de").into(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_de);
assert!(matches!(response, Ok(_)));
// English requests should fail:
let req_en = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: langid!("en-US").into(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_en);
assert!(matches!(
response,
Err(DataError { kind: DataErrorKind::FilteredResource, .. })
));
assert_eq!(
response.unwrap_err().str_context,
Some("Demo German+Chinese filter")
);
pub fn require_langid<'a>(
self
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
pub fn require_langid<'a>(
self
) -> RequestFilterDataProvider<D, Box<dyn Fn(&DataRequest) -> bool + 'a>> where
F: 'a,
Require that data requests contain a langid.
Examples
use icu_provider::prelude::*;
use icu_provider::hello_world::*;
use icu_provider::filter::Filterable;
use icu_locid_macros::langid;
let provider = HelloWorldProvider::new_with_placeholder_data()
.filterable("Demo require-langid filter")
.require_langid();
// Requests with a langid should succeed:
let req_with_langid = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: langid!("de").into(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_with_langid);
assert!(matches!(response, Ok(_)));
// Requests without a langid should fail:
let req_no_langid = DataRequest {
resource_path: ResourcePath {
key: key::HELLO_WORLD_V1,
options: Default::default(),
}
};
let response: Result<DataResponse<HelloWorldV1Marker>, _> =
provider.load_payload(&req_no_langid);
assert!(matches!(
response,
Err(DataError { kind: DataErrorKind::FilteredResource, .. })
));
Trait Implementations
impl<D, F> BufferProvider for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
D: BufferProvider,
impl<D, F> BufferProvider for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
D: BufferProvider,
impl<D, F, M> DataProvider<M> for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
M: DataMarker,
D: DataProvider<M>,
impl<D, F, M> DataProvider<M> for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
M: DataMarker,
D: DataProvider<M>,
Query the provider for data, returning the result. Read more
impl<D, F> IterableProvider for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
D: IterableProvider,
impl<D, F> IterableProvider for RequestFilterDataProvider<D, F> where
F: Fn(&DataRequest) -> bool,
D: IterableProvider,
fn supported_options_for_key(
&self,
resc_key: &ResourceKey
) -> Result<Box<dyn Iterator<Item = ResourceOptions>>, DataError>
fn supported_options_for_key(
&self,
resc_key: &ResourceKey
) -> Result<Box<dyn Iterator<Item = ResourceOptions>>, DataError>
Given a ResourceKey
, returns a boxed iterator over ResourceOptions
.
Auto Trait Implementations
impl<D, F> RefUnwindSafe for RequestFilterDataProvider<D, F> where
D: RefUnwindSafe,
F: RefUnwindSafe,
impl<D, F> Send for RequestFilterDataProvider<D, F> where
D: Send,
F: Send,
impl<D, F> Sync for RequestFilterDataProvider<D, F> where
D: Sync,
F: Sync,
impl<D, F> Unpin for RequestFilterDataProvider<D, F> where
D: Unpin,
F: Unpin,
impl<D, F> UnwindSafe for RequestFilterDataProvider<D, F> where
D: UnwindSafe,
F: UnwindSafe,
Blanket Implementations
Returns an object implementing AnyProvider
when called on DataProvider<AnyMarker>
Mutably borrows from an owned value. Read more
fn filterable(
self,
filter_name: &'static str
) -> RequestFilterDataProvider<Self, fn(_: &DataRequest) -> bool>
fn filterable(
self,
filter_name: &'static str
) -> RequestFilterDataProvider<Self, fn(_: &DataRequest) -> bool>
Creates a filterable data provider with the given name for debugging. Read more