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