icu_provider/lib.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
5//! `icu_provider` is one of the [`ICU4X`] components.
6//!
7//! Unicode's experience with ICU4X's parent projects, ICU4C and ICU4J, led the team to realize
8//! that data management is the most critical aspect of deploying internationalization, and that it requires
9//! a high level of customization for the needs of the platform it is embedded in. As a result
10//! ICU4X comes with a selection of providers that should allow for ICU4X to naturally fit into
11//! different business and technological needs of customers.
12//!
13//! `icu_provider` defines traits and structs for transmitting data through the ICU4X locale
14//! data pipeline. The primary trait is [`DataProvider`]. It is parameterized by a
15//! [`KeyedDataMarker`], which contains the data type and a [`DataKey`]. It has one method,
16//! [`DataProvider::load`], which transforms a [`DataRequest`]
17//! into a [`DataResponse`].
18//!
19//! - [`DataKey`] is a fixed identifier for the data type, such as `"plurals/cardinal@1"`.
20//! - [`DataRequest`] contains additional annotations to choose a specific variant of the key,
21//! such as a locale.
22//! - [`DataResponse`] contains the data if the request was successful.
23//!
24//! In addition, there are three other traits which are widely implemented:
25//!
26//! - [`AnyProvider`] returns data as `dyn Any` trait objects.
27//! - [`BufferProvider`] returns data as `[u8]` buffers.
28//! - [`DynamicDataProvider`] returns structured data but is not specific to a key.
29//!
30//! The most common types required for this crate are included via the prelude:
31//!
32//! ```
33//! use icu_provider::prelude::*;
34//! ```
35//!
36//! ## Types of Data Providers
37//!
38//! All nontrivial data providers can fit into one of two classes.
39//!
40//! 1. [`AnyProvider`]: Those whose data originates as structured Rust objects
41//! 2. [`BufferProvider`]: Those whose data originates as unstructured `[u8]` buffers
42//!
43//! **✨ Key Insight:** A given data provider is generally *either* an [`AnyProvider`] *or* a
44//! [`BufferProvider`]. Which type depends on the data source, and it is not generally possible
45//! to convert one to the other.
46//!
47//! See also [crate::constructors].
48//!
49//! ### AnyProvider
50//!
51//! These providers are able to return structured data cast into `dyn Any` trait objects. Users
52//! can call [`as_downcasting()`] to get an object implementing [`DataProvider`] by downcasting
53//! the trait objects.
54//!
55//! Examples of AnyProviders:
56//!
57//! - [`DatagenProvider`] reads structured data from CLDR source files and returns ICU4X data structs.
58//! - [`AnyPayloadProvider`] wraps a specific data struct and returns it.
59//! - The `BakedDataProvider` which encodes structured data directly in Rust source
60//!
61//! ### BufferProvider
62//!
63//! These providers are able to return unstructured data typically represented as
64//! [`serde`]-serialized buffers. Users can call [`as_deserializing()`] to get an object
65//! implementing [`DataProvider`] by invoking Serde Deserialize.
66//!
67//! Examples of BufferProviders:
68//!
69//! - [`FsDataProvider`] reads individual buffers from the filesystem.
70//! - [`BlobDataProvider`] reads buffers from a large in-memory blob.
71//!
72//! ## Provider Adapters
73//!
74//! ICU4X offers several built-in modules to combine providers in interesting ways.
75//! These can be found in the [`icu_provider_adapters`] crate.
76//!
77//! ## Testing Provider
78//!
79//! This crate also contains a concrete provider for demonstration purposes:
80//!
81//! - [`HelloWorldProvider`] returns "hello world" strings in several languages.
82//!
83//! ## Types and Lifetimes
84//!
85//! Types compatible with [`Yokeable`] can be passed through the data provider, so long as they are
86//! associated with a marker type implementing [`DataMarker`].
87//!
88//! Data structs should generally have one lifetime argument: `'data`. This lifetime allows data
89//! structs to borrow zero-copy data.
90//!
91//! ## Data generation API
92//!
93//! *This functionality is enabled with the "datagen" Cargo feature*
94//!
95//! The [`datagen`] module contains several APIs for data generation. See [`icu_datagen`] for the reference
96//! data generation implementation.
97//!
98//! [`ICU4X`]: ../icu/index.html
99//! [`DataProvider`]: data_provider::DataProvider
100//! [`DataKey`]: key::DataKey
101//! [`DataLocale`]: request::DataLocale
102//! [`IterableDynamicDataProvider`]: datagen::IterableDynamicDataProvider
103//! [`IterableDataProvider`]: datagen::IterableDataProvider
104//! [`AnyPayloadProvider`]: ../icu_provider_adapters/any_payload/struct.AnyPayloadProvider.html
105//! [`HelloWorldProvider`]: hello_world::HelloWorldProvider
106//! [`AnyProvider`]: any::AnyProvider
107//! [`Yokeable`]: yoke::Yokeable
108//! [`impl_dynamic_data_provider!`]: impl_dynamic_data_provider
109//! [`icu_provider_adapters`]: ../icu_provider_adapters/index.html
110//! [`DatagenProvider`]: ../icu_datagen/struct.DatagenProvider.html
111//! [`as_downcasting()`]: AsDowncastingAnyProvider::as_downcasting
112//! [`as_deserializing()`]: AsDeserializingBufferProvider::as_deserializing
113//! [`CldrJsonDataProvider`]: ../icu_datagen/cldr/struct.CldrJsonDataProvider.html
114//! [`FsDataProvider`]: ../icu_provider_fs/struct.FsDataProvider.html
115//! [`BlobDataProvider`]: ../icu_provider_blob/struct.BlobDataProvider.html
116//! [`icu_datagen`]: ../icu_datagen/index.html
117
118// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
119#![cfg_attr(not(any(test, feature = "std")), no_std)]
120#![cfg_attr(
121 not(test),
122 deny(
123 clippy::indexing_slicing,
124 clippy::unwrap_used,
125 clippy::expect_used,
126 clippy::panic,
127 clippy::exhaustive_structs,
128 clippy::exhaustive_enums,
129 missing_debug_implementations,
130 )
131)]
132#![warn(missing_docs)]
133
134extern crate alloc;
135
136mod data_provider;
137mod error;
138#[doc(hidden)]
139pub mod fallback;
140mod key;
141mod request;
142mod response;
143
144pub mod any;
145pub mod buf;
146pub mod constructors;
147#[cfg(feature = "datagen")]
148pub mod datagen;
149pub mod dynutil;
150pub mod hello_world;
151pub mod marker;
152#[cfg(feature = "serde")]
153pub mod serde;
154
155// Types from private modules
156pub use crate::data_provider::BoundDataProvider;
157pub use crate::data_provider::DataProvider;
158pub use crate::data_provider::DataProviderWithKey;
159pub use crate::data_provider::DynamicDataProvider;
160pub use crate::error::DataError;
161pub use crate::error::DataErrorKind;
162pub use crate::key::DataKey;
163pub use crate::key::DataKeyHash;
164pub use crate::key::DataKeyMetadata;
165pub use crate::key::DataKeyPath;
166#[cfg(feature = "experimental")]
167pub use crate::request::AuxiliaryKeys;
168pub use crate::request::DataLocale;
169pub use crate::request::DataRequest;
170pub use crate::request::DataRequestMetadata;
171pub use crate::response::Cart;
172pub use crate::response::DataPayload;
173pub use crate::response::DataPayloadOr;
174pub use crate::response::DataResponse;
175pub use crate::response::DataResponseMetadata;
176#[cfg(feature = "macros")]
177pub use icu_provider_macros::data_struct;
178
179// Reexports from public modules
180pub use crate::any::AnyMarker;
181pub use crate::any::AnyPayload;
182pub use crate::any::AnyProvider;
183pub use crate::any::AnyResponse;
184pub use crate::any::AsDowncastingAnyProvider;
185pub use crate::any::AsDynamicDataProviderAnyMarkerWrap;
186pub use crate::any::MaybeSendSync;
187pub use crate::buf::BufferMarker;
188pub use crate::buf::BufferProvider;
189pub use crate::marker::DataMarker;
190pub use crate::marker::KeyedDataMarker;
191pub use crate::marker::NeverMarker;
192#[cfg(feature = "serde")]
193pub use crate::serde::AsDeserializingBufferProvider;
194
195/// Core selection of APIs and structures for the ICU4X data provider.
196pub mod prelude {
197 #[doc(no_inline)]
198 pub use crate::data_key;
199 #[doc(no_inline)]
200 pub use crate::AnyMarker;
201 #[doc(no_inline)]
202 pub use crate::AnyPayload;
203 #[doc(no_inline)]
204 pub use crate::AnyProvider;
205 #[doc(no_inline)]
206 pub use crate::AnyResponse;
207 #[doc(no_inline)]
208 #[cfg(feature = "serde")]
209 pub use crate::AsDeserializingBufferProvider;
210 #[doc(no_inline)]
211 pub use crate::AsDowncastingAnyProvider;
212 #[doc(no_inline)]
213 pub use crate::AsDynamicDataProviderAnyMarkerWrap;
214 #[doc(no_inline)]
215 #[cfg(feature = "experimental")]
216 pub use crate::AuxiliaryKeys;
217 #[doc(no_inline)]
218 pub use crate::BoundDataProvider;
219 #[doc(no_inline)]
220 pub use crate::BufferMarker;
221 #[doc(no_inline)]
222 pub use crate::BufferProvider;
223 #[doc(no_inline)]
224 pub use crate::DataError;
225 #[doc(no_inline)]
226 pub use crate::DataErrorKind;
227 #[doc(no_inline)]
228 pub use crate::DataKey;
229 #[doc(no_inline)]
230 pub use crate::DataKeyHash;
231 #[doc(no_inline)]
232 pub use crate::DataLocale;
233 #[doc(no_inline)]
234 pub use crate::DataMarker;
235 #[doc(no_inline)]
236 pub use crate::DataPayload;
237 #[doc(no_inline)]
238 pub use crate::DataProvider;
239 #[doc(no_inline)]
240 pub use crate::DataRequest;
241 #[doc(no_inline)]
242 pub use crate::DataRequestMetadata;
243 #[doc(no_inline)]
244 pub use crate::DataResponse;
245 #[doc(no_inline)]
246 pub use crate::DataResponseMetadata;
247 #[doc(no_inline)]
248 pub use crate::DynamicDataProvider;
249 #[doc(no_inline)]
250 pub use crate::KeyedDataMarker;
251
252 #[doc(hidden)]
253 pub use yoke;
254 #[doc(hidden)]
255 pub use zerofrom;
256}
257
258// Additional crate re-exports for compatibility
259#[doc(hidden)]
260pub use fallback::LocaleFallbackPriority as FallbackPriority;
261#[doc(hidden)]
262pub use fallback::LocaleFallbackSupplement as FallbackSupplement;
263#[doc(hidden)]
264pub use yoke;
265#[doc(hidden)]
266pub use zerofrom;
267
268// For macros
269#[doc(hidden)]
270pub mod _internal {
271 pub use super::fallback::{LocaleFallbackPriority, LocaleFallbackSupplement};
272 pub use icu_locid as locid;
273
274 #[cfg(feature = "logging")]
275 pub use log;
276
277 #[cfg(all(not(feature = "logging"), debug_assertions, feature = "std"))]
278 pub mod log {
279 pub use std::eprintln as error;
280 pub use std::eprintln as warn;
281 pub use std::eprintln as info;
282 pub use std::eprintln as debug;
283 pub use std::eprintln as trace;
284 }
285
286 #[cfg(all(
287 not(feature = "logging"),
288 any(not(debug_assertions), not(feature = "std"))
289 ))]
290 pub mod log {
291 #[macro_export]
292 macro_rules! _internal_noop_log {
293 ($($t:expr),*) => {};
294 }
295 pub use crate::_internal_noop_log as error;
296 pub use crate::_internal_noop_log as warn;
297 pub use crate::_internal_noop_log as info;
298 pub use crate::_internal_noop_log as debug;
299 pub use crate::_internal_noop_log as trace;
300 }
301}
302
303#[test]
304fn test_logging() {
305 // This should compile on all combinations of features
306 crate::_internal::log::info!("Hello World");
307}