| 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 | |
| 134 | extern crate alloc; |
| 135 | |
| 136 | mod data_provider; |
| 137 | mod error; |
| 138 | #[doc (hidden)] |
| 139 | pub mod fallback; |
| 140 | mod key; |
| 141 | mod request; |
| 142 | mod response; |
| 143 | |
| 144 | pub mod any; |
| 145 | pub mod buf; |
| 146 | pub mod constructors; |
| 147 | #[cfg (feature = "datagen" )] |
| 148 | pub mod datagen; |
| 149 | pub mod dynutil; |
| 150 | pub mod hello_world; |
| 151 | pub mod marker; |
| 152 | #[cfg (feature = "serde" )] |
| 153 | pub mod serde; |
| 154 | |
| 155 | // Types from private modules |
| 156 | pub use crate::data_provider::BoundDataProvider; |
| 157 | pub use crate::data_provider::DataProvider; |
| 158 | pub use crate::data_provider::DataProviderWithKey; |
| 159 | pub use crate::data_provider::DynamicDataProvider; |
| 160 | pub use crate::error::DataError; |
| 161 | pub use crate::error::DataErrorKind; |
| 162 | pub use crate::key::DataKey; |
| 163 | pub use crate::key::DataKeyHash; |
| 164 | pub use crate::key::DataKeyMetadata; |
| 165 | pub use crate::key::DataKeyPath; |
| 166 | #[cfg (feature = "experimental" )] |
| 167 | pub use crate::request::AuxiliaryKeys; |
| 168 | pub use crate::request::DataLocale; |
| 169 | pub use crate::request::DataRequest; |
| 170 | pub use crate::request::DataRequestMetadata; |
| 171 | pub use crate::response::Cart; |
| 172 | pub use crate::response::DataPayload; |
| 173 | pub use crate::response::DataPayloadOr; |
| 174 | pub use crate::response::DataResponse; |
| 175 | pub use crate::response::DataResponseMetadata; |
| 176 | #[cfg (feature = "macros" )] |
| 177 | pub use icu_provider_macros::data_struct; |
| 178 | |
| 179 | // Reexports from public modules |
| 180 | pub use crate::any::AnyMarker; |
| 181 | pub use crate::any::AnyPayload; |
| 182 | pub use crate::any::AnyProvider; |
| 183 | pub use crate::any::AnyResponse; |
| 184 | pub use crate::any::AsDowncastingAnyProvider; |
| 185 | pub use crate::any::AsDynamicDataProviderAnyMarkerWrap; |
| 186 | pub use crate::any::MaybeSendSync; |
| 187 | pub use crate::buf::BufferMarker; |
| 188 | pub use crate::buf::BufferProvider; |
| 189 | pub use crate::marker::DataMarker; |
| 190 | pub use crate::marker::KeyedDataMarker; |
| 191 | pub use crate::marker::NeverMarker; |
| 192 | #[cfg (feature = "serde" )] |
| 193 | pub use crate::serde::AsDeserializingBufferProvider; |
| 194 | |
| 195 | /// Core selection of APIs and structures for the ICU4X data provider. |
| 196 | pub 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)] |
| 260 | pub use fallback::LocaleFallbackPriority as FallbackPriority; |
| 261 | #[doc (hidden)] |
| 262 | pub use fallback::LocaleFallbackSupplement as FallbackSupplement; |
| 263 | #[doc (hidden)] |
| 264 | pub use yoke; |
| 265 | #[doc (hidden)] |
| 266 | pub use zerofrom; |
| 267 | |
| 268 | // For macros |
| 269 | #[doc (hidden)] |
| 270 | pub 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 ] |
| 304 | fn test_logging() { |
| 305 | // This should compile on all combinations of features |
| 306 | crate::_internal::log::info!("Hello World" ); |
| 307 | } |
| 308 | |