Skip to content

Commit

Permalink
DigitalDurationMarker provider impl
Browse files Browse the repository at this point in the history
  • Loading branch information
kartva committed Jul 5, 2024
1 parent 3ab47de commit b14c65a
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -179,36 +179,6 @@ impl ValidatedDurationFormatterOptions {

Ok(builder.try_into().unwrap())
}

/// Iterates over all unit fields of the struct, returning a tuple of the unit,
/// and mutable references to its style and the visibility.
#[allow(dead_code)]
pub(crate) fn iter_units(&mut self) -> [(Unit, &mut FieldStyle, &mut FieldDisplay); 10] {
[
(Unit::Year, &mut self.year, &mut self.year_visibility),
(Unit::Month, &mut self.month, &mut self.month_visibility),
(Unit::Week, &mut self.week, &mut self.week_visibility),
(Unit::Day, &mut self.day, &mut self.day_visibility),
(Unit::Hour, &mut self.hour, &mut self.hour_visibility),
(Unit::Minute, &mut self.minute, &mut self.minute_visibility),
(Unit::Second, &mut self.second, &mut self.second_visibility),
(
Unit::Millisecond,
&mut self.millisecond,
&mut self.millisecond_visibility,
),
(
Unit::Microsecond,
&mut self.microsecond,
&mut self.microsecond_visibility,
),
(
Unit::Nanosecond,
&mut self.nanosecond,
&mut self.nanosecond_visibility,
),
]
}
}

/// Validated options builder for [DurationFormatter](DurationFormatter).
Expand Down
2 changes: 2 additions & 0 deletions components/experimental/src/duration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

mod duration;
mod formatter;
pub mod provider;

pub mod options;

pub use duration::{Duration, DurationSign};
Expand Down
61 changes: 61 additions & 0 deletions components/experimental/src/duration/provider/digital.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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 ).

// Provider structs must be stable
#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]

//! Data provider struct definitions for this ICU4X component.
//!
//! Read more about data providers: [`icu_provider`]
use alloc::borrow::Cow;
use core::str::FromStr;

use displaydoc::Display;
use icu_provider::prelude::*;

#[icu_provider::data_struct(DigitalDurationDataV1Marker = "duration/digital@1")]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "datagen",
derive(serde::Serialize, databake::Bake),
databake(path = icu_experimental::duration::provider)
)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]

/// A struct containing digital duration data (durationUnit-type-* patterns).
pub struct DigitalDurationDataV1 <'data> {
separator: Cow<str, 'data>,
hour_padding: u8
}

/// Unknown time pattern: {0}
#[derive(Debug, Display)]
pub struct UnknownPatternError(String);

impl<'data> FromStr for DigitalDurationDataV1<'data> {
type Err = UnknownPatternError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"hh:mm:ss" => Ok(DigitalDurationDataV1 {
separator: ":".into(),
hour_padding: 2
}),
"h:mm:ss" => Ok(DigitalDurationDataV1 {
separator: ":".into(),
hour_padding: 1
}),
"h.mm.ss" => Ok(DigitalDurationDataV1 {
separator: ".".into(),
hour_padding: 1
}),
"h,mm,ss" => Ok(DigitalDurationDataV1 {
separator: ",".into(),
hour_padding: 1
}),
_ => Err(UnknownPatternError(s.to_string())),
}
}
}
5 changes: 5 additions & 0 deletions components/experimental/src/duration/provider/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// 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 ).

pub mod digital;
2 changes: 2 additions & 0 deletions components/experimental/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub mod provider {
impl_currency_essentials_v1_marker!(Baked);
impl_units_display_name_v1_marker!(Baked);
impl_units_essentials_v1_marker!(Baked);
impl_duration_digital_data_v1_marker!(Baked);
impl_language_display_names_v1_marker!(Baked);
impl_locale_display_names_v1_marker!(Baked);
impl_region_display_names_v1_marker!(Baked);
Expand Down Expand Up @@ -95,6 +96,7 @@ pub mod provider {
super::dimension::provider::percent::PercentEssentialsV1Marker::INFO,
super::dimension::provider::units_essentials::UnitsEssentialsV1Marker::INFO,
super::dimension::provider::units::UnitsDisplayNameV1Marker::INFO,
super::duration::provider::digital::DigitalDurationDataV1Marker::INFO,
super::displaynames::provider::LanguageDisplayNamesV1Marker::INFO,
super::displaynames::provider::LocaleDisplayNamesV1Marker::INFO,
super::displaynames::provider::RegionDisplayNamesV1Marker::INFO,
Expand Down
56 changes: 56 additions & 0 deletions provider/bikeshed/src/duration/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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::cldr_serde;
use crate::cldr_serde::units::data::DurationUnits;
use crate::DatagenProvider;
use icu_provider::prelude::*;
use std::collections::HashSet;
use std::str::FromStr;

use icu::experimental::duration::provider::digital::{
DigitalDurationDataV1, DigitalDurationDataV1Marker,
};

impl DataProvider<DigitalDurationDataV1Marker> for DatagenProvider {
fn load(
&self,
req: DataRequest,
) -> Result<DataResponse<DigitalDurationDataV1Marker>, DataError> {
self.check_req::<DigitalDurationDataV1Marker>(req)?;
let langid = req.id.locale.get_langid();

// Get units
let units_format_data: &cldr_serde::units::data::Resource =
self.cldr()?.units().read_and_parse(&langid, "units.json")?;
let DurationUnits { hms, .. } = &units_format_data.main.value.units.duration;

let result = DigitalDurationDataV1::from_str(&hms.pat).map_err(|err| {
DataError::custom("Failed to convert hms pattern: ").with_debug_context(&err)
})?;

Ok(DataResponse {
metadata: Default::default(),
payload: DataPayload::from_owned(result),
})
}
}

impl crate::IterableDataProviderCached<DigitalDurationDataV1Marker> for DatagenProvider {
fn iter_ids_cached(&self) -> Result<HashSet<DataIdentifierCow<'static>>, DataError> {
Ok(self
.cldr()?
.numbers()
.list_langs()?
.filter(|langid| {
self.cldr()
.unwrap()
.units()
.read_and_parse::<cldr_serde::units::data::Resource>(langid, "units.json")
.is_ok()
})
.map(|langid| DataIdentifierCow::from_locale(DataLocale::from(&langid)))
.collect())
}
}
1 change: 1 addition & 0 deletions provider/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ macro_rules! registry(
icu::experimental::dimension::provider::percent::PercentEssentialsV1Marker = "percent/essentials@1",
icu::experimental::dimension::provider::units::UnitsDisplayNameV1Marker = "units/displaynames@1",
icu::experimental::dimension::provider::units_essentials::UnitsEssentialsV1Marker = "units/essentials@1",
icu::experimental::duration::provider::digital::DigitalDurationDataV1Marker = "duration/digital@1",
icu::experimental::displaynames::provider::RegionDisplayNamesV1Marker = "displaynames/regions@1",
icu::experimental::displaynames::provider::LanguageDisplayNamesV1Marker = "displaynames/languages@1",
icu::experimental::displaynames::provider::LocaleDisplayNamesV1Marker = "displaynames/locales@1",
Expand Down
21 changes: 21 additions & 0 deletions provider/source/src/cldr_serde/units/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ pub(crate) struct Patterns {
pub(crate) other_compound_unit_pattern1: Option<String>,
}

#[derive(PartialEq, Debug, Deserialize)]
pub struct DurationUnit {
#[serde(rename = "durationUnitPattern")]
pub(crate) pat: String,
#[serde(rename = "durationUnitPattern-alt-variant")]
pub(crate) alt_pat: Option<String>,
}

#[derive(PartialEq, Debug, Deserialize)]
pub struct DurationUnits {
#[serde(rename = "durationUnit-type-hm")]
pub hm: DurationUnit,
#[serde(rename = "durationUnit-type-hms")]
pub hms: DurationUnit,
#[serde(rename = "durationUnit-type-ms")]
pub ms: DurationUnit,
}

// TODO: replace Value with specific structs
#[derive(PartialEq, Debug, Deserialize)]
pub(crate) struct UnitsData {
Expand All @@ -70,6 +88,9 @@ pub(crate) struct UnitsData {
pub(crate) short: BTreeMap<String, Patterns>,

pub(crate) narrow: BTreeMap<String, Patterns>,

#[serde(flatten)]
pub(crate) duration: DurationUnits,
}

#[derive(PartialEq, Debug, Deserialize)]
Expand Down
2 changes: 2 additions & 0 deletions provider/source/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ mod datetime;
mod decimal;
#[cfg(feature = "experimental")]
mod displaynames;
#[cfg(feature = "experimental")]
mod duration;
mod fallback;
#[cfg(test)]
mod hello_world;
Expand Down

0 comments on commit b14c65a

Please sign in to comment.