Skip to main content

icu_provider_adapters/filter/
impls.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::*;
6use alloc::boxed::Box;
7use icu_provider::prelude::*;
8
9impl<D> FilterDataProvider<D, fn(DataIdentifierBorrowed) -> bool> {
10    /// Creates a [`FilterDataProvider`] that does not do any filtering.
11    ///
12    /// Filters can be added using [`Self::with_filter`].
13    pub fn new(provider: D, filter_name: &'static str) -> Self {
14        Self {
15            inner: provider,
16            predicate: |_| true,
17            filter_name,
18        }
19    }
20}
21
22impl<D, F> FilterDataProvider<D, F>
23where
24    F: Fn(DataIdentifierBorrowed) -> bool + Sync,
25{
26    /// Filter out data requests with certain langids according to the predicate function. The
27    /// predicate should return `true` to allow a langid and `false` to reject a langid.
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// use icu_locale::LanguageIdentifier;
33    /// use icu_locale::{langid, subtags::language};
34    /// use icu_provider::hello_world::*;
35    /// use icu_provider::prelude::*;
36    /// use icu_provider_adapters::filter::FilterDataProvider;
37    ///
38    /// let provider =
39    ///     FilterDataProvider::new(HelloWorldProvider, "Demo no-English filter")
40    ///         .with_filter(|id| id.locale.language != language!("en"));
41    ///
42    /// // German requests should succeed:
43    /// let de = DataIdentifierCow::from_locale(langid!("de").into());
44    /// let response: Result<DataResponse<HelloWorldV1>, _> =
45    ///     provider.load(DataRequest {
46    ///         id: de.as_borrowed(),
47    ///         ..Default::default()
48    ///     });
49    /// assert!(response.is_ok());
50    ///
51    /// // English requests should fail:
52    /// let en = DataIdentifierCow::from_locale(langid!("en-US").into());
53    /// let response: Result<DataResponse<HelloWorldV1>, _> =
54    ///     provider.load(DataRequest {
55    ///         id: en.as_borrowed(),
56    ///         ..Default::default()
57    ///     });
58    /// let response: Result<DataResponse<HelloWorldV1>, _> =
59    ///     provider.load(DataRequest {
60    ///         id: en.as_borrowed(),
61    ///         ..Default::default()
62    ///     });
63    /// assert_eq!(
64    ///     response.unwrap_err().kind,
65    ///     DataErrorKind::IdentifierNotFound,
66    /// );
67    ///
68    /// // English should not appear in the iterator result:
69    /// let available_ids = provider
70    ///     .iter_ids()
71    ///     .expect("Should successfully make an iterator of supported locales");
72    /// assert!(available_ids
73    ///     .contains(&DataIdentifierCow::from_locale(langid!("de").into())));
74    /// assert!(!available_ids
75    ///     .contains(&DataIdentifierCow::from_locale(langid!("en").into())));
76    /// ```
77    #[expect(clippy::type_complexity)]
78    pub fn with_filter<'a>(
79        self,
80        predicate: impl Fn(DataIdentifierBorrowed) -> bool + Sync + 'a,
81    ) -> FilterDataProvider<D, Box<dyn Fn(DataIdentifierBorrowed) -> bool + Sync + 'a>>
82    where
83        F: 'a,
84    {
85        let old_predicate = self.predicate;
86        FilterDataProvider {
87            inner: self.inner,
88            predicate: Box::new(move |id| -> bool {
89                if !(old_predicate)(id) {
90                    return false;
91                }
92                predicate(id)
93            }),
94            filter_name: self.filter_name,
95        }
96    }
97}