Skip to content
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

Move internal fallback option to baked exporter options #5036

Merged
merged 11 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 43 additions & 70 deletions provider/baked/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@
//! // Export something
//! DatagenDriver::new()
//! .with_markers([icu_provider::hello_world::HelloWorldV1Marker::INFO])
//! .with_locales_and_fallback([LocaleFamily::FULL], {
//! let mut options = FallbackOptions::default();
//! // HelloWorldProvider cannot provide fallback data, so we cannot deduplicate
//! options.deduplication_strategy = Some(DeduplicationStrategy::None);
//! options
//! })
//! // HelloWorldProvider cannot provide fallback data, so we cannot deduplicate
//! .with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
//! .export(&icu_provider::hello_world::HelloWorldProvider, exporter)
//! .unwrap();
//! #
Expand Down Expand Up @@ -132,6 +128,9 @@ fn maybe_msrv() -> TokenStream {
#[non_exhaustive]
#[derive(Debug, Clone, Copy)]
pub struct Options {
/// By default, baked providers perform fallback internally. This field can be used to
/// disable this behavior.
pub with_fallback: bool,
/// Whether to run `rustfmt` on the generated files.
pub pretty: bool,
/// Whether to use separate crates to name types instead of the `icu` metacrate.
Expand All @@ -145,10 +144,10 @@ pub struct Options {
pub overwrite: bool,
}

#[allow(clippy::derivable_impls)] // want to be explicit about bool defaults
impl Default for Options {
fn default() -> Self {
Self {
with_fallback: true,
pretty: false,
use_separate_crates: false,
overwrite: false,
Expand All @@ -163,6 +162,7 @@ pub struct BakedExporter {
mod_directory: PathBuf,
pretty: bool,
use_separate_crates: bool,
with_fallback: bool,
// Temporary storage for put_payload: marker -> (bake -> {(locale, marker_attributes)})
data: Mutex<
HashMap<
Expand Down Expand Up @@ -191,6 +191,7 @@ impl BakedExporter {
/// Constructs a new [`BakedExporter`] with the given output directory and options.
pub fn new(mod_directory: PathBuf, options: Options) -> Result<Self, DataError> {
let Options {
with_fallback,
pretty,
use_separate_crates,
overwrite,
Expand All @@ -208,6 +209,7 @@ impl BakedExporter {
Ok(Self {
mod_directory,
pretty,
with_fallback,
use_separate_crates,
data: Default::default(),
impl_data: Default::default(),
Expand Down Expand Up @@ -436,32 +438,6 @@ impl DataExporter for BakedExporter {
}

fn flush(&self, marker: DataMarkerInfo) -> Result<(), DataError> {
self.flush_internal(marker, None)
}

fn flush_with_built_in_fallback(
&self,
marker: DataMarkerInfo,
fallback_mode: BuiltInFallbackMode,
) -> Result<(), DataError> {
self.flush_internal(marker, Some(fallback_mode))
}

fn close(&mut self) -> Result<(), DataError> {
self.close_internal()
}

fn supports_built_in_fallback(&self) -> bool {
true
}
}

impl BakedExporter {
fn flush_internal(
&self,
marker: DataMarkerInfo,
fallback_mode: Option<BuiltInFallbackMode>,
) -> Result<(), DataError> {
let marker_bake = bake_marker(marker, &self.dependencies);

let (struct_type, into_data_payload) = if marker_bake
Expand Down Expand Up @@ -545,9 +521,12 @@ impl BakedExporter {

let lookup = crate::binary_search::bake(&struct_type, values);

let load_body = match fallback_mode {
None => {
quote! {
let load_body = if !self.with_fallback
|| deduplicated_values
.iter()
.all(|(_, reqs)| reqs.iter().all(|(l, _)| l.is_und()))
{
quote! {
#(#structs)*
#lookup

Expand All @@ -559,44 +538,38 @@ impl BakedExporter {
} else {
Err(icu_provider::DataErrorKind::MissingLocale.with_req(<#marker_bake as icu_provider::DataMarker>::INFO, req))
}
}
}
Some(BuiltInFallbackMode::Standard) => {
self.dependencies.insert("icu_locale/compiled_data");
quote! {
#(#structs)*
#lookup
} else {
self.dependencies.insert("icu_locale/compiled_data");
quote! {
#(#structs)*
#lookup

let mut metadata = icu_provider::DataResponseMetadata::default();
let mut metadata = icu_provider::DataResponseMetadata::default();

let payload = if let Some(payload) = lookup(req) {
payload
} else {
const FALLBACKER: icu_locale::fallback::LocaleFallbackerWithConfig<'static> =
icu_locale::fallback::LocaleFallbacker::new()
.for_config(<#marker_bake as icu_provider::DataMarker>::INFO.fallback_config);
let mut fallback_iterator = FALLBACKER.fallback_for(req.locale.clone());
loop {
if let Some(payload) = lookup(icu_provider::DataRequest { locale: fallback_iterator.get(), ..req }) {
metadata.locale = Some(fallback_iterator.take());
break payload;
}
if fallback_iterator.get().is_und() {
return Err(icu_provider::DataErrorKind::MissingLocale.with_req(<#marker_bake as icu_provider::DataMarker>::INFO, req));
}
fallback_iterator.step();
let payload = if let Some(payload) = lookup(req) {
payload
} else {
const FALLBACKER: icu_locale::fallback::LocaleFallbackerWithConfig<'static> =
icu_locale::fallback::LocaleFallbacker::new()
.for_config(<#marker_bake as icu_provider::DataMarker>::INFO.fallback_config);
let mut fallback_iterator = FALLBACKER.fallback_for(req.locale.clone());
loop {
if let Some(payload) = lookup(icu_provider::DataRequest { locale: fallback_iterator.get(), ..req }) {
metadata.locale = Some(fallback_iterator.take());
break payload;
}
};
if fallback_iterator.get().is_und() {
return Err(icu_provider::DataErrorKind::MissingLocale.with_req(<#marker_bake as icu_provider::DataMarker>::INFO, req));
}
fallback_iterator.step();
}
};

Ok(icu_provider::DataResponse {
payload: #into_data_payload,
metadata
})
}
}
f => {
return Err(DataError::custom("Unknown fallback mode")
.with_display_context(&format!("{f:?}")))
Ok(icu_provider::DataResponse {
payload: #into_data_payload,
metadata
})
}
};

Expand Down Expand Up @@ -650,7 +623,7 @@ impl BakedExporter {
)
}

fn close_internal(&mut self) -> Result<(), DataError> {
fn close(&mut self) -> Result<(), DataError> {
log::info!("Writing macros module...");

let data = move_out!(self.impl_data).into_inner().expect("poison");
Expand Down
4 changes: 2 additions & 2 deletions provider/blob/benches/auxkey_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn make_blob_v1() -> Vec<u8> {
let exporter = BlobExporter::new_with_sink(Box::new(&mut blob));
DatagenDriver::new()
.with_markers(skeleton_markers!(marker_array_cb))
.with_locales_and_fallback([LocaleFamily::FULL], Default::default())
.with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
.export(&Baked, exporter)
.unwrap();
assert_eq!(blob.len(), 450725);
Expand All @@ -105,7 +105,7 @@ fn make_blob_v2() -> Vec<u8> {
let exporter = BlobExporter::new_v2_with_sink(Box::new(&mut blob));
DatagenDriver::new()
.with_markers(skeleton_markers!(marker_array_cb))
.with_locales_and_fallback([LocaleFamily::FULL], Default::default())
.with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
.export(&Baked, exporter)
.unwrap();
assert_eq!(blob.len(), 241278);
Expand Down
3 changes: 2 additions & 1 deletion provider/blob/src/export/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
//! // Export something
//! DatagenDriver::new()
//! .with_markers([icu_provider::hello_world::HelloWorldV1Marker::INFO])
//! .with_locales_and_fallback([LocaleFamily::FULL], Default::default())
//! // HelloWorldProvider cannot provide fallback data, so we cannot deduplicate
//! .with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
//! .export(&icu_provider::hello_world::HelloWorldProvider, exporter)
//! .unwrap();
//!
Expand Down
4 changes: 2 additions & 2 deletions provider/blob/tests/test_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const BLOB_V2: &[u8] = include_bytes!("data/v2.postcard");
fn run_driver(exporter: BlobExporter) -> Result<(), DataError> {
DatagenDriver::new()
.with_markers([icu_provider::hello_world::HelloWorldV1Marker::INFO])
.with_locales_and_fallback([LocaleFamily::FULL], Default::default())
.with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
.export(&icu_provider::hello_world::HelloWorldProvider, exporter)
}

Expand Down Expand Up @@ -80,7 +80,7 @@ fn test_v2_bigger() {
let exporter = BlobExporter::new_v2_with_sink(Box::new(&mut blob));
DatagenDriver::new()
.with_markers([icu_provider::hello_world::HelloWorldV1Marker::INFO])
.with_locales_and_fallback([LocaleFamily::FULL], Default::default())
.with_locales_and_fallback([LocaleFamily::FULL], FallbackOptions::no_deduplication())
.export(&ManyLocalesProvider, exporter)
.unwrap();

Expand Down
54 changes: 0 additions & 54 deletions provider/core/src/datagen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ pub use payload::{ExportBox, ExportMarker};

use crate::prelude::*;

/// The type of built-in fallback that the data was generated for, if applicable.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BuiltInFallbackMode {
/// Data uses full UTS 35 fallbacking.
Standard,
}

/// An object capable of exporting data payloads in some form.
pub trait DataExporter: Sync {
/// Save a `payload` corresponding to the given marker and locale.
Expand All @@ -52,20 +44,6 @@ pub trait DataExporter: Sync {
self.flush(marker)
}

/// Function called after a non-singleton marker has been fully enumerated,
/// flushing that marker with built-in fallback.
///
/// Takes non-mut self as it can be called concurrently.
fn flush_with_built_in_fallback(
&self,
_marker: DataMarkerInfo,
_fallback_mode: BuiltInFallbackMode,
) -> Result<(), DataError> {
Err(DataError::custom(
"Exporter does not implement built-in fallback",
))
}

/// Function called after a non-singleton marker has been fully enumerated.
/// Does not include built-in fallback.
///
Expand All @@ -80,12 +58,6 @@ pub trait DataExporter: Sync {
fn close(&mut self) -> Result<(), DataError> {
Ok(())
}

/// Returns whether the provider supports built-in fallback. If `true`, the provider must
/// implement [`Self::flush_with_built_in_fallback()`].
fn supports_built_in_fallback(&self) -> bool {
false
}
}

impl DataExporter for Box<dyn DataExporter> {
Expand All @@ -107,25 +79,13 @@ impl DataExporter for Box<dyn DataExporter> {
(**self).flush_singleton(marker, payload)
}

fn flush_with_built_in_fallback(
&self,
marker: DataMarkerInfo,
fallback_mode: BuiltInFallbackMode,
) -> Result<(), DataError> {
(**self).flush_with_built_in_fallback(marker, fallback_mode)
}

fn flush(&self, marker: DataMarkerInfo) -> Result<(), DataError> {
(**self).flush(marker)
}

fn close(&mut self) -> Result<(), DataError> {
(**self).close()
}

fn supports_built_in_fallback(&self) -> bool {
(**self).supports_built_in_fallback()
}
}

/// A [`DynamicDataProvider`] that can be used for exporting data.
Expand Down Expand Up @@ -229,21 +189,7 @@ impl DataExporter for MultiExporter {
self.0.iter().try_for_each(|e| e.flush(marker))
}

fn flush_with_built_in_fallback(
&self,
marker: DataMarkerInfo,
fallback_mode: BuiltInFallbackMode,
) -> Result<(), DataError> {
self.0
.iter()
.try_for_each(|e| e.flush_with_built_in_fallback(marker, fallback_mode))
}

fn close(&mut self) -> Result<(), DataError> {
self.0.iter_mut().try_for_each(|e| e.close())
}

fn supports_built_in_fallback(&self) -> bool {
self.0.iter().all(|e| e.supports_built_in_fallback())
}
}
2 changes: 1 addition & 1 deletion provider/datagen/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading