Skip to main content

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;
126pub use response::DataPayloadOr;
127pub use response::{Cart, DataPayload, DataResponse, DataResponseMetadata};
128
129#[path = "marker.rs"]
130mod marker_full;
131
132pub use marker_full::{DataMarker, DataMarkerInfo, DynamicDataMarker};
133pub mod marker {
134    //! Additional [`DataMarker`](super::DataMarker) helpers.
135
136    #[doc(inline)]
137    pub use super::marker_full::impl_data_provider_never_marker;
138    pub use super::marker_full::{
139        DataMarkerExt, DataMarkerId, DataMarkerIdHash, ErasedMarker, NeverMarker,
140    };
141}
142
143mod varule_traits;
144pub mod ule {
145    //! Traits that data provider implementations can use to optimize storage
146    //! by using [`VarULE`](zerovec::ule::VarULE).
147    //!
148    //! See [`MaybeAsVarULE`] for details.
149
150    pub use super::varule_traits::MaybeAsVarULE;
151    #[cfg(feature = "export")]
152    pub use super::varule_traits::MaybeEncodeAsVarULE;
153}
154
155/// Core selection of APIs and structures for the ICU4X data provider.
156pub mod prelude {
157    #[doc(no_inline)]
158    #[cfg(feature = "serde")]
159    pub use crate::buf::AsDeserializingBufferProvider;
160    #[doc(no_inline)]
161    pub use crate::buf::{BufferMarker, BufferProvider};
162    #[doc(no_inline)]
163    pub use crate::{
164        BoundDataProvider, DataError, DataErrorKind, DataLocale, DataMarker, DataMarkerAttributes,
165        DataMarkerInfo, DataPayload, DataProvider, DataRequest, DataRequestMetadata, DataResponse,
166        DataResponseMetadata, DryDataProvider, DynamicDataMarker, DynamicDataProvider,
167        DynamicDryDataProvider, ResultDataError, data_marker, data_struct, marker::DataMarkerExt,
168        request::AttributeParseError, request::DataIdentifierBorrowed,
169    };
170    #[cfg(feature = "alloc")]
171    #[doc(no_inline)]
172    pub use crate::{
173        IterableDataProvider, IterableDynamicDataProvider, request::DataIdentifierCow,
174    };
175
176    #[doc(no_inline)]
177    pub use icu_locale_core;
178    #[doc(no_inline)]
179    pub use yoke;
180    #[doc(no_inline)]
181    pub use zerofrom;
182}
183
184#[doc(hidden)] // internal
185pub mod fallback;
186
187#[doc(hidden)] // internal
188#[cfg(feature = "logging")]
189pub use log;
190
191#[doc(hidden)] // internal
192#[cfg(all(
193    not(feature = "logging"),
194    all(debug_assertions, feature = "alloc", not(target_os = "none"))
195))]
196pub mod log {
197    extern crate std;
198    pub use std::eprintln as error;
199    pub use std::eprintln as warn;
200    pub use std::eprintln as info;
201    pub use std::eprintln as debug;
202    pub use std::eprintln as trace;
203}
204
205#[cfg(all(
206    not(feature = "logging"),
207    not(all(debug_assertions, feature = "alloc", not(target_os = "none"),))
208))]
209#[doc(hidden)] // internal
210pub mod log {
211    #[macro_export]
212    macro_rules! _internal_noop_log {
213        ($($t:expr),*) => {};
214    }
215    pub use crate::_internal_noop_log as error;
216    pub use crate::_internal_noop_log as warn;
217    pub use crate::_internal_noop_log as info;
218    pub use crate::_internal_noop_log as debug;
219    pub use crate::_internal_noop_log as trace;
220}
221
222#[test]
223fn test_logging() {
224    // This should compile on all combinations of features
225    crate::log::info!("Hello World");
226}