Skip to content

Commit

Permalink
Bug 1767961 - Part 2: Switch fluent-ffi to use TryCreateFromComponent…
Browse files Browse the repository at this point in the history
…s. r=platform-i18n-reviewers,dminor

Instead of creating a skeleton from the components bag on the Rust side,
directly pass the Rust components bag and translate it into the C++
components bag after crossing the FFI boundary.

Depends on D145580

Differential Revision: https://phabricator.services.mozilla.com/D145581
  • Loading branch information
anba committed May 5, 2022
1 parent e6d82f6 commit 8459959
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 104 deletions.
124 changes: 115 additions & 9 deletions intl/l10n/FluentBundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,117 @@ static Maybe<DateTimeFormat::Style> GetStyle(ffi::FluentDateTimeStyle aStyle) {
return Nothing();
}

static Maybe<DateTimeFormat::Text> GetText(
ffi::FluentDateTimeTextComponent aText) {
switch (aText) {
case ffi::FluentDateTimeTextComponent::Long:
return Some(DateTimeFormat::Text::Long);
case ffi::FluentDateTimeTextComponent::Short:
return Some(DateTimeFormat::Text::Short);
case ffi::FluentDateTimeTextComponent::Narrow:
return Some(DateTimeFormat::Text::Narrow);
case ffi::FluentDateTimeTextComponent::None:
return Nothing();
}
MOZ_ASSERT_UNREACHABLE();
return Nothing();
}

static Maybe<DateTimeFormat::Month> GetMonth(
ffi::FluentDateTimeMonthComponent aMonth) {
switch (aMonth) {
case ffi::FluentDateTimeMonthComponent::Numeric:
return Some(DateTimeFormat::Month::Numeric);
case ffi::FluentDateTimeMonthComponent::TwoDigit:
return Some(DateTimeFormat::Month::TwoDigit);
case ffi::FluentDateTimeMonthComponent::Long:
return Some(DateTimeFormat::Month::Long);
case ffi::FluentDateTimeMonthComponent::Short:
return Some(DateTimeFormat::Month::Short);
case ffi::FluentDateTimeMonthComponent::Narrow:
return Some(DateTimeFormat::Month::Narrow);
case ffi::FluentDateTimeMonthComponent::None:
return Nothing();
}
MOZ_ASSERT_UNREACHABLE();
return Nothing();
}

static Maybe<DateTimeFormat::Numeric> GetNumeric(
ffi::FluentDateTimeNumericComponent aNumeric) {
switch (aNumeric) {
case ffi::FluentDateTimeNumericComponent::Numeric:
return Some(DateTimeFormat::Numeric::Numeric);
case ffi::FluentDateTimeNumericComponent::TwoDigit:
return Some(DateTimeFormat::Numeric::TwoDigit);
case ffi::FluentDateTimeNumericComponent::None:
return Nothing();
}
MOZ_ASSERT_UNREACHABLE();
return Nothing();
}

static Maybe<DateTimeFormat::TimeZoneName> GetTimeZoneName(
ffi::FluentDateTimeTimeZoneNameComponent aTimeZoneName) {
switch (aTimeZoneName) {
case ffi::FluentDateTimeTimeZoneNameComponent::Long:
return Some(DateTimeFormat::TimeZoneName::Long);
case ffi::FluentDateTimeTimeZoneNameComponent::Short:
return Some(DateTimeFormat::TimeZoneName::Short);
case ffi::FluentDateTimeTimeZoneNameComponent::None:
return Nothing();
}
MOZ_ASSERT_UNREACHABLE();
return Nothing();
}

static Maybe<DateTimeFormat::HourCycle> GetHourCycle(
ffi::FluentDateTimeHourCycle aHourCycle) {
switch (aHourCycle) {
case ffi::FluentDateTimeHourCycle::H24:
return Some(DateTimeFormat::HourCycle::H24);
case ffi::FluentDateTimeHourCycle::H23:
return Some(DateTimeFormat::HourCycle::H23);
case ffi::FluentDateTimeHourCycle::H12:
return Some(DateTimeFormat::HourCycle::H12);
case ffi::FluentDateTimeHourCycle::H11:
return Some(DateTimeFormat::HourCycle::H11);
case ffi::FluentDateTimeHourCycle::None:
return Nothing();
}
MOZ_ASSERT_UNREACHABLE();
return Nothing();
}

static Maybe<DateTimeFormat::ComponentsBag> GetComponentsBag(
ffi::FluentDateTimeOptions aOptions) {
if (GetStyle(aOptions.date_style) || GetStyle(aOptions.time_style)) {
return Nothing();
}

DateTimeFormat::ComponentsBag components;
components.era = GetText(aOptions.era);
components.year = GetNumeric(aOptions.year);
components.month = GetMonth(aOptions.month);
components.day = GetNumeric(aOptions.day);
components.weekday = GetText(aOptions.weekday);
components.hour = GetNumeric(aOptions.hour);
components.minute = GetNumeric(aOptions.minute);
components.second = GetNumeric(aOptions.second);
components.timeZoneName = GetTimeZoneName(aOptions.time_zone_name);
components.hourCycle = GetHourCycle(aOptions.hour_cycle);

if (!components.era && !components.year && !components.month &&
!components.day && !components.weekday && !components.hour &&
!components.minute && !components.second && !components.timeZoneName) {
return Nothing();
}

return Some(components);
}

ffi::RawDateTimeFormatter* FluentBuiltInDateTimeFormatterCreate(
const nsCString* aLocale, const ffi::FluentDateTimeOptionsRaw* aOptions) {
const nsCString* aLocale, ffi::FluentDateTimeOptions aOptions) {
auto genResult = DateTimePatternGenerator::TryCreate(aLocale->get());
if (genResult.isErr()) {
MOZ_ASSERT_UNREACHABLE("There was an error in DateTimeFormat");
Expand All @@ -351,12 +460,9 @@ ffi::RawDateTimeFormatter* FluentBuiltInDateTimeFormatterCreate(
UniquePtr<DateTimePatternGenerator> dateTimePatternGenerator =
genResult.unwrap();

if (aOptions->date_style == ffi::FluentDateTimeStyle::None &&
aOptions->time_style == ffi::FluentDateTimeStyle::None &&
!aOptions->skeleton.IsEmpty()) {
auto result = DateTimeFormat::TryCreateFromSkeleton(
Span(*aLocale), Span(*aOptions->skeleton),
dateTimePatternGenerator.get());
if (auto components = GetComponentsBag(aOptions)) {
auto result = DateTimeFormat::TryCreateFromComponents(
Span(*aLocale), *components, dateTimePatternGenerator.get());
if (result.isErr()) {
MOZ_ASSERT_UNREACHABLE("There was an error in DateTimeFormat");
return nullptr;
Expand All @@ -367,8 +473,8 @@ ffi::RawDateTimeFormatter* FluentBuiltInDateTimeFormatterCreate(
}

DateTimeFormat::StyleBag style;
style.date = GetStyle(aOptions->date_style);
style.time = GetStyle(aOptions->time_style);
style.date = GetStyle(aOptions.date_style);
style.time = GetStyle(aOptions.time_style);

auto result = DateTimeFormat::TryCreateFromStyle(
Span(*aLocale), style, dateTimePatternGenerator.get());
Expand Down
99 changes: 6 additions & 93 deletions intl/l10n/rust/fluent-ffi/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ impl From<&str> for FluentDateTimeStyle {
}
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeHourCycle {
H24,
Expand Down Expand Up @@ -129,6 +130,7 @@ impl From<&str> for FluentDateTimeHourCycle {
}
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeTextComponent {
Long,
Expand All @@ -154,6 +156,7 @@ impl From<&str> for FluentDateTimeTextComponent {
}
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeNumericComponent {
Numeric,
Expand All @@ -177,6 +180,7 @@ impl From<&str> for FluentDateTimeNumericComponent {
}
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeMonthComponent {
Numeric,
Expand Down Expand Up @@ -206,6 +210,7 @@ impl From<&str> for FluentDateTimeMonthComponent {
}
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeTimeZoneNameComponent {
Long,
Expand Down Expand Up @@ -292,98 +297,6 @@ impl FluentDateTimeOptions {
}
}

#[repr(C)]
pub struct FluentDateTimeOptionsRaw {
pub date_style: FluentDateTimeStyle,
pub time_style: FluentDateTimeStyle,
pub skeleton: nsCString,
}

impl FluentDateTimeOptionsRaw {
fn convert_options_to_skeleton(input: &FluentDateTimeOptions) -> String {
let mut result = String::new();

match input.weekday {
FluentDateTimeTextComponent::Narrow => result.push_str("EEEEE"),
FluentDateTimeTextComponent::Short => result.push_str("E"),
FluentDateTimeTextComponent::Long => result.push_str("EEEE"),
FluentDateTimeTextComponent::None => {}
}
match input.era {
FluentDateTimeTextComponent::Narrow => result.push_str("GGGGG"),
FluentDateTimeTextComponent::Short => result.push_str("G"),
FluentDateTimeTextComponent::Long => result.push_str("GGGG"),
FluentDateTimeTextComponent::None => {}
}
match input.year {
FluentDateTimeNumericComponent::Numeric => result.push_str("y"),
FluentDateTimeNumericComponent::TwoDigit => result.push_str("yy"),
FluentDateTimeNumericComponent::None => {}
}
match input.month {
FluentDateTimeMonthComponent::Numeric => result.push_str("M"),
FluentDateTimeMonthComponent::TwoDigit => result.push_str("MM"),
FluentDateTimeMonthComponent::Narrow => result.push_str("MMMMM"),
FluentDateTimeMonthComponent::Short => result.push_str("MMM"),
FluentDateTimeMonthComponent::Long => result.push_str("MMMM"),
FluentDateTimeMonthComponent::None => {}
}
match input.day {
FluentDateTimeNumericComponent::Numeric => result.push_str("d"),
FluentDateTimeNumericComponent::TwoDigit => result.push_str("dd"),
FluentDateTimeNumericComponent::None => {}
}
let hour_skeleton_char = match input.hour_cycle {
FluentDateTimeHourCycle::H24 => 'H',
FluentDateTimeHourCycle::H23 => 'H',
FluentDateTimeHourCycle::H12 => 'h',
FluentDateTimeHourCycle::H11 => 'h',
FluentDateTimeHourCycle::None => 'j',
};
match input.hour {
FluentDateTimeNumericComponent::Numeric => result.push(hour_skeleton_char),
FluentDateTimeNumericComponent::TwoDigit => {
result.push(hour_skeleton_char);
result.push(hour_skeleton_char);
}
FluentDateTimeNumericComponent::None => {}
}
match input.minute {
FluentDateTimeNumericComponent::Numeric => result.push_str("m"),
FluentDateTimeNumericComponent::TwoDigit => result.push_str("mm"),
FluentDateTimeNumericComponent::None => {}
}
match input.second {
FluentDateTimeNumericComponent::Numeric => result.push_str("s"),
FluentDateTimeNumericComponent::TwoDigit => result.push_str("ss"),
FluentDateTimeNumericComponent::None => {}
}
match input.time_zone_name {
FluentDateTimeTimeZoneNameComponent::Short => result.push_str("z"),
FluentDateTimeTimeZoneNameComponent::Long => result.push_str("zzzz"),
FluentDateTimeTimeZoneNameComponent::None => {}
}
result
}
}

impl From<&FluentDateTimeOptions> for FluentDateTimeOptionsRaw {
fn from(input: &FluentDateTimeOptions) -> Self {
let skeleton = if input.date_style == FluentDateTimeStyle::None
&& input.time_style == FluentDateTimeStyle::None
{
Self::convert_options_to_skeleton(&input).into()
} else {
nsCString::new()
};
Self {
date_style: input.date_style,
time_style: input.time_style,
skeleton,
}
}
}

#[derive(Debug, PartialEq, Clone)]
pub struct FluentDateTime {
epoch: f64,
Expand Down Expand Up @@ -441,7 +354,7 @@ impl DateTimeFormat {
raw: unsafe {
NonNull::new(ffi::FluentBuiltInDateTimeFormatterCreate(
&loc,
&(&options).into(),
options,
))
},
}
Expand Down
4 changes: 2 additions & 2 deletions intl/l10n/rust/fluent-ffi/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::builtins::FluentDateTimeOptionsRaw;
use crate::builtins::FluentDateTimeOptions;
use fluent::types::FluentNumberCurrencyDisplayStyle;
use fluent::types::FluentNumberOptions;
use fluent::types::FluentNumberStyle;
Expand Down Expand Up @@ -143,7 +143,7 @@ extern "C" {

pub fn FluentBuiltInDateTimeFormatterCreate(
locale: &nsCString,
options: &FluentDateTimeOptionsRaw,
options: FluentDateTimeOptions,
) -> *mut RawDateTimeFormatter;
pub fn FluentBuiltInDateTimeFormatterFormat(
formatter: *const RawDateTimeFormatter,
Expand Down

0 comments on commit 8459959

Please sign in to comment.