From 2032a4b05a2c774d9b55ce1259b7e4d5ffbdda96 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 17 Aug 2021 19:31:32 -0500 Subject: [PATCH 01/17] Eliminate low-hanging fruit for code size of FFI example --- Cargo.lock | 1 + ffi/capi/Cargo.toml | 1 + ffi/capi/examples/fixeddecimal/test.c | 10 +- ffi/capi/include/ICU4XFixedDecimalFormat.h | 3 + ffi/capi/include/ICU4XLocale.h | 4 + ffi/capi/src/decimal.rs | 77 +++++ ffi/capi/src/locale.rs | 10 + ffi/cpp/include/ICU4XFixedDecimalFormat.h | 3 + ffi/cpp/include/ICU4XFixedDecimalFormat.hpp | 15 + ffi/cpp/include/ICU4XLocale.h | 4 + ffi/cpp/include/ICU4XLocale.hpp | 8 + ffi/wasm/docs.rst | 332 ++++++++++++++++++++ ffi/wasm/lib/api.mjs | 94 ++++++ 13 files changed, 557 insertions(+), 5 deletions(-) create mode 100644 ffi/wasm/docs.rst diff --git a/Cargo.lock b/Cargo.lock index a843fde6b32..64039561bb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -982,6 +982,7 @@ dependencies = [ "icu_decimal", "icu_locale_canonicalizer", "icu_locid", + "icu_locid_macros", "icu_plurals", "icu_provider", "icu_provider_fs", diff --git a/ffi/capi/Cargo.toml b/ffi/capi/Cargo.toml index 3f3e3b692c3..b747fb071dc 100644 --- a/ffi/capi/Cargo.toml +++ b/ffi/capi/Cargo.toml @@ -61,6 +61,7 @@ fixed_decimal = { path = "../../utils/fixed_decimal" } icu_decimal = { path = "../../components/decimal/" } icu_locale_canonicalizer = { path = "../../components/locale_canonicalizer" } icu_locid = { path = "../../components/locid" } +icu_locid_macros = { path = "../../components/locid/macros" } icu_plurals = { path = "../../components/plurals/" } icu_provider = { path = "../../provider/core", features = ["provider_serde"] } tinystr = { version = "0.4.10", features = ["alloc"], default-features = false } diff --git a/ffi/capi/examples/fixeddecimal/test.c b/ffi/capi/examples/fixeddecimal/test.c index 53834fcf0f6..f55eaaef20b 100644 --- a/ffi/capi/examples/fixeddecimal/test.c +++ b/ffi/capi/examples/fixeddecimal/test.c @@ -7,18 +7,18 @@ #include int main() { - ICU4XLocale* locale = ICU4XLocale_create("bn", 2); - ICU4XCreateDataProviderResult result = ICU4XDataProvider_create_static(); + ICU4XLocale* locale = ICU4XLocale_create_bn(); + ICU4XCreateFixedDecimalFormatDataProviderResult result = ICU4XFixedDecimalFormatDataProvider_create_static(); if (!result.success) { printf("Failed to create FsDataProvider\n"); return 1; } - ICU4XDataProvider* provider = result.provider; + ICU4XFixedDecimalFormatDataProvider* provider = result.provider; ICU4XFixedDecimal* decimal = ICU4XFixedDecimal_create(1000007); ICU4XFixedDecimalFormatOptions opts = {ICU4XFixedDecimalGroupingStrategy_Auto, ICU4XFixedDecimalSignDisplay_Auto}; - ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new(locale, provider, opts); + ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new_specific(locale, provider, opts); if (!fdf_result.success) { printf("Failed to create FixedDecimalFormat\n"); return 1; @@ -91,7 +91,7 @@ int main() { ICU4XFixedDecimal_destroy(decimal); ICU4XFixedDecimalFormat_destroy(fdf); ICU4XLocale_destroy(locale); - ICU4XDataProvider_destroy(provider); + ICU4XFixedDecimalFormatDataProvider_destroy(provider); return 0; } diff --git a/ffi/capi/include/ICU4XFixedDecimalFormat.h b/ffi/capi/include/ICU4XFixedDecimalFormat.h index 83e53df2b68..9c4a9f89e28 100644 --- a/ffi/capi/include/ICU4XFixedDecimalFormat.h +++ b/ffi/capi/include/ICU4XFixedDecimalFormat.h @@ -15,11 +15,14 @@ typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat; #include "ICU4XDataProvider.h" #include "ICU4XFixedDecimalFormatOptions.h" #include "ICU4XFixedDecimalFormatResult.h" +#include "ICU4XFixedDecimalFormatDataProvider.h" #include "ICU4XFixedDecimal.h" #include "result_void_void.h" ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new(const ICU4XLocale* locale, const ICU4XDataProvider* provider, ICU4XFixedDecimalFormatOptions options); +ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_specific(const ICU4XLocale* locale, const ICU4XFixedDecimalFormatDataProvider* provider, ICU4XFixedDecimalFormatOptions options); + decimal_ffi_result_void_void ICU4XFixedDecimalFormat_format(const ICU4XFixedDecimalFormat* self, const ICU4XFixedDecimal* value, DiplomatWriteable* write); void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self); diff --git a/ffi/capi/include/ICU4XLocale.h b/ffi/capi/include/ICU4XLocale.h index 1039f0a39f3..dd6866be15c 100644 --- a/ffi/capi/include/ICU4XLocale.h +++ b/ffi/capi/include/ICU4XLocale.h @@ -15,6 +15,10 @@ typedef struct ICU4XLocale ICU4XLocale; ICU4XLocale* ICU4XLocale_create(const char* name_data, size_t name_len); +ICU4XLocale* ICU4XLocale_create_en(); + +ICU4XLocale* ICU4XLocale_create_bn(); + ICU4XLocale* ICU4XLocale_clone(const ICU4XLocale* self); locale_ffi_result_void_ICU4XLocaleError ICU4XLocale_basename(const ICU4XLocale* self, DiplomatWriteable* write); diff --git a/ffi/capi/src/decimal.rs b/ffi/capi/src/decimal.rs index a39f8fabe5b..29c403e83e1 100644 --- a/ffi/capi/src/decimal.rs +++ b/ffi/capi/src/decimal.rs @@ -8,8 +8,10 @@ pub mod ffi { use diplomat_runtime::DiplomatResult; use icu_decimal::{ options::{FixedDecimalFormatOptions, GroupingStrategy, SignDisplay}, + provider::DecimalSymbolsV1Marker, FixedDecimalFormat, }; + use icu_provider::prelude::DataProvider; use writeable::Writeable; use crate::{ @@ -58,6 +60,41 @@ pub mod ffi { } } + #[diplomat::opaque] + /// A DataProvider specific to FixedDecimalFormat. + pub struct ICU4XFixedDecimalFormatDataProvider( + pub Box>, + ); + + /// A result type for `ICU4XDataProvider::create`. + pub struct ICU4XCreateFixedDecimalFormatDataProviderResult { + /// Will be `None` if `success` is `false`, do not use in that case. + pub provider: Option>, + // May potentially add a better error type in the future + pub success: bool, + } + + impl ICU4XFixedDecimalFormatDataProvider { + /// Create a DataProvider reading from static data specific to FixedDecimalFormat. + fn create_static() -> ICU4XCreateFixedDecimalFormatDataProviderResult { + #[cfg(not(feature = "provider_static"))] + unimplemented!(); + + #[cfg(feature = "provider_static")] + { + #[cfg(feature = "smaller_static")] + let provider = icu_testdata::get_smaller_static_provider(); + #[cfg(not(feature = "smaller_static"))] + let provider = icu_testdata::get_static_provider(); + let fdf_provider = Box::new(provider); + ICU4XCreateFixedDecimalFormatDataProviderResult { + provider: Some(Box::new(ICU4XFixedDecimalFormatDataProvider(fdf_provider))), + success: true, + } + } + } + } + impl ICU4XFixedDecimalFormat { /// Creates a new [`ICU4XFixedDecimalFormat`] from locale data. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. pub fn try_new( @@ -99,6 +136,46 @@ pub mod ffi { } } + /// Creates a new [`ICU4XFixedDecimalFormat`] from a data provider specific to FixedDecimalFormat. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. + fn try_new_specific( + locale: &ICU4XLocale, + provider: &ICU4XFixedDecimalFormatDataProvider, + options: ICU4XFixedDecimalFormatOptions, + ) -> ICU4XFixedDecimalFormatResult { + let langid = locale.0.as_ref().clone(); + let provider = provider.0.as_ref(); + + if let Result::Ok(fdf) = FixedDecimalFormat::try_new( + langid, + provider, + FixedDecimalFormatOptions { + grouping_strategy: match options.grouping_strategy { + ICU4XFixedDecimalGroupingStrategy::Auto => GroupingStrategy::Auto, + ICU4XFixedDecimalGroupingStrategy::Never => GroupingStrategy::Never, + ICU4XFixedDecimalGroupingStrategy::Always => GroupingStrategy::Always, + ICU4XFixedDecimalGroupingStrategy::Min2 => GroupingStrategy::Min2, + }, + sign_display: match options.sign_display { + ICU4XFixedDecimalSignDisplay::Auto => SignDisplay::Auto, + ICU4XFixedDecimalSignDisplay::Never => SignDisplay::Never, + ICU4XFixedDecimalSignDisplay::Always => SignDisplay::Always, + ICU4XFixedDecimalSignDisplay::ExceptZero => SignDisplay::ExceptZero, + ICU4XFixedDecimalSignDisplay::Negative => SignDisplay::Negative, + }, + }, + ) { + ICU4XFixedDecimalFormatResult { + fdf: Some(Box::new(ICU4XFixedDecimalFormat(fdf))), + success: true, + } + } else { + ICU4XFixedDecimalFormatResult { + fdf: None, + success: false, + } + } + } + /// Formats a [`ICU4XFixedDecimal`] to a string. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.format) for more information. pub fn format( &self, diff --git a/ffi/capi/src/locale.rs b/ffi/capi/src/locale.rs index 9941c6d81e0..d343704c645 100644 --- a/ffi/capi/src/locale.rs +++ b/ffi/capi/src/locale.rs @@ -31,6 +31,16 @@ pub mod ffi { .map(|l| Box::new(ICU4XLocale(l))) } + /// Construct an [`ICU4XLocale`] for the English language. + fn create_en() -> Box { + Box::new(ICU4XLocale(icu_locid_macros::langid!("en").into())) + } + + /// Construct an [`ICU4XLocale`] for the Bangla language. + fn create_bn() -> Box { + Box::new(ICU4XLocale(icu_locid_macros::langid!("bn").into())) + } + /// Clones the [`ICU4XLocale`]. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/locid/struct.Locale.html) for more information. #[allow(clippy::should_implement_trait)] diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormat.h b/ffi/cpp/include/ICU4XFixedDecimalFormat.h index 83e53df2b68..9c4a9f89e28 100644 --- a/ffi/cpp/include/ICU4XFixedDecimalFormat.h +++ b/ffi/cpp/include/ICU4XFixedDecimalFormat.h @@ -15,11 +15,14 @@ typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat; #include "ICU4XDataProvider.h" #include "ICU4XFixedDecimalFormatOptions.h" #include "ICU4XFixedDecimalFormatResult.h" +#include "ICU4XFixedDecimalFormatDataProvider.h" #include "ICU4XFixedDecimal.h" #include "result_void_void.h" ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new(const ICU4XLocale* locale, const ICU4XDataProvider* provider, ICU4XFixedDecimalFormatOptions options); +ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_specific(const ICU4XLocale* locale, const ICU4XFixedDecimalFormatDataProvider* provider, ICU4XFixedDecimalFormatOptions options); + decimal_ffi_result_void_void ICU4XFixedDecimalFormat_format(const ICU4XFixedDecimalFormat* self, const ICU4XFixedDecimal* value, DiplomatWriteable* write); void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self); diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp b/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp index 40dce549ea6..034344c1fe0 100644 --- a/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp +++ b/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp @@ -17,6 +17,7 @@ class ICU4XLocale; class ICU4XDataProvider; struct ICU4XFixedDecimalFormatOptions; struct ICU4XFixedDecimalFormatResult; +class ICU4XFixedDecimalFormatDataProvider; class ICU4XFixedDecimal; struct ICU4XFixedDecimalFormatDeleter { @@ -27,6 +28,7 @@ struct ICU4XFixedDecimalFormatDeleter { class ICU4XFixedDecimalFormat { public: static ICU4XFixedDecimalFormatResult try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options); + static ICU4XFixedDecimalFormatResult try_new_specific(const ICU4XLocale& locale, const ICU4XFixedDecimalFormatDataProvider& provider, ICU4XFixedDecimalFormatOptions options); template diplomat::result format_to_writeable(const ICU4XFixedDecimal& value, W& write); diplomat::result format(const ICU4XFixedDecimal& value); inline const capi::ICU4XFixedDecimalFormat* AsFFI() const { return this->inner.get(); } @@ -40,6 +42,7 @@ class ICU4XFixedDecimalFormat { #include "ICU4XDataProvider.hpp" #include "ICU4XFixedDecimalFormatOptions.hpp" #include "ICU4XFixedDecimalFormatResult.hpp" +#include "ICU4XFixedDecimalFormatDataProvider.hpp" #include "ICU4XFixedDecimal.hpp" inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options) { @@ -54,6 +57,18 @@ inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new(const ICU4 } return ICU4XFixedDecimalFormatResult{ .fdf = std::move(diplomat_optional_out_value_fdf), .success = std::move(diplomat_raw_struct_out_value.success) }; } +inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new_specific(const ICU4XLocale& locale, const ICU4XFixedDecimalFormatDataProvider& provider, ICU4XFixedDecimalFormatOptions options) { + ICU4XFixedDecimalFormatOptions diplomat_wrapped_struct_options = options; + capi::ICU4XFixedDecimalFormatResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormat_try_new_specific(locale.AsFFI(), provider.AsFFI(), capi::ICU4XFixedDecimalFormatOptions{ .grouping_strategy = static_cast(diplomat_wrapped_struct_options.grouping_strategy), .sign_display = static_cast(diplomat_wrapped_struct_options.sign_display) }); + auto diplomat_optional_raw_out_value_fdf = diplomat_raw_struct_out_value.fdf; + std::optional diplomat_optional_out_value_fdf; + if (diplomat_optional_raw_out_value_fdf != nullptr) { + diplomat_optional_out_value_fdf = ICU4XFixedDecimalFormat(diplomat_optional_raw_out_value_fdf); + } else { + diplomat_optional_out_value_fdf = std::nullopt; + } + return ICU4XFixedDecimalFormatResult{ .fdf = std::move(diplomat_optional_out_value_fdf), .success = std::move(diplomat_raw_struct_out_value.success) }; +} template inline diplomat::result ICU4XFixedDecimalFormat::format_to_writeable(const ICU4XFixedDecimal& value, W& write) { capi::DiplomatWriteable write_writer = diplomat::WriteableTrait::Construct(write); auto diplomat_result_raw_out_value = capi::ICU4XFixedDecimalFormat_format(this->inner.get(), value.AsFFI(), &write_writer); diff --git a/ffi/cpp/include/ICU4XLocale.h b/ffi/cpp/include/ICU4XLocale.h index 1039f0a39f3..dd6866be15c 100644 --- a/ffi/cpp/include/ICU4XLocale.h +++ b/ffi/cpp/include/ICU4XLocale.h @@ -15,6 +15,10 @@ typedef struct ICU4XLocale ICU4XLocale; ICU4XLocale* ICU4XLocale_create(const char* name_data, size_t name_len); +ICU4XLocale* ICU4XLocale_create_en(); + +ICU4XLocale* ICU4XLocale_create_bn(); + ICU4XLocale* ICU4XLocale_clone(const ICU4XLocale* self); locale_ffi_result_void_ICU4XLocaleError ICU4XLocale_basename(const ICU4XLocale* self, DiplomatWriteable* write); diff --git a/ffi/cpp/include/ICU4XLocale.hpp b/ffi/cpp/include/ICU4XLocale.hpp index 0a2c9deb181..12da7c95670 100644 --- a/ffi/cpp/include/ICU4XLocale.hpp +++ b/ffi/cpp/include/ICU4XLocale.hpp @@ -24,6 +24,8 @@ struct ICU4XLocaleDeleter { class ICU4XLocale { public: static std::optional create(const std::string_view name); + static ICU4XLocale create_en(); + static ICU4XLocale create_bn(); ICU4XLocale clone(); template diplomat::result basename_to_writeable(W& write); diplomat::result basename(); @@ -55,6 +57,12 @@ inline std::optional ICU4XLocale::create(const std::string_view nam } return diplomat_optional_out_value; } +inline ICU4XLocale ICU4XLocale::create_en() { + return ICU4XLocale(capi::ICU4XLocale_create_en()); +} +inline ICU4XLocale ICU4XLocale::create_bn() { + return ICU4XLocale(capi::ICU4XLocale_create_bn()); +} inline ICU4XLocale ICU4XLocale::clone() { return ICU4XLocale(capi::ICU4XLocale_clone(this->inner.get())); } diff --git a/ffi/wasm/docs.rst b/ffi/wasm/docs.rst new file mode 100644 index 00000000000..4f523315679 --- /dev/null +++ b/ffi/wasm/docs.rst @@ -0,0 +1,332 @@ + +.. js:class:: ICU4XCanonicalizationResult + + + FFI version of ``CanonicalizationResult``. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XCreateDataProviderResult + + + A result type for ``ICU4XDataProvider::create``. + + .. js:attribute:: provider + + + Will be ``None`` if ``success`` is ``false``, do not use in that case. + + .. js:attribute:: success + + + +.. js:class:: ICU4XCreateFixedDecimalFormatDataProviderResult + + + A result type for ``ICU4XDataProvider::create``. + + .. js:attribute:: provider + + + Will be ``None`` if ``success`` is ``false``, do not use in that case. + + .. js:attribute:: success + + + +.. js:class:: ICU4XCreateFixedDecimalResult + + + + .. js:attribute:: fd + + + Will be None if ``success`` is ``false`` + + .. js:attribute:: success + + + Currently just a boolean, but we might add a proper error enum as necessary + +.. js:class:: ICU4XCreatePluralOperandsResult + + + This is the result returned by ``ICU4XPluralOperands::create()`` See `the Rust docs `__ for more details. + + .. js:attribute:: operands + + + + .. js:attribute:: success + + + +.. js:class:: ICU4XCreatePluralRulesResult + + + + .. js:attribute:: rules + + + + .. js:attribute:: success + + + +.. js:class:: ICU4XDataProvider + + + An ICU4X data provider, capable of loading ICU4X data keys from some source. See `the Rust docs `__ for more information. + + .. js:staticfunction:: create_fs(path) + + Constructs an ``FsDataProvider`` and retirns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + + .. js:staticfunction:: create_static() + + Constructs an ``StaticDataProvider`` and retirns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XFixedDecimal + + + A decimal number. See `the Rust docs `__ for more information. + + .. js:staticfunction:: create(v) + + Construct an :js:class:`ICU4XFixedDecimal` from an integer. See `the Rust docs `__ for more information. + + .. js:staticfunction:: create_fromstr(v) + + Construct an :js:class:`ICU4XFixedDecimal` from a string. See `the Rust docs `__ for more information. + + .. js:function:: multiply_pow10(power) + + Multiply the :js:class:`ICU4XFixedDecimal` by a given power of ten. See `the Rust docs `__ for more information. + + .. js:function:: negate() + + Invert the sign of the :js:class:`ICU4XFixedDecimal`. See `the Rust docs `__ for more information. + + .. js:function:: to_string() + + Format the :js:class:`ICU4XFixedDecimal` as a string. See `the Rust docs `__ for more information. + +.. js:class:: ICU4XFixedDecimalFormat + + + An ICU4X Fixed Decimal Format object, capable of formatting a :js:class:`ICU4XFixedDecimal` as a string. See `the Rust docs `__ for more information. + + .. js:staticfunction:: try_new(locale, provider, options) + + Creates a new :js:class:`ICU4XFixedDecimalFormat` from locale data. See `the Rust docs `__ for more information. + + .. js:staticfunction:: try_new_specific(locale, provider, options) + + Creates a new :js:class:`ICU4XFixedDecimalFormat` from a data provider specific to FixedDecimalFormat. See `the Rust docs `__ for more information. + + .. js:function:: format(value) + + Formats a :js:class:`ICU4XFixedDecimal` to a string. See `the Rust docs `__ for more information. + +.. js:class:: ICU4XFixedDecimalFormatDataProvider + + + A DataProvider specific to FixedDecimalFormat. + + .. js:staticfunction:: create_static() + + Create a DataProvider reading from static data specific to FixedDecimalFormat. + +.. js:class:: ICU4XFixedDecimalFormatOptions + + + + .. js:attribute:: grouping_strategy + + + + .. js:attribute:: sign_display + + + + .. js:staticfunction:: default() + + +.. js:class:: ICU4XFixedDecimalFormatResult + + + + .. js:attribute:: fdf + + + The :js:class:`ICU4XFixedDecimalFormat`, exists if creation was successful. + + .. js:attribute:: success + + + Whether creating the :js:class:`ICU4XFixedDecimalFormat` was successful. + +.. js:class:: ICU4XFixedDecimalGroupingStrategy + + + +.. js:class:: ICU4XFixedDecimalSignDisplay + + + +.. js:class:: ICU4XLocale + + + An ICU4X Locale, capable of representing strings like ``"en-US"``. See `the Rust docs `__ for more information. + + .. js:staticfunction:: create(name) + + Construct an :js:class:`ICU4XLocale` from an locale identifier. See `the Rust docs `__ for more information. + + .. js:staticfunction:: create_en() + + Construct an :js:class:`ICU4XLocale` for the English language. + + .. js:staticfunction:: create_bn() + + Construct an :js:class:`ICU4XLocale` for the Bangla language. + + .. js:function:: clone() + + Clones the :js:class:`ICU4XLocale`. See `the Rust docs `__ for more information. + + .. js:function:: basename() + + Write a string representation of the ``LanguageIdentifier`` part of :js:class:`ICU4XLocale` to ``write``. See `the Rust docs `__ for more information. + + .. js:function:: get_unicode_extension(bytes) + + Write a string representation of the unicode extension to ``write`` See `the Rust docs `__ for more information. + + .. js:function:: language() + + Write a string representation of :js:class:`ICU4XLocale` language to ``write`` See `the Rust docs `__ for more information. + + .. js:function:: region() + + Write a string representation of :js:class:`ICU4XLocale` region to ``write`` See `the Rust docs `__ for more information. + + .. js:function:: script() + + Write a string representation of :js:class:`ICU4XLocale` script to ``write`` See `the Rust docs `__ for more information. + + .. js:function:: tostring() + + Write a string representation of :js:class:`ICU4XLocale` to ``write`` See `the Rust docs `__ for more information. + +.. js:class:: ICU4XLocaleCanonicalizer + + + A locale canonicalizer. See `the Rust docs `__ for more details. + + .. js:staticfunction:: create(provider) + + Create a new :js:class:`ICU4XLocaleCanonicalizer`. See `the Rust docs `__ for more details. + + .. js:function:: canonicalize(locale) + + FFI version of ``LocaleCanonicalizer::canonicalize()``. See `the Rust docs `__ for more details. + + .. js:function:: maximize(locale) + + FFI version of ``LocaleCanonicalizer::maximize()``. See `the Rust docs `__ for more details. + + .. js:function:: minimize(locale) + + FFI version of ``LocaleCanonicalizer::minimize()``. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XLocaleError + + + +.. js:class:: ICU4XPluralCategories + + + FFI version of ``PluralRules::categories()`` data. + + .. js:attribute:: zero + + + + .. js:attribute:: one + + + + .. js:attribute:: two + + + + .. js:attribute:: few + + + + .. js:attribute:: many + + + + .. js:attribute:: other + + + +.. js:class:: ICU4XPluralCategory + + + FFI version of ``PluralCategory``. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XPluralOperands + + + FFI version of ``PluralOperands``. See `the Rust docs `__ for more details. + + .. js:attribute:: i + + + + .. js:attribute:: v + + + + .. js:attribute:: w + + + + .. js:attribute:: f + + + + .. js:attribute:: t + + + + .. js:attribute:: c + + + + .. js:staticfunction:: create(s) + + FFI version of ``PluralOperands::from_str()``. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XPluralRuleType + + + FFI version of ``PluralRuleType``. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XPluralRules + + + FFI version of ``PluralRules``. See `the Rust docs `__ for more details. + + .. js:staticfunction:: create(locale, provider, ty) + + FFI version of ``PluralRules::try_new()``. See `the Rust docs `__ for more details. + + .. js:function:: select(op) + + FFI version of ``PluralRules::select()``. See `the Rust docs `__ for more details. + + .. js:function:: categories() + + FFI version of ``PluralRules::categories()``. See `the Rust docs `__ for more details. diff --git a/ffi/wasm/lib/api.mjs b/ffi/wasm/lib/api.mjs index 921cf2bdbdd..2422b2367ab 100644 --- a/ffi/wasm/lib/api.mjs +++ b/ffi/wasm/lib/api.mjs @@ -35,6 +35,28 @@ export class ICU4XCreateDataProviderResult { } } +const ICU4XCreateFixedDecimalFormatDataProviderResult_box_destroy_registry = new FinalizationRegistry(underlying => { + wasm.ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(underlying); +}); + +export class ICU4XCreateFixedDecimalFormatDataProviderResult { + constructor(underlying) { + this.underlying = underlying; + } + + get provider() { + return (() => { + const out = new ICU4XFixedDecimalFormatDataProvider((new Uint32Array(wasm.memory.buffer, this.underlying + 0, 1))[0]); + out.owner = null; + return out; + })(); + } + + get success() { + return (new Uint8Array(wasm.memory.buffer, this.underlying + 4, 1))[0] == 1; + } +} + const ICU4XCreateFixedDecimalResult_box_destroy_registry = new FinalizationRegistry(underlying => { wasm.ICU4XCreateFixedDecimalResult_destroy(underlying); }); @@ -239,6 +261,25 @@ export class ICU4XFixedDecimalFormat { return diplomat_out; } + static try_new_specific(locale, provider, options) { + const diplomat_ICU4XFixedDecimalFormatOptions_extracted_grouping_strategy = options["grouping_strategy"]; + const diplomat_ICU4XFixedDecimalFormatOptions_extracted_sign_display = options["sign_display"]; + const diplomat_out = (() => { + const diplomat_receive_buffer = wasm.diplomat_alloc(5); + wasm.ICU4XFixedDecimalFormat_try_new_specific(diplomat_receive_buffer, locale.underlying, provider.underlying, ICU4XFixedDecimalGroupingStrategy_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_grouping_strategy], ICU4XFixedDecimalSignDisplay_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_sign_display]); + const out = new ICU4XFixedDecimalFormatResult(diplomat_receive_buffer); + const out_fdf_value = out.fdf; + ICU4XFixedDecimalFormat_box_destroy_registry.register(out_fdf_value, out_fdf_value.underlying); + Object.defineProperty(out, "fdf", { value: out_fdf_value }); + diplomat_alloc_destroy_registry.register(out, { + ptr: out.underlying, + size: 5 + }); + return out; + })(); + return diplomat_out; + } + format(value) { const diplomat_out = diplomatRuntime.withWriteable(wasm, (writeable) => { return (() => { @@ -252,6 +293,33 @@ export class ICU4XFixedDecimalFormat { } } +const ICU4XFixedDecimalFormatDataProvider_box_destroy_registry = new FinalizationRegistry(underlying => { + wasm.ICU4XFixedDecimalFormatDataProvider_destroy(underlying); +}); + +export class ICU4XFixedDecimalFormatDataProvider { + constructor(underlying) { + this.underlying = underlying; + } + + static create_static() { + const diplomat_out = (() => { + const diplomat_receive_buffer = wasm.diplomat_alloc(5); + wasm.ICU4XFixedDecimalFormatDataProvider_create_static(diplomat_receive_buffer); + const out = new ICU4XCreateFixedDecimalFormatDataProviderResult(diplomat_receive_buffer); + const out_provider_value = out.provider; + ICU4XFixedDecimalFormatDataProvider_box_destroy_registry.register(out_provider_value, out_provider_value.underlying); + Object.defineProperty(out, "provider", { value: out_provider_value }); + diplomat_alloc_destroy_registry.register(out, { + ptr: out.underlying, + size: 5 + }); + return out; + })(); + return diplomat_out; + } +} + const ICU4XFixedDecimalFormatOptions_box_destroy_registry = new FinalizationRegistry(underlying => { wasm.ICU4XFixedDecimalFormatOptions_destroy(underlying); }); @@ -361,6 +429,32 @@ export class ICU4XLocale { return diplomat_out; } + static create_en() { + const diplomat_out = (() => { + const out = (() => { + const out = new ICU4XLocale(wasm.ICU4XLocale_create_en()); + out.owner = null; + return out; + })(); + ICU4XLocale_box_destroy_registry.register(out, out.underlying) + return out; + })(); + return diplomat_out; + } + + static create_bn() { + const diplomat_out = (() => { + const out = (() => { + const out = new ICU4XLocale(wasm.ICU4XLocale_create_bn()); + out.owner = null; + return out; + })(); + ICU4XLocale_box_destroy_registry.register(out, out.underlying) + return out; + })(); + return diplomat_out; + } + clone() { const diplomat_out = (() => { const out = (() => { From 64616f2f3cc0b5cb25e9d1a59c9879b5bfbeac57 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 17 Aug 2021 19:34:44 -0500 Subject: [PATCH 02/17] Add generated Diplomat files --- ...eateFixedDecimalFormatDataProviderResult.h | 24 ++++++++++ .../ICU4XFixedDecimalFormatDataProvider.h | 22 +++++++++ ...eateFixedDecimalFormatDataProviderResult.h | 24 ++++++++++ ...teFixedDecimalFormatDataProviderResult.hpp | 30 ++++++++++++ .../ICU4XFixedDecimalFormatDataProvider.h | 22 +++++++++ .../ICU4XFixedDecimalFormatDataProvider.hpp | 46 +++++++++++++++++++ 6 files changed, 168 insertions(+) create mode 100644 ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h create mode 100644 ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h create mode 100644 ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h create mode 100644 ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp create mode 100644 ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.h create mode 100644 ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp diff --git a/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h b/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h new file mode 100644 index 00000000000..c6d3c8935e5 --- /dev/null +++ b/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h @@ -0,0 +1,24 @@ +#ifndef ICU4XCreateFixedDecimalFormatDataProviderResult_H +#define ICU4XCreateFixedDecimalFormatDataProviderResult_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; + +typedef struct ICU4XCreateFixedDecimalFormatDataProviderResult { + ICU4XFixedDecimalFormatDataProvider* provider; + bool success; +} ICU4XCreateFixedDecimalFormatDataProviderResult; + +void ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(ICU4XCreateFixedDecimalFormatDataProviderResult* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h b/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h new file mode 100644 index 00000000000..2c1c9cf5de8 --- /dev/null +++ b/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h @@ -0,0 +1,22 @@ +#ifndef ICU4XFixedDecimalFormatDataProvider_H +#define ICU4XFixedDecimalFormatDataProvider_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; +#include "ICU4XCreateFixedDecimalFormatDataProviderResult.h" + +ICU4XCreateFixedDecimalFormatDataProviderResult ICU4XFixedDecimalFormatDataProvider_create_static(); +void ICU4XFixedDecimalFormatDataProvider_destroy(ICU4XFixedDecimalFormatDataProvider* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h b/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h new file mode 100644 index 00000000000..c6d3c8935e5 --- /dev/null +++ b/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h @@ -0,0 +1,24 @@ +#ifndef ICU4XCreateFixedDecimalFormatDataProviderResult_H +#define ICU4XCreateFixedDecimalFormatDataProviderResult_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; + +typedef struct ICU4XCreateFixedDecimalFormatDataProviderResult { + ICU4XFixedDecimalFormatDataProvider* provider; + bool success; +} ICU4XCreateFixedDecimalFormatDataProviderResult; + +void ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(ICU4XCreateFixedDecimalFormatDataProviderResult* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp b/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp new file mode 100644 index 00000000000..4f558603571 --- /dev/null +++ b/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp @@ -0,0 +1,30 @@ +#ifndef ICU4XCreateFixedDecimalFormatDataProviderResult_HPP +#define ICU4XCreateFixedDecimalFormatDataProviderResult_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "ICU4XCreateFixedDecimalFormatDataProviderResult.h" +} + +class ICU4XFixedDecimalFormatDataProvider; + +struct ICU4XCreateFixedDecimalFormatDataProviderResultDeleter { + void operator()(capi::ICU4XCreateFixedDecimalFormatDataProviderResult* l) const noexcept { + capi::ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(l); + } +}; +struct ICU4XCreateFixedDecimalFormatDataProviderResult { + public: + std::optional provider; + bool success; +}; + + +#endif diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.h b/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.h new file mode 100644 index 00000000000..2c1c9cf5de8 --- /dev/null +++ b/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.h @@ -0,0 +1,22 @@ +#ifndef ICU4XFixedDecimalFormatDataProvider_H +#define ICU4XFixedDecimalFormatDataProvider_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; +#include "ICU4XCreateFixedDecimalFormatDataProviderResult.h" + +ICU4XCreateFixedDecimalFormatDataProviderResult ICU4XFixedDecimalFormatDataProvider_create_static(); +void ICU4XFixedDecimalFormatDataProvider_destroy(ICU4XFixedDecimalFormatDataProvider* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp b/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp new file mode 100644 index 00000000000..f3cc06e8587 --- /dev/null +++ b/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp @@ -0,0 +1,46 @@ +#ifndef ICU4XFixedDecimalFormatDataProvider_HPP +#define ICU4XFixedDecimalFormatDataProvider_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "ICU4XFixedDecimalFormatDataProvider.h" +} + +struct ICU4XCreateFixedDecimalFormatDataProviderResult; + +struct ICU4XFixedDecimalFormatDataProviderDeleter { + void operator()(capi::ICU4XFixedDecimalFormatDataProvider* l) const noexcept { + capi::ICU4XFixedDecimalFormatDataProvider_destroy(l); + } +}; +class ICU4XFixedDecimalFormatDataProvider { + public: + static ICU4XCreateFixedDecimalFormatDataProviderResult create_static(); + inline const capi::ICU4XFixedDecimalFormatDataProvider* AsFFI() const { return this->inner.get(); } + inline capi::ICU4XFixedDecimalFormatDataProvider* AsFFIMut() { return this->inner.get(); } + inline ICU4XFixedDecimalFormatDataProvider(capi::ICU4XFixedDecimalFormatDataProvider* i) : inner(i) {} + private: + std::unique_ptr inner; +}; + +#include "ICU4XCreateFixedDecimalFormatDataProviderResult.hpp" + +inline ICU4XCreateFixedDecimalFormatDataProviderResult ICU4XFixedDecimalFormatDataProvider::create_static() { + capi::ICU4XCreateFixedDecimalFormatDataProviderResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormatDataProvider_create_static(); + auto diplomat_optional_raw_out_value_provider = diplomat_raw_struct_out_value.provider; + std::optional diplomat_optional_out_value_provider; + if (diplomat_optional_raw_out_value_provider != nullptr) { + diplomat_optional_out_value_provider = ICU4XFixedDecimalFormatDataProvider(diplomat_optional_raw_out_value_provider); + } else { + diplomat_optional_out_value_provider = std::nullopt; + } + return ICU4XCreateFixedDecimalFormatDataProviderResult{ .provider = std::move(diplomat_optional_out_value_provider), .success = std::move(diplomat_raw_struct_out_value.success) }; +} +#endif From e6a1e30d8d6fc0b974c52901c2c1893bafcc04aa Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:11:22 -0500 Subject: [PATCH 03/17] Add initial ICU4XStaticDataProvider --- Cargo.lock | 1 + ffi/capi/Cargo.toml | 1 + ffi/capi/src/decimal.rs | 43 +++++----------------------------------- ffi/capi/src/provider.rs | 43 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64039561bb8..0f384f12d8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -985,6 +985,7 @@ dependencies = [ "icu_locid_macros", "icu_plurals", "icu_provider", + "icu_provider_blob", "icu_provider_fs", "icu_testdata", "log", diff --git a/ffi/capi/Cargo.toml b/ffi/capi/Cargo.toml index b747fb071dc..e1df53bbb79 100644 --- a/ffi/capi/Cargo.toml +++ b/ffi/capi/Cargo.toml @@ -64,6 +64,7 @@ icu_locid = { path = "../../components/locid" } icu_locid_macros = { path = "../../components/locid/macros" } icu_plurals = { path = "../../components/plurals/" } icu_provider = { path = "../../provider/core", features = ["provider_serde"] } +icu_provider_blob = { path = "../../provider/blob" } tinystr = { version = "0.4.10", features = ["alloc"], default-features = false } writeable = { path = "../../utils/writeable/" } diff --git a/ffi/capi/src/decimal.rs b/ffi/capi/src/decimal.rs index 29c403e83e1..5bd2af4fe55 100644 --- a/ffi/capi/src/decimal.rs +++ b/ffi/capi/src/decimal.rs @@ -17,6 +17,7 @@ pub mod ffi { use crate::{ fixed_decimal::ffi::ICU4XFixedDecimal, locale::ffi::ICU4XLocale, provider::ffi::ICU4XDataProvider, + provider::ffi::ICU4XStaticDataProvider, }; #[diplomat::opaque] @@ -60,41 +61,6 @@ pub mod ffi { } } - #[diplomat::opaque] - /// A DataProvider specific to FixedDecimalFormat. - pub struct ICU4XFixedDecimalFormatDataProvider( - pub Box>, - ); - - /// A result type for `ICU4XDataProvider::create`. - pub struct ICU4XCreateFixedDecimalFormatDataProviderResult { - /// Will be `None` if `success` is `false`, do not use in that case. - pub provider: Option>, - // May potentially add a better error type in the future - pub success: bool, - } - - impl ICU4XFixedDecimalFormatDataProvider { - /// Create a DataProvider reading from static data specific to FixedDecimalFormat. - fn create_static() -> ICU4XCreateFixedDecimalFormatDataProviderResult { - #[cfg(not(feature = "provider_static"))] - unimplemented!(); - - #[cfg(feature = "provider_static")] - { - #[cfg(feature = "smaller_static")] - let provider = icu_testdata::get_smaller_static_provider(); - #[cfg(not(feature = "smaller_static"))] - let provider = icu_testdata::get_static_provider(); - let fdf_provider = Box::new(provider); - ICU4XCreateFixedDecimalFormatDataProviderResult { - provider: Some(Box::new(ICU4XFixedDecimalFormatDataProvider(fdf_provider))), - success: true, - } - } - } - } - impl ICU4XFixedDecimalFormat { /// Creates a new [`ICU4XFixedDecimalFormat`] from locale data. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. pub fn try_new( @@ -136,10 +102,11 @@ pub mod ffi { } } - /// Creates a new [`ICU4XFixedDecimalFormat`] from a data provider specific to FixedDecimalFormat. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. - fn try_new_specific( + /// Creates a new [`ICU4XFixedDecimalFormat`] from a [`ICU4XStaticDataProvider`]. + /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. + fn try_new_from_static( locale: &ICU4XLocale, - provider: &ICU4XFixedDecimalFormatDataProvider, + provider: &ICU4XStaticDataProvider, options: ICU4XFixedDecimalFormatOptions, ) -> ICU4XFixedDecimalFormatResult { let langid = locale.0.as_ref().clone(); diff --git a/ffi/capi/src/provider.rs b/ffi/capi/src/provider.rs index 0d8685aa226..1762bef59d4 100644 --- a/ffi/capi/src/provider.rs +++ b/ffi/capi/src/provider.rs @@ -17,6 +17,7 @@ pub mod ffi { not(any(target_arch = "wasm32", target_os = "none")) ))] use icu_provider_fs::FsDataProvider; + use icu_provider_blob::StaticDataProvider; #[diplomat::opaque] /// An ICU4X data provider, capable of loading ICU4X data keys from some source. @@ -32,7 +33,7 @@ pub mod ffi { } impl ICU4XDataProvider { - /// Constructs an `FsDataProvider` and retirns it as an [`ICU4XDataProvider`]. + /// Constructs an `FsDataProvider` and returns it as an [`ICU4XDataProvider`]. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu_provider_fs/struct.FsDataProvider.html) for more details. #[allow(unused_variables)] pub fn create_fs(path: &str) -> ICU4XCreateDataProviderResult { @@ -61,7 +62,7 @@ pub mod ffi { unimplemented!(); } - /// Constructs an `StaticDataProvider` and retirns it as an [`ICU4XDataProvider`]. + /// Constructs an `StaticDataProvider` and returns it as an [`ICU4XDataProvider`]. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu_provider_blob/struct.StaticDataProvider.html) for more details. pub fn create_static() -> ICU4XCreateDataProviderResult { #[cfg(not(feature = "provider_static"))] @@ -81,4 +82,42 @@ pub mod ffi { } } } + + #[diplomat::opaque] + /// An ICU4X data provider backed by static data. This is a specialization of + /// [`ICU4XDataProvider`] intended to reduce code size. + /// + /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu_provider_blob/struct.StaticDataProvider.html) for more information. + pub struct ICU4XStaticDataProvider(pub Box); + + /// A result type for `ICU4XStaticDataProvider::create`. + pub struct ICU4XCreateStaticDataProviderResult { + /// Will be `None` if `success` is `false`, do not use in that case. + pub provider: Option>, + // May potentially add a better error type in the future + pub success: bool, + } + + impl ICU4XStaticDataProvider { + /// Constructs an `StaticDataProvider` and returns it as an [`ICU4XStaticDataProvider`]. + /// + /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu_provider_blob/struct.StaticDataProvider.html) for more details. + fn create() -> ICU4XCreateStaticDataProviderResult { + #[cfg(not(feature = "provider_static"))] + unimplemented!(); + + #[cfg(feature = "provider_static")] + { + #[cfg(feature = "smaller_static")] + let provider = icu_testdata::get_smaller_static_provider(); + #[cfg(not(feature = "smaller_static"))] + let provider = icu_testdata::get_static_provider(); + let erased = Box::new(provider); + ICU4XCreateStaticDataProviderResult { + provider: Some(Box::new(ICU4XStaticDataProvider(erased))), + success: true, + } + } + } + } } From 09cf5c5b24ff44b472f084ae33bc0f9307ccc5c4 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:25:22 -0500 Subject: [PATCH 04/17] Update Diplomat bindings --- ...eateFixedDecimalFormatDataProviderResult.h | 24 ----- .../ICU4XCreateStaticDataProviderResult.h | 24 +++++ ffi/capi/include/ICU4XFixedDecimalFormat.h | 4 +- .../ICU4XFixedDecimalFormatDataProvider.h | 22 ---- ffi/capi/include/ICU4XStaticDataProvider.h | 22 ++++ ffi/capi/src/decimal.rs | 2 +- ffi/capi/src/locale.rs | 4 +- ffi/capi/src/provider.rs | 2 +- ffi/cpp/docs/source/decimal_ffi.rst | 4 + ffi/cpp/docs/source/locale_ffi.rst | 8 ++ ffi/cpp/docs/source/provider_ffi.rst | 24 ++++- ...teFixedDecimalFormatDataProviderResult.hpp | 30 ------ .../ICU4XCreateStaticDataProviderResult.h | 24 +++++ .../ICU4XCreateStaticDataProviderResult.hpp | 30 ++++++ ffi/cpp/include/ICU4XFixedDecimalFormat.h | 4 +- ffi/cpp/include/ICU4XFixedDecimalFormat.hpp | 10 +- .../ICU4XFixedDecimalFormatDataProvider.hpp | 46 -------- ffi/cpp/include/ICU4XStaticDataProvider.h | 22 ++++ ffi/cpp/include/ICU4XStaticDataProvider.hpp | 46 ++++++++ ffi/wasm/docs/decimal_ffi.rst | 4 + ffi/wasm/docs/locale_ffi.rst | 8 ++ ffi/wasm/docs/provider_ffi.rst | 24 ++++- ffi/wasm/lib/api.mjs | 102 +++++++++--------- 23 files changed, 300 insertions(+), 190 deletions(-) delete mode 100644 ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h create mode 100644 ffi/capi/include/ICU4XCreateStaticDataProviderResult.h delete mode 100644 ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h create mode 100644 ffi/capi/include/ICU4XStaticDataProvider.h delete mode 100644 ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp create mode 100644 ffi/cpp/include/ICU4XCreateStaticDataProviderResult.h create mode 100644 ffi/cpp/include/ICU4XCreateStaticDataProviderResult.hpp delete mode 100644 ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp create mode 100644 ffi/cpp/include/ICU4XStaticDataProvider.h create mode 100644 ffi/cpp/include/ICU4XStaticDataProvider.hpp diff --git a/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h b/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h deleted file mode 100644 index c6d3c8935e5..00000000000 --- a/ffi/capi/include/ICU4XCreateFixedDecimalFormatDataProviderResult.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ICU4XCreateFixedDecimalFormatDataProviderResult_H -#define ICU4XCreateFixedDecimalFormatDataProviderResult_H -#include -#include -#include -#include -#include "diplomat_runtime.h" - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; - -typedef struct ICU4XCreateFixedDecimalFormatDataProviderResult { - ICU4XFixedDecimalFormatDataProvider* provider; - bool success; -} ICU4XCreateFixedDecimalFormatDataProviderResult; - -void ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(ICU4XCreateFixedDecimalFormatDataProviderResult* self); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ffi/capi/include/ICU4XCreateStaticDataProviderResult.h b/ffi/capi/include/ICU4XCreateStaticDataProviderResult.h new file mode 100644 index 00000000000..9bc03f9040d --- /dev/null +++ b/ffi/capi/include/ICU4XCreateStaticDataProviderResult.h @@ -0,0 +1,24 @@ +#ifndef ICU4XCreateStaticDataProviderResult_H +#define ICU4XCreateStaticDataProviderResult_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct ICU4XStaticDataProvider ICU4XStaticDataProvider; + +typedef struct ICU4XCreateStaticDataProviderResult { + ICU4XStaticDataProvider* provider; + bool success; +} ICU4XCreateStaticDataProviderResult; + +void ICU4XCreateStaticDataProviderResult_destroy(ICU4XCreateStaticDataProviderResult* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/capi/include/ICU4XFixedDecimalFormat.h b/ffi/capi/include/ICU4XFixedDecimalFormat.h index 9c4a9f89e28..08172977365 100644 --- a/ffi/capi/include/ICU4XFixedDecimalFormat.h +++ b/ffi/capi/include/ICU4XFixedDecimalFormat.h @@ -15,13 +15,13 @@ typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat; #include "ICU4XDataProvider.h" #include "ICU4XFixedDecimalFormatOptions.h" #include "ICU4XFixedDecimalFormatResult.h" -#include "ICU4XFixedDecimalFormatDataProvider.h" +#include "ICU4XStaticDataProvider.h" #include "ICU4XFixedDecimal.h" #include "result_void_void.h" ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new(const ICU4XLocale* locale, const ICU4XDataProvider* provider, ICU4XFixedDecimalFormatOptions options); -ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_specific(const ICU4XLocale* locale, const ICU4XFixedDecimalFormatDataProvider* provider, ICU4XFixedDecimalFormatOptions options); +ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_from_static(const ICU4XLocale* locale, const ICU4XStaticDataProvider* provider, ICU4XFixedDecimalFormatOptions options); decimal_ffi_result_void_void ICU4XFixedDecimalFormat_format(const ICU4XFixedDecimalFormat* self, const ICU4XFixedDecimal* value, DiplomatWriteable* write); void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self); diff --git a/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h b/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h deleted file mode 100644 index 2c1c9cf5de8..00000000000 --- a/ffi/capi/include/ICU4XFixedDecimalFormatDataProvider.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ICU4XFixedDecimalFormatDataProvider_H -#define ICU4XFixedDecimalFormatDataProvider_H -#include -#include -#include -#include -#include "diplomat_runtime.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ICU4XFixedDecimalFormatDataProvider ICU4XFixedDecimalFormatDataProvider; -#include "ICU4XCreateFixedDecimalFormatDataProviderResult.h" - -ICU4XCreateFixedDecimalFormatDataProviderResult ICU4XFixedDecimalFormatDataProvider_create_static(); -void ICU4XFixedDecimalFormatDataProvider_destroy(ICU4XFixedDecimalFormatDataProvider* self); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/ffi/capi/include/ICU4XStaticDataProvider.h b/ffi/capi/include/ICU4XStaticDataProvider.h new file mode 100644 index 00000000000..c47876813a0 --- /dev/null +++ b/ffi/capi/include/ICU4XStaticDataProvider.h @@ -0,0 +1,22 @@ +#ifndef ICU4XStaticDataProvider_H +#define ICU4XStaticDataProvider_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ICU4XStaticDataProvider ICU4XStaticDataProvider; +#include "ICU4XCreateStaticDataProviderResult.h" + +ICU4XCreateStaticDataProviderResult ICU4XStaticDataProvider_create(); +void ICU4XStaticDataProvider_destroy(ICU4XStaticDataProvider* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/capi/src/decimal.rs b/ffi/capi/src/decimal.rs index 5bd2af4fe55..1aa8d0748e5 100644 --- a/ffi/capi/src/decimal.rs +++ b/ffi/capi/src/decimal.rs @@ -104,7 +104,7 @@ pub mod ffi { /// Creates a new [`ICU4XFixedDecimalFormat`] from a [`ICU4XStaticDataProvider`]. /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. - fn try_new_from_static( + pub fn try_new_from_static( locale: &ICU4XLocale, provider: &ICU4XStaticDataProvider, options: ICU4XFixedDecimalFormatOptions, diff --git a/ffi/capi/src/locale.rs b/ffi/capi/src/locale.rs index d343704c645..412461b66c1 100644 --- a/ffi/capi/src/locale.rs +++ b/ffi/capi/src/locale.rs @@ -32,12 +32,12 @@ pub mod ffi { } /// Construct an [`ICU4XLocale`] for the English language. - fn create_en() -> Box { + pub fn create_en() -> Box { Box::new(ICU4XLocale(icu_locid_macros::langid!("en").into())) } /// Construct an [`ICU4XLocale`] for the Bangla language. - fn create_bn() -> Box { + pub fn create_bn() -> Box { Box::new(ICU4XLocale(icu_locid_macros::langid!("bn").into())) } diff --git a/ffi/capi/src/provider.rs b/ffi/capi/src/provider.rs index 1762bef59d4..d7853d03084 100644 --- a/ffi/capi/src/provider.rs +++ b/ffi/capi/src/provider.rs @@ -102,7 +102,7 @@ pub mod ffi { /// Constructs an `StaticDataProvider` and returns it as an [`ICU4XStaticDataProvider`]. /// /// See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu_provider_blob/struct.StaticDataProvider.html) for more details. - fn create() -> ICU4XCreateStaticDataProviderResult { + pub fn create() -> ICU4XCreateStaticDataProviderResult { #[cfg(not(feature = "provider_static"))] unimplemented!(); diff --git a/ffi/cpp/docs/source/decimal_ffi.rst b/ffi/cpp/docs/source/decimal_ffi.rst index bf80e764c5b..1bdd2db31ff 100644 --- a/ffi/cpp/docs/source/decimal_ffi.rst +++ b/ffi/cpp/docs/source/decimal_ffi.rst @@ -9,6 +9,10 @@ Creates a new :cpp:class:`ICU4XFixedDecimalFormat` from locale data. See `the Rust docs `__ for more information. + .. cpp:function:: static ICU4XFixedDecimalFormatResult try_new_from_static(const ICU4XLocale& locale, const ICU4XStaticDataProvider& provider, ICU4XFixedDecimalFormatOptions options) + + Creates a new :cpp:class:`ICU4XFixedDecimalFormat` from a :cpp:class:`ICU4XStaticDataProvider`. See `the Rust docs `__ for more information. + .. cpp:function:: template diplomat::result format_to_writeable(const ICU4XFixedDecimal& value, W& write) Formats a :cpp:class:`ICU4XFixedDecimal` to a string. See `the Rust docs `__ for more information. diff --git a/ffi/cpp/docs/source/locale_ffi.rst b/ffi/cpp/docs/source/locale_ffi.rst index 3c7edaafa5a..e8ba809ca75 100644 --- a/ffi/cpp/docs/source/locale_ffi.rst +++ b/ffi/cpp/docs/source/locale_ffi.rst @@ -9,6 +9,14 @@ Construct an :cpp:class:`ICU4XLocale` from an locale identifier. See `the Rust docs `__ for more information. + .. cpp:function:: static ICU4XLocale create_en() + + Construct an :cpp:class:`ICU4XLocale` for the English language. + + .. cpp:function:: static ICU4XLocale create_bn() + + Construct an :cpp:class:`ICU4XLocale` for the Bangla language. + .. cpp:function:: ICU4XLocale clone() Clones the :cpp:class:`ICU4XLocale`. See `the Rust docs `__ for more information. diff --git a/ffi/cpp/docs/source/provider_ffi.rst b/ffi/cpp/docs/source/provider_ffi.rst index fa2a741d83e..c1013a55070 100644 --- a/ffi/cpp/docs/source/provider_ffi.rst +++ b/ffi/cpp/docs/source/provider_ffi.rst @@ -11,14 +11,34 @@ .. cpp:member:: bool success +.. cpp:struct:: ICU4XCreateStaticDataProviderResult + + A result type for ``ICU4XStaticDataProvider::create``. + + .. cpp:member:: std::optional provider + + Will be ``None`` if ``success`` is ``false``, do not use in that case. + + .. cpp:member:: bool success + .. cpp:class:: ICU4XDataProvider An ICU4X data provider, capable of loading ICU4X data keys from some source. See `the Rust docs `__ for more information. .. cpp:function:: static ICU4XCreateDataProviderResult create_fs(const std::string_view path) - Constructs an ``FsDataProvider`` and retirns it as an :cpp:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + Constructs an ``FsDataProvider`` and returns it as an :cpp:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. .. cpp:function:: static ICU4XCreateDataProviderResult create_static() - Constructs an ``StaticDataProvider`` and retirns it as an :cpp:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + Constructs an ``StaticDataProvider`` and returns it as an :cpp:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + +.. cpp:class:: ICU4XStaticDataProvider + + An ICU4X data provider backed by static data. This is a specialization of :cpp:class:`ICU4XDataProvider` intended to reduce code size. + See `the Rust docs `__ for more information. + + .. cpp:function:: static ICU4XCreateStaticDataProviderResult create() + + Constructs an ``StaticDataProvider`` and returns it as an :cpp:class:`ICU4XStaticDataProvider`. + See `the Rust docs `__ for more details. diff --git a/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp b/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp deleted file mode 100644 index 4f558603571..00000000000 --- a/ffi/cpp/include/ICU4XCreateFixedDecimalFormatDataProviderResult.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ICU4XCreateFixedDecimalFormatDataProviderResult_HPP -#define ICU4XCreateFixedDecimalFormatDataProviderResult_HPP -#include -#include -#include -#include -#include -#include -#include -#include "diplomat_runtime.hpp" - -namespace capi { -#include "ICU4XCreateFixedDecimalFormatDataProviderResult.h" -} - -class ICU4XFixedDecimalFormatDataProvider; - -struct ICU4XCreateFixedDecimalFormatDataProviderResultDeleter { - void operator()(capi::ICU4XCreateFixedDecimalFormatDataProviderResult* l) const noexcept { - capi::ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(l); - } -}; -struct ICU4XCreateFixedDecimalFormatDataProviderResult { - public: - std::optional provider; - bool success; -}; - - -#endif diff --git a/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.h b/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.h new file mode 100644 index 00000000000..9bc03f9040d --- /dev/null +++ b/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.h @@ -0,0 +1,24 @@ +#ifndef ICU4XCreateStaticDataProviderResult_H +#define ICU4XCreateStaticDataProviderResult_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct ICU4XStaticDataProvider ICU4XStaticDataProvider; + +typedef struct ICU4XCreateStaticDataProviderResult { + ICU4XStaticDataProvider* provider; + bool success; +} ICU4XCreateStaticDataProviderResult; + +void ICU4XCreateStaticDataProviderResult_destroy(ICU4XCreateStaticDataProviderResult* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.hpp b/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.hpp new file mode 100644 index 00000000000..d06a4bcb765 --- /dev/null +++ b/ffi/cpp/include/ICU4XCreateStaticDataProviderResult.hpp @@ -0,0 +1,30 @@ +#ifndef ICU4XCreateStaticDataProviderResult_HPP +#define ICU4XCreateStaticDataProviderResult_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "ICU4XCreateStaticDataProviderResult.h" +} + +class ICU4XStaticDataProvider; + +struct ICU4XCreateStaticDataProviderResultDeleter { + void operator()(capi::ICU4XCreateStaticDataProviderResult* l) const noexcept { + capi::ICU4XCreateStaticDataProviderResult_destroy(l); + } +}; +struct ICU4XCreateStaticDataProviderResult { + public: + std::optional provider; + bool success; +}; + + +#endif diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormat.h b/ffi/cpp/include/ICU4XFixedDecimalFormat.h index 9c4a9f89e28..08172977365 100644 --- a/ffi/cpp/include/ICU4XFixedDecimalFormat.h +++ b/ffi/cpp/include/ICU4XFixedDecimalFormat.h @@ -15,13 +15,13 @@ typedef struct ICU4XFixedDecimalFormat ICU4XFixedDecimalFormat; #include "ICU4XDataProvider.h" #include "ICU4XFixedDecimalFormatOptions.h" #include "ICU4XFixedDecimalFormatResult.h" -#include "ICU4XFixedDecimalFormatDataProvider.h" +#include "ICU4XStaticDataProvider.h" #include "ICU4XFixedDecimal.h" #include "result_void_void.h" ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new(const ICU4XLocale* locale, const ICU4XDataProvider* provider, ICU4XFixedDecimalFormatOptions options); -ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_specific(const ICU4XLocale* locale, const ICU4XFixedDecimalFormatDataProvider* provider, ICU4XFixedDecimalFormatOptions options); +ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat_try_new_from_static(const ICU4XLocale* locale, const ICU4XStaticDataProvider* provider, ICU4XFixedDecimalFormatOptions options); decimal_ffi_result_void_void ICU4XFixedDecimalFormat_format(const ICU4XFixedDecimalFormat* self, const ICU4XFixedDecimal* value, DiplomatWriteable* write); void ICU4XFixedDecimalFormat_destroy(ICU4XFixedDecimalFormat* self); diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp b/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp index 034344c1fe0..f2fd5fcf278 100644 --- a/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp +++ b/ffi/cpp/include/ICU4XFixedDecimalFormat.hpp @@ -17,7 +17,7 @@ class ICU4XLocale; class ICU4XDataProvider; struct ICU4XFixedDecimalFormatOptions; struct ICU4XFixedDecimalFormatResult; -class ICU4XFixedDecimalFormatDataProvider; +class ICU4XStaticDataProvider; class ICU4XFixedDecimal; struct ICU4XFixedDecimalFormatDeleter { @@ -28,7 +28,7 @@ struct ICU4XFixedDecimalFormatDeleter { class ICU4XFixedDecimalFormat { public: static ICU4XFixedDecimalFormatResult try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options); - static ICU4XFixedDecimalFormatResult try_new_specific(const ICU4XLocale& locale, const ICU4XFixedDecimalFormatDataProvider& provider, ICU4XFixedDecimalFormatOptions options); + static ICU4XFixedDecimalFormatResult try_new_from_static(const ICU4XLocale& locale, const ICU4XStaticDataProvider& provider, ICU4XFixedDecimalFormatOptions options); template diplomat::result format_to_writeable(const ICU4XFixedDecimal& value, W& write); diplomat::result format(const ICU4XFixedDecimal& value); inline const capi::ICU4XFixedDecimalFormat* AsFFI() const { return this->inner.get(); } @@ -42,7 +42,7 @@ class ICU4XFixedDecimalFormat { #include "ICU4XDataProvider.hpp" #include "ICU4XFixedDecimalFormatOptions.hpp" #include "ICU4XFixedDecimalFormatResult.hpp" -#include "ICU4XFixedDecimalFormatDataProvider.hpp" +#include "ICU4XStaticDataProvider.hpp" #include "ICU4XFixedDecimal.hpp" inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options) { @@ -57,9 +57,9 @@ inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new(const ICU4 } return ICU4XFixedDecimalFormatResult{ .fdf = std::move(diplomat_optional_out_value_fdf), .success = std::move(diplomat_raw_struct_out_value.success) }; } -inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new_specific(const ICU4XLocale& locale, const ICU4XFixedDecimalFormatDataProvider& provider, ICU4XFixedDecimalFormatOptions options) { +inline ICU4XFixedDecimalFormatResult ICU4XFixedDecimalFormat::try_new_from_static(const ICU4XLocale& locale, const ICU4XStaticDataProvider& provider, ICU4XFixedDecimalFormatOptions options) { ICU4XFixedDecimalFormatOptions diplomat_wrapped_struct_options = options; - capi::ICU4XFixedDecimalFormatResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormat_try_new_specific(locale.AsFFI(), provider.AsFFI(), capi::ICU4XFixedDecimalFormatOptions{ .grouping_strategy = static_cast(diplomat_wrapped_struct_options.grouping_strategy), .sign_display = static_cast(diplomat_wrapped_struct_options.sign_display) }); + capi::ICU4XFixedDecimalFormatResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormat_try_new_from_static(locale.AsFFI(), provider.AsFFI(), capi::ICU4XFixedDecimalFormatOptions{ .grouping_strategy = static_cast(diplomat_wrapped_struct_options.grouping_strategy), .sign_display = static_cast(diplomat_wrapped_struct_options.sign_display) }); auto diplomat_optional_raw_out_value_fdf = diplomat_raw_struct_out_value.fdf; std::optional diplomat_optional_out_value_fdf; if (diplomat_optional_raw_out_value_fdf != nullptr) { diff --git a/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp b/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp deleted file mode 100644 index f3cc06e8587..00000000000 --- a/ffi/cpp/include/ICU4XFixedDecimalFormatDataProvider.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef ICU4XFixedDecimalFormatDataProvider_HPP -#define ICU4XFixedDecimalFormatDataProvider_HPP -#include -#include -#include -#include -#include -#include -#include -#include "diplomat_runtime.hpp" - -namespace capi { -#include "ICU4XFixedDecimalFormatDataProvider.h" -} - -struct ICU4XCreateFixedDecimalFormatDataProviderResult; - -struct ICU4XFixedDecimalFormatDataProviderDeleter { - void operator()(capi::ICU4XFixedDecimalFormatDataProvider* l) const noexcept { - capi::ICU4XFixedDecimalFormatDataProvider_destroy(l); - } -}; -class ICU4XFixedDecimalFormatDataProvider { - public: - static ICU4XCreateFixedDecimalFormatDataProviderResult create_static(); - inline const capi::ICU4XFixedDecimalFormatDataProvider* AsFFI() const { return this->inner.get(); } - inline capi::ICU4XFixedDecimalFormatDataProvider* AsFFIMut() { return this->inner.get(); } - inline ICU4XFixedDecimalFormatDataProvider(capi::ICU4XFixedDecimalFormatDataProvider* i) : inner(i) {} - private: - std::unique_ptr inner; -}; - -#include "ICU4XCreateFixedDecimalFormatDataProviderResult.hpp" - -inline ICU4XCreateFixedDecimalFormatDataProviderResult ICU4XFixedDecimalFormatDataProvider::create_static() { - capi::ICU4XCreateFixedDecimalFormatDataProviderResult diplomat_raw_struct_out_value = capi::ICU4XFixedDecimalFormatDataProvider_create_static(); - auto diplomat_optional_raw_out_value_provider = diplomat_raw_struct_out_value.provider; - std::optional diplomat_optional_out_value_provider; - if (diplomat_optional_raw_out_value_provider != nullptr) { - diplomat_optional_out_value_provider = ICU4XFixedDecimalFormatDataProvider(diplomat_optional_raw_out_value_provider); - } else { - diplomat_optional_out_value_provider = std::nullopt; - } - return ICU4XCreateFixedDecimalFormatDataProviderResult{ .provider = std::move(diplomat_optional_out_value_provider), .success = std::move(diplomat_raw_struct_out_value.success) }; -} -#endif diff --git a/ffi/cpp/include/ICU4XStaticDataProvider.h b/ffi/cpp/include/ICU4XStaticDataProvider.h new file mode 100644 index 00000000000..c47876813a0 --- /dev/null +++ b/ffi/cpp/include/ICU4XStaticDataProvider.h @@ -0,0 +1,22 @@ +#ifndef ICU4XStaticDataProvider_H +#define ICU4XStaticDataProvider_H +#include +#include +#include +#include +#include "diplomat_runtime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ICU4XStaticDataProvider ICU4XStaticDataProvider; +#include "ICU4XCreateStaticDataProviderResult.h" + +ICU4XCreateStaticDataProviderResult ICU4XStaticDataProvider_create(); +void ICU4XStaticDataProvider_destroy(ICU4XStaticDataProvider* self); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ffi/cpp/include/ICU4XStaticDataProvider.hpp b/ffi/cpp/include/ICU4XStaticDataProvider.hpp new file mode 100644 index 00000000000..ed038ecc12f --- /dev/null +++ b/ffi/cpp/include/ICU4XStaticDataProvider.hpp @@ -0,0 +1,46 @@ +#ifndef ICU4XStaticDataProvider_HPP +#define ICU4XStaticDataProvider_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "ICU4XStaticDataProvider.h" +} + +struct ICU4XCreateStaticDataProviderResult; + +struct ICU4XStaticDataProviderDeleter { + void operator()(capi::ICU4XStaticDataProvider* l) const noexcept { + capi::ICU4XStaticDataProvider_destroy(l); + } +}; +class ICU4XStaticDataProvider { + public: + static ICU4XCreateStaticDataProviderResult create(); + inline const capi::ICU4XStaticDataProvider* AsFFI() const { return this->inner.get(); } + inline capi::ICU4XStaticDataProvider* AsFFIMut() { return this->inner.get(); } + inline ICU4XStaticDataProvider(capi::ICU4XStaticDataProvider* i) : inner(i) {} + private: + std::unique_ptr inner; +}; + +#include "ICU4XCreateStaticDataProviderResult.hpp" + +inline ICU4XCreateStaticDataProviderResult ICU4XStaticDataProvider::create() { + capi::ICU4XCreateStaticDataProviderResult diplomat_raw_struct_out_value = capi::ICU4XStaticDataProvider_create(); + auto diplomat_optional_raw_out_value_provider = diplomat_raw_struct_out_value.provider; + std::optional diplomat_optional_out_value_provider; + if (diplomat_optional_raw_out_value_provider != nullptr) { + diplomat_optional_out_value_provider = ICU4XStaticDataProvider(diplomat_optional_raw_out_value_provider); + } else { + diplomat_optional_out_value_provider = std::nullopt; + } + return ICU4XCreateStaticDataProviderResult{ .provider = std::move(diplomat_optional_out_value_provider), .success = std::move(diplomat_raw_struct_out_value.success) }; +} +#endif diff --git a/ffi/wasm/docs/decimal_ffi.rst b/ffi/wasm/docs/decimal_ffi.rst index 43d53dc1aa8..6e0ec4081a8 100644 --- a/ffi/wasm/docs/decimal_ffi.rst +++ b/ffi/wasm/docs/decimal_ffi.rst @@ -9,6 +9,10 @@ Creates a new :js:class:`ICU4XFixedDecimalFormat` from locale data. See `the Rust docs `__ for more information. + .. js:staticfunction:: try_new_from_static(locale, provider, options) + + Creates a new :js:class:`ICU4XFixedDecimalFormat` from a :js:class:`ICU4XStaticDataProvider`. See `the Rust docs `__ for more information. + .. js:function:: format(value) Formats a :js:class:`ICU4XFixedDecimal` to a string. See `the Rust docs `__ for more information. diff --git a/ffi/wasm/docs/locale_ffi.rst b/ffi/wasm/docs/locale_ffi.rst index 32fe17be420..97813434977 100644 --- a/ffi/wasm/docs/locale_ffi.rst +++ b/ffi/wasm/docs/locale_ffi.rst @@ -9,6 +9,14 @@ Construct an :js:class:`ICU4XLocale` from an locale identifier. See `the Rust docs `__ for more information. + .. js:staticfunction:: create_en() + + Construct an :js:class:`ICU4XLocale` for the English language. + + .. js:staticfunction:: create_bn() + + Construct an :js:class:`ICU4XLocale` for the Bangla language. + .. js:function:: clone() Clones the :js:class:`ICU4XLocale`. See `the Rust docs `__ for more information. diff --git a/ffi/wasm/docs/provider_ffi.rst b/ffi/wasm/docs/provider_ffi.rst index 401513bbdac..3fe9657f856 100644 --- a/ffi/wasm/docs/provider_ffi.rst +++ b/ffi/wasm/docs/provider_ffi.rst @@ -11,14 +11,34 @@ .. js:attribute:: success +.. js:class:: ICU4XCreateStaticDataProviderResult + + A result type for ``ICU4XStaticDataProvider::create``. + + .. js:attribute:: provider + + Will be ``None`` if ``success`` is ``false``, do not use in that case. + + .. js:attribute:: success + .. js:class:: ICU4XDataProvider An ICU4X data provider, capable of loading ICU4X data keys from some source. See `the Rust docs `__ for more information. .. js:staticfunction:: create_fs(path) - Constructs an ``FsDataProvider`` and retirns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + Constructs an ``FsDataProvider`` and returns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. .. js:staticfunction:: create_static() - Constructs an ``StaticDataProvider`` and retirns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + Constructs an ``StaticDataProvider`` and returns it as an :js:class:`ICU4XDataProvider`. See `the Rust docs `__ for more details. + +.. js:class:: ICU4XStaticDataProvider + + An ICU4X data provider backed by static data. This is a specialization of :js:class:`ICU4XDataProvider` intended to reduce code size. + See `the Rust docs `__ for more information. + + .. js:staticfunction:: create() + + Constructs an ``StaticDataProvider`` and returns it as an :js:class:`ICU4XStaticDataProvider`. + See `the Rust docs `__ for more details. diff --git a/ffi/wasm/lib/api.mjs b/ffi/wasm/lib/api.mjs index 2422b2367ab..7ca2de3256c 100644 --- a/ffi/wasm/lib/api.mjs +++ b/ffi/wasm/lib/api.mjs @@ -35,28 +35,6 @@ export class ICU4XCreateDataProviderResult { } } -const ICU4XCreateFixedDecimalFormatDataProviderResult_box_destroy_registry = new FinalizationRegistry(underlying => { - wasm.ICU4XCreateFixedDecimalFormatDataProviderResult_destroy(underlying); -}); - -export class ICU4XCreateFixedDecimalFormatDataProviderResult { - constructor(underlying) { - this.underlying = underlying; - } - - get provider() { - return (() => { - const out = new ICU4XFixedDecimalFormatDataProvider((new Uint32Array(wasm.memory.buffer, this.underlying + 0, 1))[0]); - out.owner = null; - return out; - })(); - } - - get success() { - return (new Uint8Array(wasm.memory.buffer, this.underlying + 4, 1))[0] == 1; - } -} - const ICU4XCreateFixedDecimalResult_box_destroy_registry = new FinalizationRegistry(underlying => { wasm.ICU4XCreateFixedDecimalResult_destroy(underlying); }); @@ -123,6 +101,28 @@ export class ICU4XCreatePluralRulesResult { } } +const ICU4XCreateStaticDataProviderResult_box_destroy_registry = new FinalizationRegistry(underlying => { + wasm.ICU4XCreateStaticDataProviderResult_destroy(underlying); +}); + +export class ICU4XCreateStaticDataProviderResult { + constructor(underlying) { + this.underlying = underlying; + } + + get provider() { + return (() => { + const out = new ICU4XStaticDataProvider((new Uint32Array(wasm.memory.buffer, this.underlying + 0, 1))[0]); + out.owner = null; + return out; + })(); + } + + get success() { + return (new Uint8Array(wasm.memory.buffer, this.underlying + 4, 1))[0] == 1; + } +} + const ICU4XDataProvider_box_destroy_registry = new FinalizationRegistry(underlying => { wasm.ICU4XDataProvider_destroy(underlying); }); @@ -261,12 +261,12 @@ export class ICU4XFixedDecimalFormat { return diplomat_out; } - static try_new_specific(locale, provider, options) { + static try_new_from_static(locale, provider, options) { const diplomat_ICU4XFixedDecimalFormatOptions_extracted_grouping_strategy = options["grouping_strategy"]; const diplomat_ICU4XFixedDecimalFormatOptions_extracted_sign_display = options["sign_display"]; const diplomat_out = (() => { const diplomat_receive_buffer = wasm.diplomat_alloc(5); - wasm.ICU4XFixedDecimalFormat_try_new_specific(diplomat_receive_buffer, locale.underlying, provider.underlying, ICU4XFixedDecimalGroupingStrategy_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_grouping_strategy], ICU4XFixedDecimalSignDisplay_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_sign_display]); + wasm.ICU4XFixedDecimalFormat_try_new_from_static(diplomat_receive_buffer, locale.underlying, provider.underlying, ICU4XFixedDecimalGroupingStrategy_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_grouping_strategy], ICU4XFixedDecimalSignDisplay_js_to_rust[diplomat_ICU4XFixedDecimalFormatOptions_extracted_sign_display]); const out = new ICU4XFixedDecimalFormatResult(diplomat_receive_buffer); const out_fdf_value = out.fdf; ICU4XFixedDecimalFormat_box_destroy_registry.register(out_fdf_value, out_fdf_value.underlying); @@ -293,33 +293,6 @@ export class ICU4XFixedDecimalFormat { } } -const ICU4XFixedDecimalFormatDataProvider_box_destroy_registry = new FinalizationRegistry(underlying => { - wasm.ICU4XFixedDecimalFormatDataProvider_destroy(underlying); -}); - -export class ICU4XFixedDecimalFormatDataProvider { - constructor(underlying) { - this.underlying = underlying; - } - - static create_static() { - const diplomat_out = (() => { - const diplomat_receive_buffer = wasm.diplomat_alloc(5); - wasm.ICU4XFixedDecimalFormatDataProvider_create_static(diplomat_receive_buffer); - const out = new ICU4XCreateFixedDecimalFormatDataProviderResult(diplomat_receive_buffer); - const out_provider_value = out.provider; - ICU4XFixedDecimalFormatDataProvider_box_destroy_registry.register(out_provider_value, out_provider_value.underlying); - Object.defineProperty(out, "provider", { value: out_provider_value }); - diplomat_alloc_destroy_registry.register(out, { - ptr: out.underlying, - size: 5 - }); - return out; - })(); - return diplomat_out; - } -} - const ICU4XFixedDecimalFormatOptions_box_destroy_registry = new FinalizationRegistry(underlying => { wasm.ICU4XFixedDecimalFormatOptions_destroy(underlying); }); @@ -817,3 +790,30 @@ export class ICU4XPluralRules { return diplomat_out; } } + +const ICU4XStaticDataProvider_box_destroy_registry = new FinalizationRegistry(underlying => { + wasm.ICU4XStaticDataProvider_destroy(underlying); +}); + +export class ICU4XStaticDataProvider { + constructor(underlying) { + this.underlying = underlying; + } + + static create() { + const diplomat_out = (() => { + const diplomat_receive_buffer = wasm.diplomat_alloc(5); + wasm.ICU4XStaticDataProvider_create(diplomat_receive_buffer); + const out = new ICU4XCreateStaticDataProviderResult(diplomat_receive_buffer); + const out_provider_value = out.provider; + ICU4XStaticDataProvider_box_destroy_registry.register(out_provider_value, out_provider_value.underlying); + Object.defineProperty(out, "provider", { value: out_provider_value }); + diplomat_alloc_destroy_registry.register(out, { + ptr: out.underlying, + size: 5 + }); + return out; + })(); + return diplomat_out; + } +} From 319dc34bcfbefc897526648d77b127822ae9180c Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:29:30 -0500 Subject: [PATCH 05/17] cargo fmt --- ffi/capi/src/decimal.rs | 48 ++++++++++++---------------------------- ffi/capi/src/provider.rs | 2 +- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/ffi/capi/src/decimal.rs b/ffi/capi/src/decimal.rs index 1aa8d0748e5..a1a6de8a66f 100644 --- a/ffi/capi/src/decimal.rs +++ b/ffi/capi/src/decimal.rs @@ -16,8 +16,7 @@ pub mod ffi { use crate::{ fixed_decimal::ffi::ICU4XFixedDecimal, locale::ffi::ICU4XLocale, - provider::ffi::ICU4XDataProvider, - provider::ffi::ICU4XStaticDataProvider, + provider::ffi::ICU4XDataProvider, provider::ffi::ICU4XStaticDataProvider, }; #[diplomat::opaque] @@ -68,38 +67,8 @@ pub mod ffi { provider: &ICU4XDataProvider, options: ICU4XFixedDecimalFormatOptions, ) -> ICU4XFixedDecimalFormatResult { - let langid = locale.0.as_ref().clone(); let provider = provider.0.as_ref(); - - if let Result::Ok(fdf) = FixedDecimalFormat::try_new( - langid, - provider, - FixedDecimalFormatOptions { - grouping_strategy: match options.grouping_strategy { - ICU4XFixedDecimalGroupingStrategy::Auto => GroupingStrategy::Auto, - ICU4XFixedDecimalGroupingStrategy::Never => GroupingStrategy::Never, - ICU4XFixedDecimalGroupingStrategy::Always => GroupingStrategy::Always, - ICU4XFixedDecimalGroupingStrategy::Min2 => GroupingStrategy::Min2, - }, - sign_display: match options.sign_display { - ICU4XFixedDecimalSignDisplay::Auto => SignDisplay::Auto, - ICU4XFixedDecimalSignDisplay::Never => SignDisplay::Never, - ICU4XFixedDecimalSignDisplay::Always => SignDisplay::Always, - ICU4XFixedDecimalSignDisplay::ExceptZero => SignDisplay::ExceptZero, - ICU4XFixedDecimalSignDisplay::Negative => SignDisplay::Negative, - }, - }, - ) { - ICU4XFixedDecimalFormatResult { - fdf: Some(Box::new(ICU4XFixedDecimalFormat(fdf))), - success: true, - } - } else { - ICU4XFixedDecimalFormatResult { - fdf: None, - success: false, - } - } + Self::try_new_impl(locale, provider, options) } /// Creates a new [`ICU4XFixedDecimalFormat`] from a [`ICU4XStaticDataProvider`]. @@ -109,8 +78,19 @@ pub mod ffi { provider: &ICU4XStaticDataProvider, options: ICU4XFixedDecimalFormatOptions, ) -> ICU4XFixedDecimalFormatResult { - let langid = locale.0.as_ref().clone(); let provider = provider.0.as_ref(); + Self::try_new_impl(locale, provider, options) + } + + fn try_new_impl( + locale: &ICU4XLocale, + provider: &D, + options: ICU4XFixedDecimalFormatOptions, + ) -> ICU4XFixedDecimalFormatResult + where + D: DataProvider<'static, DecimalSymbolsV1Marker> + ?Sized, + { + let langid = locale.0.as_ref().clone(); if let Result::Ok(fdf) = FixedDecimalFormat::try_new( langid, diff --git a/ffi/capi/src/provider.rs b/ffi/capi/src/provider.rs index d7853d03084..9d930cca740 100644 --- a/ffi/capi/src/provider.rs +++ b/ffi/capi/src/provider.rs @@ -12,12 +12,12 @@ pub mod ffi { use alloc::string::ToString; use icu_provider::serde::SerdeDeDataProvider; + use icu_provider_blob::StaticDataProvider; #[cfg(all( feature = "provider_fs", not(any(target_arch = "wasm32", target_os = "none")) ))] use icu_provider_fs::FsDataProvider; - use icu_provider_blob::StaticDataProvider; #[diplomat::opaque] /// An ICU4X data provider, capable of loading ICU4X data keys from some source. From 6c5a1ed9223c27f19bbc8ccf40344852be6bdde0 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:31:45 -0500 Subject: [PATCH 06/17] Update test.c --- ffi/capi/examples/fixeddecimal/test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ffi/capi/examples/fixeddecimal/test.c b/ffi/capi/examples/fixeddecimal/test.c index f55eaaef20b..f1aed1974c7 100644 --- a/ffi/capi/examples/fixeddecimal/test.c +++ b/ffi/capi/examples/fixeddecimal/test.c @@ -8,17 +8,17 @@ int main() { ICU4XLocale* locale = ICU4XLocale_create_bn(); - ICU4XCreateFixedDecimalFormatDataProviderResult result = ICU4XFixedDecimalFormatDataProvider_create_static(); + ICU4XCreateStaticDataProviderResult result = ICU4XStaticDataProvider_create(); if (!result.success) { printf("Failed to create FsDataProvider\n"); return 1; } - ICU4XFixedDecimalFormatDataProvider* provider = result.provider; + ICU4XStaticDataProvider* provider = result.provider; ICU4XFixedDecimal* decimal = ICU4XFixedDecimal_create(1000007); ICU4XFixedDecimalFormatOptions opts = {ICU4XFixedDecimalGroupingStrategy_Auto, ICU4XFixedDecimalSignDisplay_Auto}; - ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new_specific(locale, provider, opts); + ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new_from_static(locale, provider, opts); if (!fdf_result.success) { printf("Failed to create FixedDecimalFormat\n"); return 1; @@ -91,7 +91,7 @@ int main() { ICU4XFixedDecimal_destroy(decimal); ICU4XFixedDecimalFormat_destroy(fdf); ICU4XLocale_destroy(locale); - ICU4XFixedDecimalFormatDataProvider_destroy(provider); + ICU4XStaticDataProvider_destroy(provider); return 0; } From 40a150ca973842e89e722b87f26f4ba07840c58d Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:41:53 -0500 Subject: [PATCH 07/17] Move size-optimized example to another directory --- ffi/capi/examples/fixeddecimal/.gitignore | 5 - ffi/capi/examples/fixeddecimal/Makefile | 44 --------- .../examples/fixeddecimal_tiny/.gitignore | 6 ++ ffi/capi/examples/fixeddecimal_tiny/Makefile | 65 +++++++++++++ ffi/capi/examples/fixeddecimal_tiny/test.c | 97 +++++++++++++++++++ 5 files changed, 168 insertions(+), 49 deletions(-) create mode 100644 ffi/capi/examples/fixeddecimal_tiny/.gitignore create mode 100644 ffi/capi/examples/fixeddecimal_tiny/Makefile create mode 100644 ffi/capi/examples/fixeddecimal_tiny/test.c diff --git a/ffi/capi/examples/fixeddecimal/.gitignore b/ffi/capi/examples/fixeddecimal/.gitignore index 3def44c6705..cba7efc8efd 100644 --- a/ffi/capi/examples/fixeddecimal/.gitignore +++ b/ffi/capi/examples/fixeddecimal/.gitignore @@ -1,6 +1 @@ a.out -optim* -*.i64 -*.dot -*.elf -*.o diff --git a/ffi/capi/examples/fixeddecimal/Makefile b/ffi/capi/examples/fixeddecimal/Makefile index d7a045d339d..528cd69245f 100644 --- a/ffi/capi/examples/fixeddecimal/Makefile +++ b/ffi/capi/examples/fixeddecimal/Makefile @@ -16,54 +16,10 @@ $(ALL_HEADERS): ../../../../target/debug/libicu_capi.a: $(ALL_RUST) cargo build -../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny - -../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release - -# Naive target: no optimizations, full std a.out: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c gcc test.c ../../../../target/debug/libicu_capi.a -ldl -lpthread -lm -g -# optim.elf: gcc with maximum link-time code stripping (gc-sections and strip-all) -optim.elf: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c - gcc -fdata-sections -ffunction-sections test.c ../../../../target/debug/libicu_capi.a -ldl -lpthread -lm -g -o optim.elf -Wl,--gc-sections -Wl,--strip-all - -# optim2.elf: clang single-step with gc-sections -optim2.elf: ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a $(ALL_HEADERS) test.c - clang -flto -fdata-sections -ffunction-sections test.c ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a -g -o optim2.elf -Wl,--gc-sections - -optim3.o: $(ALL_HEADERS) - clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -g -o optim3.o - -# optim3.elf: clang two-step with lld, debug mode -optim3.elf: optim3.o ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a - clang -flto=thin -fuse-ld=lld -L . -o optim3.elf optim3.o ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a -Wl,--gc-sections - -optim4.o: $(ALL_HEADERS) - clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -g -o optim4.o - -# optim4.elf: clang two-step with lld, release mode with debug symbols -optim4.elf: optim4.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a - clang -flto=thin -fuse-ld=lld -L . -o optim4.elf optim4.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a -Wl,--gc-sections - -optim5.o: $(ALL_HEADERS) - clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -o optim5.o - -# optim5.elf: clang two-step with lld, release mode stripped of debug symbols -optim5.elf: optim5.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a - clang -flto=thin -fuse-ld=lld -L . -o optim5.elf optim5.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a -Wl,--gc-sections -Wl,--strip-all - build: a.out test: build ./a.out - -build-optim: optim.elf optim2.elf optim3.elf optim4.elf optim5.elf - -# note: optim2.elf and optim3.elf crash when run with error "Illegal instruction" (investigate?) -test-optim: build-optim - ./optim.elf - ./optim4.elf - ./optim5.elf diff --git a/ffi/capi/examples/fixeddecimal_tiny/.gitignore b/ffi/capi/examples/fixeddecimal_tiny/.gitignore new file mode 100644 index 00000000000..3def44c6705 --- /dev/null +++ b/ffi/capi/examples/fixeddecimal_tiny/.gitignore @@ -0,0 +1,6 @@ +a.out +optim* +*.i64 +*.dot +*.elf +*.o diff --git a/ffi/capi/examples/fixeddecimal_tiny/Makefile b/ffi/capi/examples/fixeddecimal_tiny/Makefile new file mode 100644 index 00000000000..0d07fed03bb --- /dev/null +++ b/ffi/capi/examples/fixeddecimal_tiny/Makefile @@ -0,0 +1,65 @@ +# 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 ). + +.DEFAULT_GOAL := test +.PHONY: build test + +ALL_HEADERS := $(wildcard ../../include/*.h) +ALL_RUST := $(wildcard ../../src/*.rs) + +$(ALL_RUST): + +$(ALL_HEADERS): + + +../../../../target/debug/libicu_capi.a: $(ALL_RUST) + cargo build + +../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a: $(ALL_RUST) + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny + +../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a: $(ALL_RUST) + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release + +# Naive target: no optimizations, full std +optim0.elf: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c + gcc test.c ../../../../target/debug/libicu_capi.a -ldl -lpthread -lm -g -o optim0.elf + +# optim.elf: gcc with maximum link-time code stripping (gc-sections and strip-all) +optim1.elf: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c + gcc -fdata-sections -ffunction-sections test.c ../../../../target/debug/libicu_capi.a -ldl -lpthread -lm -g -o optim1.elf -Wl,--gc-sections -Wl,--strip-all + +# optim2.elf: clang single-step with gc-sections +optim2.elf: ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a $(ALL_HEADERS) test.c + clang -flto -fdata-sections -ffunction-sections test.c ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a -g -o optim2.elf -Wl,--gc-sections + +optim3.o: $(ALL_HEADERS) + clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -g -o optim3.o + +# optim3.elf: clang two-step with lld, debug mode +optim3.elf: optim3.o ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a + clang -flto=thin -fuse-ld=lld -L . -o optim3.elf optim3.o ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a -Wl,--gc-sections + +optim4.o: $(ALL_HEADERS) + clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -g -o optim4.o + +# optim4.elf: clang two-step with lld, release mode with debug symbols +optim4.elf: optim4.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a + clang -flto=thin -fuse-ld=lld -L . -o optim4.elf optim4.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a -Wl,--gc-sections + +optim5.o: $(ALL_HEADERS) + clang -c -flto=thin -fdata-sections -ffunction-sections --target=x86_64-unknown-linux-gnu test.c -o optim5.o + +# optim5.elf: clang two-step with lld, release mode stripped of debug symbols +optim5.elf: optim5.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a + clang -flto=thin -fuse-ld=lld -L . -o optim5.elf optim5.o ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a -Wl,--gc-sections -Wl,--strip-all + +build: optim0.elf optim1.elf optim2.elf optim3.elf optim4.elf optim5.elf + +# note: optim2.elf and optim3.elf crash when run with error "Illegal instruction" (investigate?) +test: build + ./optim0.elf + ./optim1.elf + ./optim4.elf + ./optim5.elf diff --git a/ffi/capi/examples/fixeddecimal_tiny/test.c b/ffi/capi/examples/fixeddecimal_tiny/test.c new file mode 100644 index 00000000000..f1aed1974c7 --- /dev/null +++ b/ffi/capi/examples/fixeddecimal_tiny/test.c @@ -0,0 +1,97 @@ +// 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 ). + +#include "../../include/ICU4XFixedDecimalFormat.h" +#include +#include + +int main() { + ICU4XLocale* locale = ICU4XLocale_create_bn(); + ICU4XCreateStaticDataProviderResult result = ICU4XStaticDataProvider_create(); + if (!result.success) { + printf("Failed to create FsDataProvider\n"); + return 1; + } + ICU4XStaticDataProvider* provider = result.provider; + ICU4XFixedDecimal* decimal = ICU4XFixedDecimal_create(1000007); + + ICU4XFixedDecimalFormatOptions opts = {ICU4XFixedDecimalGroupingStrategy_Auto, ICU4XFixedDecimalSignDisplay_Auto}; + + ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new_from_static(locale, provider, opts); + if (!fdf_result.success) { + printf("Failed to create FixedDecimalFormat\n"); + return 1; + } + ICU4XFixedDecimalFormat* fdf = fdf_result.fdf; + char output[40]; + + DiplomatWriteable write = diplomat_simple_writeable(output, 40); + + bool success = ICU4XFixedDecimalFormat_format(fdf, decimal, &write).is_ok; + if (!success) { + printf("Failed to write result of FixedDecimalFormat::format to string.\n"); + return 1; + } + printf("Output is %s\n", output); + + const char* expected = u8"১০,০০,০০৭"; + if (strcmp(output, expected) != 0) { + printf("Output does not match expected output!\n"); + return 1; + } + + ICU4XFixedDecimal_multiply_pow10(decimal, 2); + if (!success) { + printf("Failed to multiply FixedDecimal\n"); + return 1; + } + + ICU4XFixedDecimal_negate(decimal); + + write = diplomat_simple_writeable(output, 40); + + success = ICU4XFixedDecimalFormat_format(fdf, decimal, &write).is_ok; + if (!success) { + printf("Failed to write result of FixedDecimalFormat::format to string.\n"); + return 1; + } + printf("Output x100 and negated is %s\n", output); + + expected = u8"-১০,০০,০০,৭০০"; + if (strcmp(output, expected) != 0) { + printf("Output does not match expected output!\n"); + return 1; + } + + ICU4XFixedDecimal_destroy(decimal); + + ICU4XCreateFixedDecimalResult fd_result = ICU4XFixedDecimal_create_fromstr("1000007.070", 11); + if (!fd_result.success) { + printf("Failed to create FixedDecimal from string.\n"); + return 1; + } + decimal = fd_result.fd; + + write = diplomat_simple_writeable(output, 40); + + success = ICU4XFixedDecimalFormat_format(fdf, decimal, &write).is_ok; + if (!success) { + printf("Failed to write result of FixedDecimalFormat::format to string.\n"); + return 1; + } + printf("Output is %s\n", output); + + expected = u8"১০,০০,০০৭.০৭০"; + if (strcmp(output, expected) != 0) { + printf("Output does not match expected output!\n"); + return 1; + } + + ICU4XFixedDecimal_destroy(decimal); + ICU4XFixedDecimalFormat_destroy(fdf); + ICU4XLocale_destroy(locale); + ICU4XStaticDataProvider_destroy(provider); + + return 0; +} From 6dca1d1dbcb8e9503babdc185a30d37e5f24b325 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:42:48 -0500 Subject: [PATCH 08/17] Revert test.c to mainline --- ffi/capi/examples/fixeddecimal/test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ffi/capi/examples/fixeddecimal/test.c b/ffi/capi/examples/fixeddecimal/test.c index f1aed1974c7..53834fcf0f6 100644 --- a/ffi/capi/examples/fixeddecimal/test.c +++ b/ffi/capi/examples/fixeddecimal/test.c @@ -7,18 +7,18 @@ #include int main() { - ICU4XLocale* locale = ICU4XLocale_create_bn(); - ICU4XCreateStaticDataProviderResult result = ICU4XStaticDataProvider_create(); + ICU4XLocale* locale = ICU4XLocale_create("bn", 2); + ICU4XCreateDataProviderResult result = ICU4XDataProvider_create_static(); if (!result.success) { printf("Failed to create FsDataProvider\n"); return 1; } - ICU4XStaticDataProvider* provider = result.provider; + ICU4XDataProvider* provider = result.provider; ICU4XFixedDecimal* decimal = ICU4XFixedDecimal_create(1000007); ICU4XFixedDecimalFormatOptions opts = {ICU4XFixedDecimalGroupingStrategy_Auto, ICU4XFixedDecimalSignDisplay_Auto}; - ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new_from_static(locale, provider, opts); + ICU4XFixedDecimalFormatResult fdf_result = ICU4XFixedDecimalFormat_try_new(locale, provider, opts); if (!fdf_result.success) { printf("Failed to create FixedDecimalFormat\n"); return 1; @@ -91,7 +91,7 @@ int main() { ICU4XFixedDecimal_destroy(decimal); ICU4XFixedDecimalFormat_destroy(fdf); ICU4XLocale_destroy(locale); - ICU4XStaticDataProvider_destroy(provider); + ICU4XDataProvider_destroy(provider); return 0; } From 2bb5c466519d46e972d3ef937d8c95ba33ceff66 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:48:50 -0500 Subject: [PATCH 09/17] Remove additional coverage tests from fixeddecimal_tiny --- ffi/capi/examples/fixeddecimal_tiny/test.c | 47 ---------------------- 1 file changed, 47 deletions(-) diff --git a/ffi/capi/examples/fixeddecimal_tiny/test.c b/ffi/capi/examples/fixeddecimal_tiny/test.c index f1aed1974c7..5c5b58803f0 100644 --- a/ffi/capi/examples/fixeddecimal_tiny/test.c +++ b/ffi/capi/examples/fixeddecimal_tiny/test.c @@ -41,53 +41,6 @@ int main() { return 1; } - ICU4XFixedDecimal_multiply_pow10(decimal, 2); - if (!success) { - printf("Failed to multiply FixedDecimal\n"); - return 1; - } - - ICU4XFixedDecimal_negate(decimal); - - write = diplomat_simple_writeable(output, 40); - - success = ICU4XFixedDecimalFormat_format(fdf, decimal, &write).is_ok; - if (!success) { - printf("Failed to write result of FixedDecimalFormat::format to string.\n"); - return 1; - } - printf("Output x100 and negated is %s\n", output); - - expected = u8"-১০,০০,০০,৭০০"; - if (strcmp(output, expected) != 0) { - printf("Output does not match expected output!\n"); - return 1; - } - - ICU4XFixedDecimal_destroy(decimal); - - ICU4XCreateFixedDecimalResult fd_result = ICU4XFixedDecimal_create_fromstr("1000007.070", 11); - if (!fd_result.success) { - printf("Failed to create FixedDecimal from string.\n"); - return 1; - } - decimal = fd_result.fd; - - write = diplomat_simple_writeable(output, 40); - - success = ICU4XFixedDecimalFormat_format(fdf, decimal, &write).is_ok; - if (!success) { - printf("Failed to write result of FixedDecimalFormat::format to string.\n"); - return 1; - } - printf("Output is %s\n", output); - - expected = u8"১০,০০,০০৭.০৭০"; - if (strcmp(output, expected) != 0) { - printf("Output does not match expected output!\n"); - return 1; - } - ICU4XFixedDecimal_destroy(decimal); ICU4XFixedDecimalFormat_destroy(fdf); ICU4XLocale_destroy(locale); From f51d0d1b0e8b574ec75d1b8ee3e3f41bd2de0f6f Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:53:36 -0500 Subject: [PATCH 10/17] Add test-capi-tiny --- tools/scripts/ffi.toml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/scripts/ffi.toml b/tools/scripts/ffi.toml index 4fd759acf70..e2e6e722bd6 100644 --- a/tools/scripts/ffi.toml +++ b/tools/scripts/ffi.toml @@ -10,6 +10,7 @@ category = "ICU4X Development" dependencies = [ "verify-diplomat-gen", "test-capi", + "test-capi-tiny", "test-cpp", "build-wearos-ffi", "test-nostd", @@ -44,13 +45,25 @@ script_runner = "@duckscript" script = ''' exit_on_error true cd ffi/capi/examples/pluralrules -exec make +exec --fail-on-error make cd ../fixeddecimal exec --fail-on-error make cd ../locale exec --fail-on-error make ''' +[tasks.test-capi-tiny] +description = "Run C API tests for tiny targets" +category = "ICU4X Development" +dependencies = [ "diplomat-gen-c" ] +script_runner = "@duckscript" +script = ''' +exit_on_error true +cd ffi/capi/examples/fixeddecimal_tiny +exec --fail-on-error make +exec ls -l +''' + [tasks.test-cpp] description = "Run CPP tests" category = "ICU4X Development" From 703e3b1361e5c6e86959efcedd8e2c09054b331f Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 01:55:58 -0500 Subject: [PATCH 11/17] Add LLVM tooling to build-test.yml --- .github/workflows/build-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index b4bad6e49db..3d1ac7f732f 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -144,6 +144,8 @@ jobs: packages: | sphinx sphinx-rtd-theme + - name: Install LLVM tooling + run: sudo apt-get install clang lld - name: Install Diplomat uses: actions-rs/cargo@v1.0.1 From df8d13629b6cc1af18871e3d5fe777c07fbd427d Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 02:10:04 -0500 Subject: [PATCH 12/17] Set a stable nightly toolchain version for FFI tests --- .github/workflows/build-test.yml | 9 +++++---- ffi/capi/examples/fixeddecimal_tiny/Makefile | 4 ++-- tools/scripts/ffi.toml | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3d1ac7f732f..6ba39a5a594 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -112,10 +112,11 @@ jobs: run: rustup show - name: Load cortex target for no_std build. run: | - rustup install nightly - rustup component add --toolchain nightly rust-src - rustup target add thumbv7m-none-eabi --toolchain nightly - rustup target add thumbv8m.main-none-eabihf --toolchain nightly + rustup install nightly-2021-08-18 + rustup component add --toolchain nightly-2021-08-18 rust-src + rustup target add thumbv7m-none-eabi --toolchain nightly-2021-08-18 + rustup target add thumbv8m.main-none-eabihf --toolchain nightly-2021-08-18 + rustup target add x86_64-unknown-linux-gnu --toolchain nightly-2021-08-18 - name: Get cargo-make version id: cargo-make-version run: | diff --git a/ffi/capi/examples/fixeddecimal_tiny/Makefile b/ffi/capi/examples/fixeddecimal_tiny/Makefile index 0d07fed03bb..2a780c93545 100644 --- a/ffi/capi/examples/fixeddecimal_tiny/Makefile +++ b/ffi/capi/examples/fixeddecimal_tiny/Makefile @@ -17,10 +17,10 @@ $(ALL_HEADERS): cargo build ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-08-18 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-08-18 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release # Naive target: no optimizations, full std optim0.elf: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c diff --git a/tools/scripts/ffi.toml b/tools/scripts/ffi.toml index e2e6e722bd6..5037e34a786 100644 --- a/tools/scripts/ffi.toml +++ b/tools/scripts/ffi.toml @@ -125,7 +125,7 @@ exec --fail-on-error diplomat-tool cpp ../cpp/include --docs ../cpp/docs/source [tasks.build-wearos-ffi] description = "Build ICU4X CAPI for Cortex" category = "ICU4X FFI" -toolchain = "nightly" +toolchain = "nightly-2021-08-18" env = { "RUSTFLAGS" = "-Ctarget-cpu=cortex-m33" } command = "cargo" args = ["build", "--package", "icu_capi", @@ -137,6 +137,6 @@ args = ["build", "--package", "icu_capi", [tasks.test-nostd] description = "Ensure ICU4X core builds on no-std" category = "ICU4X FFI" -toolchain = "nightly" +toolchain = "nightly-2021-08-18" command = "cargo" args = ["build", "--package", "icu", "--target", "thumbv7m-none-eabi"] From 19b6309eb272b9a057ae3fc61622bca95295be15 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 02:26:15 -0500 Subject: [PATCH 13/17] Attempt to fix build issue by reverting to nightly-2021-02-28 --- .github/workflows/build-test.yml | 10 +++++----- ffi/capi/examples/fixeddecimal_tiny/Makefile | 4 ++-- tools/scripts/ffi.toml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 6ba39a5a594..0c1eb13a2d7 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -112,11 +112,11 @@ jobs: run: rustup show - name: Load cortex target for no_std build. run: | - rustup install nightly-2021-08-18 - rustup component add --toolchain nightly-2021-08-18 rust-src - rustup target add thumbv7m-none-eabi --toolchain nightly-2021-08-18 - rustup target add thumbv8m.main-none-eabihf --toolchain nightly-2021-08-18 - rustup target add x86_64-unknown-linux-gnu --toolchain nightly-2021-08-18 + rustup install nightly-2021-02-28 + rustup component add --toolchain nightly-2021-02-28 rust-src + rustup target add thumbv7m-none-eabi --toolchain nightly-2021-02-28 + rustup target add thumbv8m.main-none-eabihf --toolchain nightly-2021-02-28 + rustup target add x86_64-unknown-linux-gnu --toolchain nightly-2021-02-28 - name: Get cargo-make version id: cargo-make-version run: | diff --git a/ffi/capi/examples/fixeddecimal_tiny/Makefile b/ffi/capi/examples/fixeddecimal_tiny/Makefile index 2a780c93545..0d07fed03bb 100644 --- a/ffi/capi/examples/fixeddecimal_tiny/Makefile +++ b/ffi/capi/examples/fixeddecimal_tiny/Makefile @@ -17,10 +17,10 @@ $(ALL_HEADERS): cargo build ../../../../target/x86_64-unknown-linux-gnu/debug/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-08-18 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny ../../../../target/x86_64-unknown-linux-gnu/release/libicu_capi.a: $(ALL_RUST) - RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-08-18 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release + RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-flto -Cpanic=abort" cargo +nightly-2021-02-28 panic-abort-build --target x86_64-unknown-linux-gnu --no-default-features --features x86tiny --features smaller_static --release # Naive target: no optimizations, full std optim0.elf: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.c diff --git a/tools/scripts/ffi.toml b/tools/scripts/ffi.toml index 5037e34a786..f7dbc35e15f 100644 --- a/tools/scripts/ffi.toml +++ b/tools/scripts/ffi.toml @@ -125,7 +125,7 @@ exec --fail-on-error diplomat-tool cpp ../cpp/include --docs ../cpp/docs/source [tasks.build-wearos-ffi] description = "Build ICU4X CAPI for Cortex" category = "ICU4X FFI" -toolchain = "nightly-2021-08-18" +toolchain = "nightly-2021-02-28" env = { "RUSTFLAGS" = "-Ctarget-cpu=cortex-m33" } command = "cargo" args = ["build", "--package", "icu_capi", @@ -137,6 +137,6 @@ args = ["build", "--package", "icu_capi", [tasks.test-nostd] description = "Ensure ICU4X core builds on no-std" category = "ICU4X FFI" -toolchain = "nightly-2021-08-18" +toolchain = "nightly-2021-02-28" command = "cargo" args = ["build", "--package", "icu", "--target", "thumbv7m-none-eabi"] From fd18830005027dfd87f4d661411bff740ce88a4a Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 02:29:40 -0500 Subject: [PATCH 14/17] Rewrite resource_path_to_string for a small code size improvement --- Cargo.lock | 1 + provider/blob/Cargo.toml | 1 + provider/blob/src/path_util.rs | 13 +++++++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f384f12d8e..a2cbfb5c055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,6 +1162,7 @@ dependencies = [ "log", "postcard", "serde", + "writeable", ] [[package]] diff --git a/provider/blob/Cargo.toml b/provider/blob/Cargo.toml index 66798438c1c..a21741dd821 100644 --- a/provider/blob/Cargo.toml +++ b/provider/blob/Cargo.toml @@ -32,6 +32,7 @@ serde = { version = "1.0", default-features = false, features = ["alloc"] } postcard = { version = "0.7.0" } erased-serde = { version = "0.3", default-features = false, features = ["alloc"] } litemap = { version = "0.2.0", path = "../../utils/litemap/", features = ["serde"] } +writeable = { path = "../../utils/writeable" } # For the export feature log = { version = "0.4", optional = true } diff --git a/provider/blob/src/path_util.rs b/provider/blob/src/path_util.rs index 8ebf8084699..b0feeae4f0b 100644 --- a/provider/blob/src/path_util.rs +++ b/provider/blob/src/path_util.rs @@ -2,13 +2,14 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use alloc::string::{String, ToString}; -use alloc::vec::Vec; +use alloc::string::String; use icu_provider::prelude::*; +use writeable::Writeable; pub fn resource_path_to_string(resource_path: &ResourcePath) -> String { - let key_components = resource_path.key.get_components(); - let opt_components = resource_path.options.get_components(); - let all_components: Vec<&str> = key_components.iter().chain(opt_components.iter()).collect(); - "/".to_string() + &all_components.join("/") + let mut output = String::with_capacity(resource_path.write_len().capacity() + 1); + output.push('/'); + resource_path.write_to(&mut output) + .expect("impl Write for String is infallible"); + output } From 763efbb3041d108ca0813485f3ec30bca5d61a2c Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 03:01:09 -0500 Subject: [PATCH 15/17] Add Writeable impls for u8 and u16 for another small code size improvement --- provider/core/src/resource.rs | 23 +++------ utils/writeable/src/impls.rs | 91 +++++++++++++++++++++++++++++++++++ utils/writeable/src/lib.rs | 1 + 3 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 utils/writeable/src/impls.rs diff --git a/provider/core/src/resource.rs b/provider/core/src/resource.rs index b3a357de323..a425bc8fb09 100644 --- a/provider/core/src/resource.rs +++ b/provider/core/src/resource.rs @@ -16,6 +16,7 @@ use core::fmt; use core::fmt::Write; use icu_locid::LanguageIdentifier; use tinystr::{TinyStr16, TinyStr4}; +use writeable::{LengthHint, Writeable}; /// A top-level collection of related resource keys. #[non_exhaustive] @@ -133,35 +134,25 @@ impl fmt::Debug for ResourceKey { impl fmt::Display for ResourceKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeable::Writeable::write_to(self, f) + Writeable::write_to(self, f) } } -impl writeable::Writeable for ResourceKey { +impl Writeable for ResourceKey { fn write_to(&self, sink: &mut W) -> core::fmt::Result { sink.write_str(&self.category.as_str())?; sink.write_char('/')?; sink.write_str(self.sub_category.as_str())?; sink.write_char('@')?; - write!(sink, "{}", self.version)?; + self.version.write_to(sink)?; Ok(()) } - fn write_len(&self) -> writeable::LengthHint { - writeable::LengthHint::Exact(2) + fn write_len(&self) -> LengthHint { + LengthHint::Exact(2) + self.category.as_str().len() + self.sub_category.len() - + if self.version < 10 { - 1 - } else if self.version < 100 { - 2 - } else if self.version < 1000 { - 3 - } else if self.version < 10000 { - 4 - } else { - 5 - } + + self.version.write_len() } } diff --git a/utils/writeable/src/impls.rs b/utils/writeable/src/impls.rs new file mode 100644 index 00000000000..4d4f6d2244f --- /dev/null +++ b/utils/writeable/src/impls.rs @@ -0,0 +1,91 @@ +// 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 ). + +use crate::LengthHint; +use crate::Writeable; +use core::convert::TryFrom; +use core::fmt; +use core::str; + +impl Writeable for u8 { + fn write_to(&self, sink: &mut W) -> fmt::Result { + let mut buf = [b'0'; 3]; + let mut n = *self; + let mut i = 3usize; + while n != 0 { + i -= 1; + buf[i] = b'0' + (n % 10); + n /= 10; + } + if i == 3 { + debug_assert_eq!(*self, 0); + i = 2; + } + let s = unsafe { str::from_utf8_unchecked(&buf[i..]) }; + sink.write_str(s) + } + + fn write_len(&self) -> LengthHint { + if *self < 10 { + LengthHint::Exact(1) + } else if *self < 100 { + LengthHint::Exact(2) + } else { + LengthHint::Exact(3) + } + } +} + +impl Writeable for u16 { + fn write_to(&self, sink: &mut W) -> fmt::Result { + let mut buf = [b'0'; 5]; + let mut n = *self; + let mut i = 5usize; + while n != 0 { + i -= 1; + buf[i] = b'0' + u8::try_from(n % 10).expect("<10"); + n /= 10; + } + if i == 5 { + debug_assert_eq!(*self, 0); + i = 4; + } + let s = unsafe { str::from_utf8_unchecked(&buf[i..]) }; + sink.write_str(s) + } + + fn write_len(&self) -> LengthHint { + if *self < 10 { + LengthHint::Exact(1) + } else if *self < 100 { + LengthHint::Exact(2) + } else if *self < 1000 { + LengthHint::Exact(3) + } else if *self < 10000 { + LengthHint::Exact(4) + } else { + LengthHint::Exact(5) + } + } +} + +#[test] +fn test_u8() { + use crate::assert_writeable_eq; + assert_writeable_eq!("0", &0u8); + assert_writeable_eq!("1", &1u8); + assert_writeable_eq!("10", &10u8); + assert_writeable_eq!("99", &99u8); + assert_writeable_eq!("255", &255u8); +} + +#[test] +fn test_u16() { + use crate::assert_writeable_eq; + assert_writeable_eq!("0", &0u16); + assert_writeable_eq!("1", &1u16); + assert_writeable_eq!("10", &10u16); + assert_writeable_eq!("99", &99u16); + assert_writeable_eq!("65535", &65535u16); +} diff --git a/utils/writeable/src/lib.rs b/utils/writeable/src/lib.rs index 3bf9712804c..7b8cb88f517 100644 --- a/utils/writeable/src/lib.rs +++ b/utils/writeable/src/lib.rs @@ -53,6 +53,7 @@ extern crate alloc; +mod impls; mod ops; use alloc::string::String; From 170b4aa123bbd449e681d0875129200dde23b095 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 03:05:37 -0500 Subject: [PATCH 16/17] cargo fmt --- provider/blob/src/path_util.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/provider/blob/src/path_util.rs b/provider/blob/src/path_util.rs index b0feeae4f0b..05aef42b004 100644 --- a/provider/blob/src/path_util.rs +++ b/provider/blob/src/path_util.rs @@ -9,7 +9,8 @@ use writeable::Writeable; pub fn resource_path_to_string(resource_path: &ResourcePath) -> String { let mut output = String::with_capacity(resource_path.write_len().capacity() + 1); output.push('/'); - resource_path.write_to(&mut output) + resource_path + .write_to(&mut output) .expect("impl Write for String is infallible"); output } From 6fea8050bcd58ff34fe9789c1ca18ef836171ba5 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 18 Aug 2021 12:15:39 -0500 Subject: [PATCH 17/17] Temporarily disable test-capi-tiny on CI --- .github/workflows/build-test.yml | 2 -- ffi/capi/examples/fixeddecimal_tiny/README.md | 15 +++++++++++++++ tools/scripts/ffi.toml | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 ffi/capi/examples/fixeddecimal_tiny/README.md diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 0c1eb13a2d7..0e7be175fe8 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -145,8 +145,6 @@ jobs: packages: | sphinx sphinx-rtd-theme - - name: Install LLVM tooling - run: sudo apt-get install clang lld - name: Install Diplomat uses: actions-rs/cargo@v1.0.1 diff --git a/ffi/capi/examples/fixeddecimal_tiny/README.md b/ffi/capi/examples/fixeddecimal_tiny/README.md new file mode 100644 index 00000000000..1adc91d9f5e --- /dev/null +++ b/ffi/capi/examples/fixeddecimal_tiny/README.md @@ -0,0 +1,15 @@ +# Tiny FixedDecimal FFI Demo + +This example contains tooling to build a size-optimized binary using FixedDecimal and FixedDecimalFormat in C over FFI. + +Prerequisites: `clang` and `lld`, which must be compatible with the Rust toolchain. `apt-get install clang lld` *might* work, but if you run into errors, refer to the following thread for tips: + +https://github.com/rust-lang/rust/issues/60059 + +You also need to install the correct toolchains: + +```bash +$ rustup install nightly-2021-02-28 +$ rustup component add --toolchain nightly-2021-02-28 rust-src +$ rustup target add x86_64-unknown-linux-gnu --toolchain nightly-2021-02-28 +``` diff --git a/tools/scripts/ffi.toml b/tools/scripts/ffi.toml index f7dbc35e15f..b2708b50e16 100644 --- a/tools/scripts/ffi.toml +++ b/tools/scripts/ffi.toml @@ -10,7 +10,8 @@ category = "ICU4X Development" dependencies = [ "verify-diplomat-gen", "test-capi", - "test-capi-tiny", + # TODO(#964): Enable this CI test. + # "test-capi-tiny", "test-cpp", "build-wearos-ffi", "test-nostd",