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//! [`DataMarker`], which is the type-system-level data identifier. [`DataProvider`] has a single method,
16//! [`DataProvider::load`], which transforms a [`DataRequest`] into a [`DataResponse`].
17//!
18//! - [`DataRequest`] contains selectors to choose a specific variant of the marker, such as a locale.
19//! - [`DataResponse`] contains the data if the request was successful.
20//!
21//! The most common types required for this crate are included via the prelude:
22//!
23//! ```
24//! use icu_provider::prelude::*;
25//! ```
26//!
27//! ## Dynamic Data Providers
28//!
29//! If the type system cannot be leveraged to load data (such as when dynamically loading from I/O),
30//! there's another form of the [`DataProvider`]: [`DynamicDataProvider`]. While [`DataProvider`] is parametrized
31//! on the type-system level by a [`DataMarker`] (which are distinct types implementing this trait),
32//! [`DynamicDataProvider`]s are parametrized at runtime by a [`DataMarkerInfo`] struct, which essentially is the runtime
33//! representation of the [`DataMarker`] type.
34//!
35//! The [`DynamicDataProvider`] is still type-level parametrized by the type that it loads, and there are two
36//! implementations that should be called out
37//!
38//! - [`DynamicDataProvider<BufferMarker>`], a.k.a. [`BufferProvider`](buf::BufferProvider) returns data as `[u8]` buffers.
39//!
40//! ### BufferProvider
41//!
42//! These providers are able to return unstructured data typically represented as
43//! [`serde`]-serialized buffers. Users can call [`as_deserializing()`] to get an object
44//! implementing [`DataProvider`] by invoking Serde Deserialize.
45//!
46//! Examples of BufferProviders:
47//!
48//! - [`FsDataProvider`] reads individual buffers from the filesystem.
49//! - [`BlobDataProvider`] reads buffers from a large in-memory blob.
50//!
51//! ## Provider Adapters
52//!
53//! ICU4X offers several built-in modules to combine providers in interesting ways.
54//! These can be found in the [`icu_provider_adapters`] crate.
55//!
56//! ## Testing Provider
57//!
58//! This crate also contains a concrete provider for demonstration purposes:
59//!
60//! - [`HelloWorldProvider`] returns "hello world" strings in several languages.
61//!
62//! ## Types and Lifetimes
63//!
64//! Types compatible with [`Yokeable`] can be passed through the data provider, so long as they are
65//! associated with a marker type implementing [`DynamicDataMarker`].
66//!
67//! Data structs should generally have one lifetime argument: `'data`. This lifetime allows data
68//! structs to borrow zero-copy data.
69//!
70//! [`FixedProvider`]: https://docs.rs/icu_provider_adapters/latest/fixed/any_payload/struct.FixedProvider.html
71//! [`HelloWorldProvider`]: hello_world::HelloWorldProvider
72//! [`Yokeable`]: yoke::Yokeable
73//! [`impl_dynamic_data_provider!`]: dynutil::impl_dynamic_data_provider
74//! [`icu_provider_adapters`]: https://docs.rs/icu_provider_adapters/latest/icu_provider_adapters/index.html
75//! [`SourceDataProvider`]: https://docs.rs/icu_provider_source/latest/icu_provider_source/struct.SourceDataProvider.html
76//! [`as_deserializing()`]: buf::AsDeserializingBufferProvider::as_deserializing
77//! [`FsDataProvider`]: https://docs.rs/icu_provider_fs/latest/icu_provider_fs/struct.FsDataProvider.html
78//! [`BlobDataProvider`]: https://docs.rs/icu_provider_blob/latest/icu_provider_blob/struct.BlobDataProvider.html
79
80// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
81#![cfg_attr(not(any(test, feature = "std")), no_std)]
82#![cfg_attr(
83 not(test),
84 deny(
85 clippy::indexing_slicing,
86 clippy::unwrap_used,
87 clippy::expect_used,
88 clippy::panic,
89 clippy::exhaustive_structs,
90 clippy::exhaustive_enums,
91 clippy::trivially_copy_pass_by_ref,
92 missing_debug_implementations,
93 )
94)]
95#![warn(missing_docs)]
96
97#[cfg(feature = "alloc")]
98extern crate alloc;
99
100#[cfg(feature = "baked")]
101pub mod baked;
102pub mod buf;
103pub mod constructors;
104pub mod dynutil;
105#[cfg(feature = "export")]
106pub mod export;
107#[cfg(feature = "alloc")]
108pub mod hello_world;
109
110// TODO: put this in a separate crate
111#[cfg(all(feature = "serde", feature = "alloc"))]
112#[doc(hidden)]
113pub mod serde_borrow_de_utils;
114
115mod data_provider;
116pub use data_provider::{
117 BoundDataProvider, DataProvider, DataProviderWithMarker, DryDataProvider, DynamicDataProvider,
118 DynamicDryDataProvider,
119};
120#[cfg(feature = "alloc")]
121pub use data_provider::{IterableDataProvider, IterableDynamicDataProvider};
122
123mod error;
124pub use error::{DataError, DataErrorKind, ResultDataError};
125
126mod request;
127pub use request::{DataLocale, DataMarkerAttributes, DataRequest, DataRequestMetadata, *};
128
129mod response;
130#[doc(hidden)] // TODO(#4467): establish this as an internal API
131pub use response::DataPayloadOr;
132pub use response::{Cart, DataPayload, DataResponse, DataResponseMetadata};
133
134#[path = "marker.rs"]
135mod marker_full;
136
137pub use marker_full::{DataMarker, DataMarkerInfo, DynamicDataMarker};
138pub mod marker {
139 //! Additional [`DataMarker`](super::DataMarker) helpers.
140
141 #[doc(inline)]
142 pub use super::marker_full::impl_data_provider_never_marker;
143 pub use super::marker_full::{
144 DataMarkerExt, DataMarkerId, DataMarkerIdHash, ErasedMarker, NeverMarker,
145 };
146}
147
148mod varule_traits;
149pub mod ule {
150 //! Traits that data provider implementations can use to optimize storage
151 //! by using [`VarULE`](zerovec::ule::VarULE).
152 //!
153 //! See [`MaybeAsVarULE`] for details.
154
155 pub use super::varule_traits::MaybeAsVarULE;
156 #[cfg(feature = "export")]
157 pub use super::varule_traits::MaybeEncodeAsVarULE;
158}
159
160/// Core selection of APIs and structures for the ICU4X data provider.
161pub mod prelude {
162 #[doc(no_inline)]
163 #[cfg(feature = "serde")]
164 pub use crate::buf::AsDeserializingBufferProvider;
165 #[doc(no_inline)]
166 pub use crate::buf::{BufferMarker, BufferProvider};
167 #[doc(no_inline)]
168 pub use crate::{
169 data_marker, data_struct, marker::DataMarkerExt, request::AttributeParseError,
170 request::DataIdentifierBorrowed, BoundDataProvider, DataError, DataErrorKind, DataLocale,
171 DataMarker, DataMarkerAttributes, DataMarkerInfo, DataPayload, DataProvider, DataRequest,
172 DataRequestMetadata, DataResponse, DataResponseMetadata, DryDataProvider,
173 DynamicDataMarker, DynamicDataProvider, DynamicDryDataProvider, ResultDataError,
174 };
175 #[cfg(feature = "alloc")]
176 #[doc(no_inline)]
177 pub use crate::{
178 request::DataIdentifierCow, IterableDataProvider, IterableDynamicDataProvider,
179 };
180
181 #[doc(no_inline)]
182 pub use icu_locale_core;
183 #[doc(no_inline)]
184 pub use yoke;
185 #[doc(no_inline)]
186 pub use zerofrom;
187}
188
189#[doc(hidden)] // internal
190pub mod fallback;
191
192#[doc(hidden)] // internal
193#[cfg(feature = "logging")]
194pub use log;
195
196#[doc(hidden)] // internal
197#[cfg(all(not(feature = "logging"), debug_assertions, not(target_os = "none")))]
198pub mod log {
199 extern crate std;
200 pub use std::eprintln as error;
201 pub use std::eprintln as warn;
202 pub use std::eprintln as info;
203 pub use std::eprintln as debug;
204 pub use std::eprintln as trace;
205}
206
207#[cfg(all(
208 not(feature = "logging"),
209 any(not(debug_assertions), target_os = "none")
210))]
211#[doc(hidden)] // internal
212pub mod log {
213 #[macro_export]
214 macro_rules! _internal_noop_log {
215 ($($t:expr),*) => {};
216 }
217 pub use crate::_internal_noop_log as error;
218 pub use crate::_internal_noop_log as warn;
219 pub use crate::_internal_noop_log as info;
220 pub use crate::_internal_noop_log as debug;
221 pub use crate::_internal_noop_log as trace;
222}
223
224#[test]
225fn test_logging() {
226 // This should compile on all combinations of features
227 crate::log::info!("Hello World");
228}