// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). //! Providers that combine multiple other providers. //! //! # Types of Forking Providers //! //! ## Key-Based //! //! To fork between providers that support different data keys, see: //! //! - [`ForkByKeyProvider`] //! - [`MultiForkByKeyProvider`] //! //! ## Locale-Based //! //! To fork between providers that support different locales, see: //! //! - [`ForkByErrorProvider`]`<`[`MissingLocalePredicate`]`>` //! - [`MultiForkByErrorProvider`]`<`[`MissingLocalePredicate`]`>` //! //! [`MissingLocalePredicate`]: predicates::MissingLocalePredicate //! //! # Examples //! //! See: //! //! - [`ForkByKeyProvider`] //! - [`MultiForkByKeyProvider`] //! - [`MissingLocalePredicate`] use alloc::vec::Vec; mod by_error; pub mod predicates; #[macro_use] mod macros; pub use by_error::ForkByErrorProvider; pub use by_error::MultiForkByErrorProvider; use predicates::ForkByErrorPredicate; use predicates::MissingDataKeyPredicate; /// Create a provider that returns data from one of two child providers based on the key. /// /// The result of the first provider that supports a particular [`DataKey`] will be returned, /// even if the request failed for other reasons (such as an unsupported language). Therefore, /// you should add child providers that support disjoint sets of keys. /// /// [`ForkByKeyProvider`] does not support forking between [`DataProvider`]s. However, it /// supports forking between [`AnyProvider`], [`BufferProvider`], and [`DynamicDataProvider`]. /// /// # Examples /// /// Normal usage: /// /// ``` /// use icu_locid::locale; /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; /// use icu_provider_adapters::fork::ForkByKeyProvider; /// /// struct DummyBufferProvider; /// impl BufferProvider for DummyBufferProvider { /// fn load_buffer( /// &self, /// key: DataKey, /// req: DataRequest, /// ) -> Result, DataError> { /// Err(DataErrorKind::MissingDataKey.with_req(key, req)) /// } /// } /// /// let forking_provider = ForkByKeyProvider::new( /// DummyBufferProvider, /// HelloWorldProvider.into_json_provider(), /// ); /// /// let data_provider = forking_provider.as_deserializing(); /// /// let german_hello_world: DataPayload = data_provider /// .load(DataRequest { /// locale: &locale!("de").into(), /// metadata: Default::default(), /// }) /// .expect("Loading should succeed") /// .take_payload() /// .expect("Data should be present"); /// /// assert_eq!("Hallo Welt", german_hello_world.get().message); /// ``` /// /// Stops at the first provider supporting a key, even if the locale is not supported: /// /// ``` /// use icu_locid::{subtags_language as language, locale}; /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; /// use icu_provider_adapters::filter::Filterable; /// use icu_provider_adapters::fork::ForkByKeyProvider; /// /// let forking_provider = ForkByKeyProvider::new( /// HelloWorldProvider /// .into_json_provider() /// .filterable("Chinese") /// .filter_by_langid(|langid| langid.language == language!("zh")), /// HelloWorldProvider /// .into_json_provider() /// .filterable("German") /// .filter_by_langid(|langid| langid.language == language!("de")), /// ); /// /// let data_provider: &dyn DataProvider = /// &forking_provider.as_deserializing(); /// /// // Chinese is the first provider, so this succeeds /// let chinese_hello_world = data_provider /// .load(DataRequest { /// locale: &locale!("zh").into(), /// metadata: Default::default(), /// }) /// .expect("Loading should succeed") /// .take_payload() /// .expect("Data should be present"); /// /// assert_eq!("你好世界", chinese_hello_world.get().message); /// /// // German is shadowed by Chinese, so this fails /// data_provider /// .load(DataRequest { /// locale: &locale!("de").into(), /// metadata: Default::default(), /// }) /// .expect_err("Should stop at the first provider, even though the second has data"); /// ``` /// /// [`DataKey`]: icu_provider::DataKey /// [`DataProvider`]: icu_provider::DataProvider /// [`AnyProvider`]: icu_provider::AnyProvider /// [`BufferProvider`]: icu_provider::BufferProvider /// [`DynamicDataProvider`]: icu_provider::DynamicDataProvider pub type ForkByKeyProvider = ForkByErrorProvider; impl ForkByKeyProvider { /// A provider that returns data from one of two child providers based on the key. /// /// See [`ForkByKeyProvider`]. pub fn new(p0: P0, p1: P1) -> Self { ForkByErrorProvider::new_with_predicate(p0, p1, MissingDataKeyPredicate) } } /// A provider that returns data from the first child provider supporting the key. /// /// The result of the first provider that supports a particular [`DataKey`] will be returned, /// even if the request failed for other reasons (such as an unsupported language). Therefore, /// you should add child providers that support disjoint sets of keys. /// /// [`MultiForkByKeyProvider`] does not support forking between [`DataProvider`]s. However, it /// supports forking between [`AnyProvider`], [`BufferProvider`], and [`DynamicDataProvider`]. /// /// # Examples /// /// ``` /// use icu_locid::{subtags_language as language, locale}; /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; /// use icu_provider_adapters::filter::Filterable; /// use icu_provider_adapters::fork::MultiForkByKeyProvider; /// /// let forking_provider = MultiForkByKeyProvider::new( /// vec![ /// HelloWorldProvider /// .into_json_provider() /// .filterable("Chinese") /// .filter_by_langid(|langid| langid.language == language!("zh")), /// HelloWorldProvider /// .into_json_provider() /// .filterable("German") /// .filter_by_langid(|langid| langid.language == language!("de")), /// ], /// ); /// /// let data_provider: &dyn DataProvider = /// &forking_provider.as_deserializing(); /// /// // Chinese is the first provider, so this succeeds /// let chinese_hello_world = data_provider /// .load(DataRequest { /// locale: &locale!("zh").into(), /// metadata: Default::default(), /// }) /// .expect("Loading should succeed") /// .take_payload() /// .expect("Data should be present"); /// /// assert_eq!("你好世界", chinese_hello_world.get().message); /// /// // German is shadowed by Chinese, so this fails /// data_provider /// .load(DataRequest { /// locale: &locale!("de").into(), /// metadata: Default::default(), /// }) /// .expect_err("Should stop at the first provider, even though the second has data"); /// ``` /// /// [`DataKey`]: icu_provider::DataKey /// [`DataProvider`]: icu_provider::DataProvider /// [`AnyProvider`]: icu_provider::AnyProvider /// [`BufferProvider`]: icu_provider::BufferProvider /// [`DynamicDataProvider`]: icu_provider::DynamicDataProvider pub type MultiForkByKeyProvider

= MultiForkByErrorProvider; impl

MultiForkByKeyProvider

{ /// Create a provider that returns data from the first child provider supporting the key. /// /// See [`MultiForkByKeyProvider`]. pub fn new(providers: Vec

) -> Self { MultiForkByErrorProvider::new_with_predicate(providers, MissingDataKeyPredicate) } }