From 8cd532db71d0674ca4f78a40515ae3f5f1fb1cd6 Mon Sep 17 00:00:00 2001 From: Robert Bastian <4706271+robertbastian@users.noreply.github.com> Date: Thu, 1 Feb 2024 18:38:05 +0100 Subject: [PATCH 1/8] hb --- components/normalizer/src/properties.rs | 2 +- components/properties/src/props.rs | 6 +- experimental/harfbuzz/Cargo.toml | 1 + experimental/harfbuzz/src/lib.rs | 307 +++++++++++++++++------- 4 files changed, 226 insertions(+), 90 deletions(-) diff --git a/components/normalizer/src/properties.rs b/components/normalizer/src/properties.rs index 631cb281fda..9794d5209cd 100644 --- a/components/normalizer/src/properties.rs +++ b/components/normalizer/src/properties.rs @@ -90,7 +90,7 @@ impl CanonicalComposition { /// /// [📚 Help choosing a constructor](icu_provider::constructors) #[cfg(feature = "compiled_data")] - pub fn new() -> Self { + pub const fn new() -> Self { Self { canonical_compositions: DataPayload::from_static_ref( crate::provider::Baked::SINGLETON_NORMALIZER_COMP_V1, diff --git a/components/properties/src/props.rs b/components/properties/src/props.rs index fbae09531bb..1ac8378b2b8 100644 --- a/components/properties/src/props.rs +++ b/components/properties/src/props.rs @@ -585,7 +585,7 @@ macro_rules! impl_value_getter { impl $ty { $(#[$attr_n2e])* #[cfg(feature = "compiled_data")] - $vis_n2e fn $cname_n2e() -> PropertyValueNameToEnumMapperBorrowed<'static, $ty> { + $vis_n2e const fn $cname_n2e() -> PropertyValueNameToEnumMapperBorrowed<'static, $ty> { PropertyValueNameToEnumMapperBorrowed { map: crate::provider::Baked::$singleton_n2e, markers: PhantomData, @@ -604,7 +604,7 @@ macro_rules! impl_value_getter { $( $(#[$attr_e2sn])* #[cfg(feature = "compiled_data")] - $vis_e2sn fn $cname_e2sn() -> $mapper_e2snb<'static, $ty> { + $vis_e2sn const fn $cname_e2sn() -> $mapper_e2snb<'static, $ty> { $mapper_e2snb { map: crate::provider::Baked::$singleton_e2sn, markers: PhantomData, @@ -622,7 +622,7 @@ macro_rules! impl_value_getter { $(#[$attr_e2ln])* #[cfg(feature = "compiled_data")] - $vis_e2ln fn $cname_e2ln() -> $mapper_e2lnb<'static, $ty> { + $vis_e2ln const fn $cname_e2ln() -> $mapper_e2lnb<'static, $ty> { $mapper_e2lnb { map: crate::provider::Baked::$singleton_e2ln, markers: PhantomData, diff --git a/experimental/harfbuzz/Cargo.toml b/experimental/harfbuzz/Cargo.toml index ba3b4f09f9c..f05f62b0a4a 100644 --- a/experimental/harfbuzz/Cargo.toml +++ b/experimental/harfbuzz/Cargo.toml @@ -44,5 +44,6 @@ harfbuzz = { version = "0.4.0" } [features] default = [] compiled_data = ["icu_normalizer/compiled_data", "icu_properties/compiled_data"] +alloc = [] std = [] serde = ["icu_properties/serde", "icu_normalizer/serde", "icu_provider/serde"] diff --git a/experimental/harfbuzz/src/lib.rs b/experimental/harfbuzz/src/lib.rs index 9a8054dfc59..b46e0e056ba 100644 --- a/experimental/harfbuzz/src/lib.rs +++ b/experimental/harfbuzz/src/lib.rs @@ -41,31 +41,43 @@ //! assert_eq!(b.get_script(), sys::HB_SCRIPT_ARABIC); //! ``` +#[cfg(feature = "alloc")] extern crate alloc; mod error; use crate::error::HarfBuzzError; -use alloc::boxed::Box; use core::ffi::{c_char, c_void}; use harfbuzz_sys::*; use icu_normalizer::properties::CanonicalCombiningClassMap; use icu_normalizer::properties::CanonicalComposition; use icu_normalizer::properties::CanonicalDecomposition; use icu_normalizer::properties::Decomposed; -use icu_normalizer::provider::CanonicalCompositionsV1Marker; -use icu_normalizer::provider::CanonicalDecompositionDataV1Marker; -use icu_normalizer::provider::CanonicalDecompositionTablesV1Marker; -use icu_normalizer::provider::NonRecursiveDecompositionSupplementV1Marker; +#[cfg(feature = "alloc")] +use icu_normalizer::provider::{ + CanonicalCompositionsV1Marker, CanonicalDecompositionDataV1Marker, + CanonicalDecompositionTablesV1Marker, NonRecursiveDecompositionSupplementV1Marker, +}; +use icu_properties::bidi_data; +#[cfg(feature = "alloc")] use icu_properties::bidi_data::BidiAuxiliaryProperties; +use icu_properties::bidi_data::BidiAuxiliaryPropertiesBorrowed; +use icu_properties::maps; +#[cfg(feature = "alloc")] use icu_properties::maps::CodePointMapData; +use icu_properties::maps::CodePointMapDataBorrowed; +#[cfg(feature = "alloc")] use icu_properties::names::PropertyEnumToValueNameLinearTiny4Mapper; +use icu_properties::names::PropertyEnumToValueNameLinearTiny4MapperBorrowed; +#[cfg(feature = "alloc")] use icu_properties::provider::bidi_data::BidiAuxiliaryPropertiesV1Marker; +#[cfg(feature = "alloc")] use icu_properties::provider::{ GeneralCategoryV1Marker, ScriptV1Marker, ScriptValueToShortNameV1Marker, }; use icu_properties::{GeneralCategory, Script}; +#[cfg(feature = "alloc")] use icu_provider::prelude::*; -use tinystr::{tinystr, TinyStr4}; +use tinystr::tinystr; /// The total number of General Category values is fixed per /// https://www.unicode.org/policies/stability_policy.html : @@ -116,35 +128,47 @@ static ICU4X_GENERAL_CATEGORY_TO_HARFBUZZ: [u8; 30] = [ unsafe extern "C" fn icu4x_hb_unicode_combining_class( _ufuncs: *mut hb_unicode_funcs_t, unicode: hb_codepoint_t, - user_data: *mut c_void, + #[cfg_attr(not(feature = "alloc"), allow(unused_variables))] user_data: *mut c_void, ) -> hb_unicode_combining_class_t { - (*(user_data as *mut CanonicalCombiningClassMap)) - .get32(unicode) - .0 as hb_unicode_combining_class_t -} + #[cfg(feature = "compiled_data")] + const CCC_MAP: Option = Some(CanonicalCombiningClassMap::new()); + #[cfg(not(feature = "compiled_data"))] + const CCC_MAP: Option = None; + + #[cfg(feature = "alloc")] + let ccc_map = (user_data as *mut CanonicalCombiningClassMap).as_ref(); + #[cfg(not(feature = "alloc"))] + let ccc_map = None; -unsafe extern "C" fn icu4x_hb_unicode_combining_class_destroy(user_data: *mut c_void) { - let _ = Box::from_raw(user_data as *mut CanonicalCombiningClassMap); + ccc_map.or(CCC_MAP.as_ref()).unwrap_unchecked().get32(unicode).0 as hb_unicode_combining_class_t } #[allow(clippy::indexing_slicing)] unsafe extern "C" fn icu4x_hb_unicode_general_category( _ufuncs: *mut hb_unicode_funcs_t, unicode: hb_codepoint_t, - user_data: *mut c_void, + #[cfg_attr(not(feature = "alloc"), allow(unused_variables))] user_data: *mut c_void, ) -> hb_unicode_general_category_t { + #[cfg(feature = "compiled_data")] + const GC_MAP: Option> = + Some(maps::general_category()); + #[cfg(not(feature = "compiled_data"))] + const GC_MAP: Option> = None; + + #[cfg(feature = "alloc")] + let gc_map = (user_data as *mut CodePointMapData) + .as_ref() + .map(CodePointMapData::as_borrowed); + #[cfg(not(feature = "alloc"))] + let gc_map = None; + // Indexing is OK, because `GeneralCategory` data is validated upon // deserialization so that there can be no out-of-range `GeneralCategory` // values (which would be UB to materialize). `GeneralCategory` is a // stable exhaustive enum, and the length of `ICU4X_GENERAL_CATEGORY_TO_HARFBUZZ` // matches the number of enum items, so the index will always be in range here. - ICU4X_GENERAL_CATEGORY_TO_HARFBUZZ[(*(user_data as *mut CodePointMapData)) - .as_borrowed() - .get32(unicode) as usize] as hb_unicode_general_category_t -} - -unsafe extern "C" fn icu4x_hb_unicode_general_category_destroy(user_data: *mut c_void) { - let _ = Box::from_raw(user_data as *mut CodePointMapData); + ICU4X_GENERAL_CATEGORY_TO_HARFBUZZ[gc_map.or(GC_MAP).unwrap_unchecked().get32(unicode) as usize] + as hb_unicode_general_category_t } /// Returns the Bidi_Mirroring_Glyph, but adjusting the return value @@ -158,20 +182,30 @@ unsafe extern "C" fn icu4x_hb_unicode_general_category_destroy(user_data: *mut c unsafe extern "C" fn icu4x_hb_unicode_mirroring( _ufuncs: *mut hb_unicode_funcs_t, unicode: hb_codepoint_t, - user_data: *mut c_void, + #[cfg_attr(not(feature = "alloc"), allow(unused_variables))] user_data: *mut c_void, ) -> hb_codepoint_t { - (*(user_data as *mut BidiAuxiliaryProperties)) - .as_borrowed() + #[cfg(feature = "compiled_data")] + const BIDI: Option> = + Some(bidi_data::bidi_auxiliary_properties()); + #[cfg(not(feature = "compiled_data"))] + const BIDI: Option> = None; + + #[cfg(feature = "alloc")] + let bidi = (user_data as *mut BidiAuxiliaryProperties) + .as_ref() + .map(BidiAuxiliaryProperties::as_borrowed); + #[cfg(not(feature = "alloc"))] + let bidi = None; + + bidi.or(BIDI) + .unwrap_unchecked() .get32_mirroring_props(unicode) .mirroring_glyph .map(u32::from) .unwrap_or(unicode) as hb_codepoint_t } -unsafe extern "C" fn icu4x_hb_unicode_mirroring_destroy(user_data: *mut c_void) { - let _ = Box::from_raw(user_data as *mut BidiAuxiliaryProperties); -} - +#[cfg(feature = "alloc")] struct ScriptDataForHarfBuzz { script_map: CodePointMapData