summaryrefslogtreecommitdiffstats
path: root/vendor/icu_provider/src/constructors.rs
blob: 053da03205a0080c7692e236d91e343a74211f3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

//! 📚 *This module documents ICU4X constructor signatures.*
//!
//! One of the key differences between ICU4X and its parent projects, ICU4C and ICU4J, is in how
//! it deals with locale data.
//!
//! In ICU4X, the data provider is an *explicit argument* whenever it is required by the library.
//! This enables ICU4X to achieve the following value propositions:
//!
//! 1. Configurable data sources (machine-readable data file, baked into code, JSON, etc).
//! 2. Dynamic data loading at runtime (load data on demand).
//! 3. Reduced overhead and code size (data is resolved locally at each call site).
//! 4. Explicit support for multiple ICU4X instances sharing data.
//!
//! In order to achieve these goals, there are 3 versions of all Rust ICU4X functions that
//! take a data provider argument:
//!
//! 1. `*_unstable`
//! 2. `*_with_any_provider`
//! 3. `*_with_buffer_provider`
//!
//! # Which constructor should I use?
//!
//! ## When to use `*_unstable`
//!
//! Use this constructor if your data provider implements the [`DataProvider`] trait for all
//! data structs in *current and future* ICU4X versions. Examples:
//!
//! 1. `BakedDataProvider` auto-regenerated on new ICU4X versions
//! 2. Anything with a _blanket_ [`DataProvider`] impl
//!
//! Since the exact set of bounds may change at any time, including in minor SemVer releases,
//! it is the client's responsibility to guarantee that the requirement is upheld.
//!
//! ## When to use `*_with_any_provider`
//!
//! Use this constructor if you need to use a provider that implements [`AnyProvider`] but not
//! [`DataProvider`]. Examples:
//!
//! 1. [`AnyPayloadProvider`]
//! 2. [`ForkByKeyProvider`] between two providers implementing [`AnyProvider`]
//! 3. Providers that cache or override certain keys but not others and therefore
//!    can't implement [`DataProvider`]
//!
//! ## When to use `*_with_buffer_provider`
//!
//! Use this constructor if your data originates as byte buffers that need to be deserialized.
//! All such providers should implement [`BufferProvider`]. Examples:
//!
//! 1. [`BlobDataProvider`]
//! 2. [`FsDataProvider`]
//! 3. [`ForkByKeyProvider`] between any of the above
//!
//! Please note that you must enable the `"serde"` Cargo feature on each crate in which you use the
//! `*_with_buffer_provider` constructor.
//!
//! # Data Versioning Policy
//!
//! The `*_with_any_provider` and `*_with_buffer_provider` functions will succeed to compile and
//! run if given a data provider supporting all of the keys required for the object being
//! constructed, either the current or any previous version within the same SemVer major release.
//! For example, if a data file is built to support FooFormatter version 1.1, then FooFormatter
//! version 1.2 will be able to read the same data file. Likewise, backwards-compatible keys can
//! always be included by `icu_datagen` to support older library versions.
//!
//! The `*_unstable` functions are only guaranteed to work on data built for the exact same version
//! of ICU4X. The advantage of the `*_unstable` functions is that they result in the smallest code
//! size and allow for automatic data slicing when `BakedDataProvider` is used. However, the type
//! bounds of this function may change over time, breaking SemVer guarantees. These functions
//! should therefore only be used when you have full control over your data lifecycle at compile
//! time.
//!
//! # Data Providers Over FFI
//!
//! Over FFI, there is only one data provider type: [`ICU4XDataProvider`]. Internally, it is an
//! `enum` between `dyn `[`AnyProvider`] and `dyn `[`BufferProvider`].
//!
//! To control for code size, there are two Cargo features, `any_provider` and `buffer_provider`,
//! that enable the corresponding items in the enum.
//!
//! In Rust ICU4X, a similar buffer/any enum approach was not taken because:
//!
//! 1. Feature-gating the enum branches gets complex across crates.
//! 2. Without feature gating, users need to carry Serde code even if they're not using it,
//!    violating one of the core value propositions of ICU4X.
//! 3. We could reduce the number of constructors from 3 to 2 but not to 1, so the educational
//!    benefit is limited.
//!
//!
//! [`DataProvider`]: crate::DataProvider
//! [`BufferProvider`]: crate::BufferProvider
//! [`AnyProvider`]: crate::AnyProvider
//! [`AnyPayloadProvider`]: ../../icu_provider_adapters/any_payload/struct.AnyPayloadProvider.html
//! [`ForkByKeyProvider`]: ../../icu_provider_adapters/fork/struct.ForkByKeyProvider.html
//! [`BlobDataProvider`]: ../../icu_provider_blob/struct.BlobDataProvider.html
//! [`StaticDataProvider`]: ../../icu_provider_blob/struct.StaticDataProvider.html
//! [`FsDataProvider`]: ../../icu_provider_blob/struct.FsDataProvider.html
//! [`ICU4XDataProvider`]: ../../icu_capi/provider/ffi/struct.ICU4XDataProvider.html