• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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")]
98 extern crate alloc;
99 
100 pub mod buf;
101 pub mod constructors;
102 pub mod dynutil;
103 #[cfg(feature = "export")]
104 pub mod export;
105 #[cfg(feature = "alloc")]
106 pub mod hello_world;
107 
108 // TODO: put this in a separate crate
109 #[cfg(all(feature = "serde", feature = "alloc"))]
110 #[doc(hidden)]
111 pub mod serde_borrow_de_utils;
112 
113 mod data_provider;
114 pub use data_provider::{
115     BoundDataProvider, DataProvider, DataProviderWithMarker, DryDataProvider, DynamicDataProvider,
116     DynamicDryDataProvider,
117 };
118 #[cfg(feature = "alloc")]
119 pub use data_provider::{IterableDataProvider, IterableDynamicDataProvider};
120 
121 mod error;
122 pub use error::{DataError, DataErrorKind, ResultDataError};
123 
124 mod request;
125 pub use request::{DataLocale, DataMarkerAttributes, DataRequest, DataRequestMetadata, *};
126 
127 mod response;
128 #[doc(hidden)] // TODO(#4467): establish this as an internal API
129 pub use response::DataPayloadOr;
130 pub use response::{Cart, DataPayload, DataResponse, DataResponseMetadata};
131 
132 #[path = "marker.rs"]
133 mod marker_full;
134 
135 pub use marker_full::{data_marker, DataMarker, DataMarkerInfo, DynamicDataMarker};
136 pub mod marker {
137     //! Additional [`DataMarker`](super::DataMarker) helpers.
138 
139     pub use super::marker_full::{
140         data_marker_id, impl_data_provider_never_marker, DataMarkerExt, DataMarkerId,
141         DataMarkerIdHash, ErasedMarker, NeverMarker,
142     };
143 }
144 
145 mod varule_traits;
146 pub mod ule {
147     //! Traits that data provider implementations can use to optimize storage
148     //! by using [`VarULE`](zerovec::ule::VarULE).
149     //!
150     //! See [`MaybeAsVarULE`] for details.
151 
152     pub use super::varule_traits::MaybeAsVarULE;
153     pub use super::varule_traits::MaybeEncodeAsVarULE;
154 }
155 
156 pub use varule_traits::data_struct;
157 
158 /// Core selection of APIs and structures for the ICU4X data provider.
159 pub mod prelude {
160     #[doc(no_inline)]
161     #[cfg(feature = "serde")]
162     pub use crate::buf::AsDeserializingBufferProvider;
163     #[doc(no_inline)]
164     pub use crate::buf::{BufferMarker, BufferProvider};
165     pub use crate::request::*;
166     #[doc(no_inline)]
167     pub use crate::{
168         data_marker, marker::DataMarkerExt, BoundDataProvider, DataError, DataErrorKind,
169         DataLocale, DataMarker, DataMarkerAttributes, DataMarkerInfo, DataPayload, DataProvider,
170         DataRequest, DataRequestMetadata, DataResponse, DataResponseMetadata, DryDataProvider,
171         DynamicDataMarker, DynamicDataProvider, DynamicDryDataProvider, ResultDataError,
172     };
173     #[cfg(feature = "alloc")]
174     pub use crate::{IterableDataProvider, IterableDynamicDataProvider};
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
185 pub mod fallback;
186 
187 #[doc(hidden)] // internal
188 #[cfg(feature = "logging")]
189 pub use log;
190 
191 #[doc(hidden)] // internal
192 #[cfg(all(not(feature = "logging"), debug_assertions, not(target_os = "none")))]
193 pub mod log {
194     extern crate std;
195     pub use std::eprintln as error;
196     pub use std::eprintln as warn;
197     pub use std::eprintln as info;
198     pub use std::eprintln as debug;
199     pub use std::eprintln as trace;
200 }
201 
202 #[cfg(all(
203     not(feature = "logging"),
204     any(not(debug_assertions), target_os = "none")
205 ))]
206 #[doc(hidden)] // internal
207 pub mod log {
208     #[macro_export]
209     macro_rules! _internal_noop_log {
210         ($($t:expr),*) => {};
211     }
212     pub use crate::_internal_noop_log as error;
213     pub use crate::_internal_noop_log as warn;
214     pub use crate::_internal_noop_log as info;
215     pub use crate::_internal_noop_log as debug;
216     pub use crate::_internal_noop_log as trace;
217 }
218 
219 #[test]
test_logging()220 fn test_logging() {
221     // This should compile on all combinations of features
222     crate::log::info!("Hello World");
223 }
224