-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example of baked data crate with macros #2992
Changes from all commits
67a3643
9f6a7ac
3c377cb
36af27e
b1f10cc
59656e1
3ceaf7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "globaldata" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dev-dependencies] | ||
icu_provider = { path = "../../provider/core" } | ||
icu_locid = { path = "../../components/locid" } | ||
|
||
[features] | ||
custom_data = [] | ||
all_features_hack = [] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#[macro_export] | ||
macro_rules! data_core_helloworld_v1_bn { | ||
() => { | ||
icu_provider::hello_world::HelloWorldV1 { | ||
message: alloc::borrow::Cow::Borrowed("ওহে বিশ\u{9cd}ব"), | ||
} | ||
}; | ||
} | ||
|
||
pub use data_core_helloworld_v1_bn; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#[macro_export] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrapping each data expression in a macro is a lot of cognitive overhead, and probably also compile time overhead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cognitive overhead is being moved from the call site (people need to learn how data providers work) to an internal crate (that only us and power users will see). |
||
macro_rules! data_core_helloworld_v1_en { | ||
() => { | ||
icu_provider::hello_world::HelloWorldV1 { | ||
message: alloc::borrow::Cow::Borrowed("Hello World"), | ||
} | ||
} | ||
} | ||
|
||
pub use data_core_helloworld_v1_en; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#[macro_export] | ||
macro_rules! data_core_helloworld_v1_ja { | ||
() => { | ||
icu_provider::hello_world::HelloWorldV1 { | ||
message: alloc::borrow::Cow::Borrowed("こんにちは世界"), | ||
} | ||
} | ||
} | ||
|
||
pub use data_core_helloworld_v1_ja; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
include!("bn.data.rs"); | ||
include!("en.data.rs"); | ||
include!("ja.data.rs"); | ||
include!("ru.data.rs"); | ||
|
||
#[macro_export] | ||
macro_rules! impl_core_helloworld_v1 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the plan for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should "just work" struct LocalBakedProvider;
impl_core_helloworld_v1!(LocalBakedProvider);
impl_decimal_symbols_v1!(LocalBakedProvider);
impl_any_provider!(LocalBakedProvider, [
icu_provider::hello_world::HelloWorldV1Marker,
icu_decimal::provider::SymbolsV1Marker,
]); |
||
($provider:path) => { | ||
impl DataProvider<icu_provider::hello_world::HelloWorldV1Marker> for $provider { | ||
fn load(&self, req: DataRequest) -> Result<DataResponse<icu_provider::hello_world::HelloWorldV1Marker>, DataError> { | ||
type DataStruct = | ||
<icu_provider::hello_world::HelloWorldV1Marker as icu_provider::DataMarker>::Yokeable; | ||
static KEYS: &[&str] = &["bn", "en", "en-US", "ja", "ru"]; | ||
static BN: DataStruct = $crate::baked::core_helloworld_v1::data_core_helloworld_v1_bn!(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works, but it will be hard to generate because you're using the absolute path of where this will be included, e.g. it has to be included at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The path is relative to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be useful if the logic we add here is also usable by datagen clients, not only for this crate. |
||
static EN: DataStruct = $crate::baked::core_helloworld_v1::data_core_helloworld_v1_en!(); | ||
static JA: DataStruct = $crate::baked::core_helloworld_v1::data_core_helloworld_v1_ja!(); | ||
static RU: DataStruct = $crate::baked::core_helloworld_v1::data_core_helloworld_v1_ru!(); | ||
static DATA: &[&DataStruct] = &[&BN, &EN, &EN, &JA, &RU]; | ||
KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()) | ||
.ok() | ||
.map(|i| unsafe { *DATA.get_unchecked(i) }) | ||
.map(zerofrom::ZeroFrom::zero_from) | ||
.map(DataPayload::from_owned) | ||
.map(|payload| DataResponse { | ||
metadata: Default::default(), | ||
payload: Some(payload), | ||
}) | ||
.ok_or_else(|| DataErrorKind::MissingLocale.with_req(icu_provider::hello_world::HelloWorldV1Marker::KEY, req)) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
pub use impl_core_helloworld_v1; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#[macro_export] | ||
macro_rules! data_core_helloworld_v1_ru { | ||
() => { | ||
icu_provider::hello_world::HelloWorldV1 { | ||
message: alloc::borrow::Cow::Borrowed("Привет, мир"), | ||
} | ||
} | ||
} | ||
|
||
pub use data_core_helloworld_v1_ru; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod core_helloworld_v1; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#![allow(unused_imports)] | ||
#![allow(unused_macros)] | ||
|
||
extern crate alloc; | ||
|
||
#[doc(hidden)] | ||
pub mod baked { | ||
#[cfg(all(feature = "custom_data", not(feature = "all_features_hack")))] | ||
include!(env!("ICU4X_MACROINCLUDE_PATH")); | ||
#[cfg(any(not(feature = "custom_data"), feature = "all_features_hack"))] | ||
include!("data/mod.rs"); | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use icu_provider::prelude::*; | ||
|
||
#[test] | ||
fn test() { | ||
use baked::core_helloworld_v1::*; | ||
struct BakedProvider; | ||
impl_core_helloworld_v1!(BakedProvider); | ||
|
||
assert_eq!( | ||
"こんにちは世界", | ||
icu_provider::hello_world::HelloWorldFormatter::try_new_unstable( | ||
&BakedProvider, | ||
&icu_locid::locale!("ja").into(), | ||
) | ||
.unwrap() | ||
.format_to_string() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -238,6 +238,31 @@ impl HelloWorldFormatter { | |
|
||
crate::gen_any_buffer_constructors!(locale: include, options: skip, error: DataError); | ||
|
||
/// Creates a new [`HelloWorldFormatter`] with global data. | ||
/// | ||
/// Requires the "globaldata" Cargo feature. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use icu_provider::hello_world::HelloWorldFormatter; | ||
/// use icu_locid::locale; | ||
/// | ||
/// let formatter = HelloWorldFormatter::try_new(&locale!("ja").into()).unwrap(); | ||
/// | ||
/// assert_eq!( | ||
/// "こんにちは世界", | ||
/// formatter.format_to_string() | ||
/// ); | ||
/// ``` | ||
#[cfg(feature = "globaldata")] | ||
pub fn try_new(locale: &DataLocale) -> Result<Self, DataError> { | ||
struct LocalBakedProvider; | ||
use crate as icu_provider; | ||
globaldata::impl_core_helloworld_v1!(LocalBakedProvider); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An open question is how to enable vertical fallback. An easy way, which is probably fine, is let provider = globaldata::with_vertical_fallback!(LocalBakedProvider); and the macro has two versions: one that is a no-op, and one that is enabled with the |
||
Self::try_new_unstable(&LocalBakedProvider, locale) | ||
} | ||
|
||
/// Formats a hello world message, returning a [`FormattedHelloWorld`]. | ||
#[allow(clippy::needless_lifetimes)] // documentary example | ||
pub fn format<'l>(&'l self) -> FormattedHelloWorld<'l> { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(reminder to remove this line)