Skip to content

Commit

Permalink
Merge branch 'main' into normalizecow
Browse files Browse the repository at this point in the history
  • Loading branch information
hsivonen authored Dec 18, 2024
2 parents d1b33d8 + 5f103cb commit 7d0033e
Show file tree
Hide file tree
Showing 247 changed files with 40,158 additions and 29,338 deletions.
14 changes: 7 additions & 7 deletions components/collator/src/comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ use crate::provider::CollationTailoringV1Marker;
use crate::{AlternateHandling, CollatorOptions, MaxVariable, ResolvedCollatorOptions, Strength};
use core::cmp::Ordering;
use core::convert::TryFrom;
use icu_normalizer::provider::CanonicalDecompositionDataV1Marker;
use icu_normalizer::provider::CanonicalDecompositionDataV2Marker;
use icu_normalizer::provider::CanonicalDecompositionTablesV1Marker;
use icu_normalizer::provider::DecompositionDataV1;
use icu_normalizer::provider::DecompositionDataV2;
use icu_normalizer::provider::DecompositionTablesV1;
use icu_normalizer::Decomposition;
use icu_provider::prelude::*;
Expand Down Expand Up @@ -220,7 +220,7 @@ pub struct Collator {
diacritics: DataPayload<CollationDiacriticsV1Marker>,
options: CollatorOptionsBitField,
reordering: Option<DataPayload<CollationReorderingV1Marker>>,
decompositions: DataPayload<CanonicalDecompositionDataV1Marker>,
decompositions: DataPayload<CanonicalDecompositionDataV2Marker>,
tables: DataPayload<CanonicalDecompositionTablesV1Marker>,
lithuanian_dot_above: bool,
}
Expand Down Expand Up @@ -276,7 +276,7 @@ impl Collator {
+ DataProvider<CollationJamoV1Marker>
+ DataProvider<CollationMetadataV1Marker>
+ DataProvider<CollationReorderingV1Marker>
+ DataProvider<CanonicalDecompositionDataV1Marker>
+ DataProvider<CanonicalDecompositionDataV2Marker>
+ DataProvider<CanonicalDecompositionTablesV1Marker>
+ ?Sized,
{
Expand All @@ -296,7 +296,7 @@ impl Collator {
fn try_new_unstable_internal<D>(
provider: &D,
root: DataPayload<CollationRootV1Marker>,
decompositions: DataPayload<CanonicalDecompositionDataV1Marker>,
decompositions: DataPayload<CanonicalDecompositionDataV2Marker>,
tables: DataPayload<CanonicalDecompositionTablesV1Marker>,
jamo: DataPayload<CollationJamoV1Marker>,
special_primaries: impl FnOnce() -> Result<
Expand Down Expand Up @@ -364,7 +364,7 @@ pub struct CollatorBorrowed<'a> {
diacritics: &'a CollationDiacriticsV1<'a>,
options: CollatorOptionsBitField,
reordering: Option<&'a CollationReorderingV1<'a>>,
decompositions: &'a DecompositionDataV1<'a>,
decompositions: &'a DecompositionDataV2<'a>,
tables: &'a DecompositionTablesV1<'a>,
lithuanian_dot_above: bool,
}
Expand All @@ -381,7 +381,7 @@ impl CollatorBorrowed<'static> {

let provider = &crate::provider::Baked;
let decompositions =
icu_normalizer::provider::Baked::SINGLETON_CANONICAL_DECOMPOSITION_DATA_V1_MARKER;
icu_normalizer::provider::Baked::SINGLETON_CANONICAL_DECOMPOSITION_DATA_V2_MARKER;
let tables =
icu_normalizer::provider::Baked::SINGLETON_CANONICAL_DECOMPOSITION_TABLES_V1_MARKER;
let root = crate::provider::Baked::SINGLETON_COLLATION_ROOT_V1_MARKER;
Expand Down
189 changes: 84 additions & 105 deletions components/collator/src/elements.rs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions components/collator/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ const _: () = {

icu_normalizer_data::impl_canonical_compositions_v1_marker!(TestingProvider);
icu_normalizer_data::impl_non_recursive_decomposition_supplement_v1_marker!(TestingProvider);
icu_normalizer_data::impl_canonical_decomposition_data_v1_marker!(TestingProvider);
icu_normalizer_data::impl_canonical_decomposition_data_v2_marker!(TestingProvider);
icu_normalizer_data::impl_canonical_decomposition_tables_v1_marker!(TestingProvider);
icu_normalizer_data::impl_compatibility_decomposition_supplement_v1_marker!(TestingProvider);
icu_normalizer_data::impl_compatibility_decomposition_data_v2_marker!(TestingProvider);
icu_normalizer_data::impl_compatibility_decomposition_tables_v1_marker!(TestingProvider);
icu_normalizer_data::impl_uts46_decomposition_supplement_v1_marker!(TestingProvider);
icu_normalizer_data::impl_uts46_decomposition_data_v2_marker!(TestingProvider);
};

type StackString = arraystring::ArrayString<arraystring::typenum::U32>;
Expand Down
6 changes: 6 additions & 0 deletions components/datetime/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ pub enum DateTimeFormatterLoadError {
Data(DataError),
}

impl From<DataError> for DateTimeFormatterLoadError {
fn from(error: DataError) -> Self {
Self::Data(error)
}
}

/// An error from mixing calendar types in a formatter.
#[derive(Display, Debug, Copy, Clone, PartialEq)]
#[displaydoc("DateTimeFormatter for {this_kind} calendar was given a {date_kind:?} calendar")]
Expand Down
35 changes: 34 additions & 1 deletion components/datetime/src/neo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::MismatchedCalendarError;
use core::fmt;
use core::marker::PhantomData;
use icu_calendar::any_calendar::IntoAnyCalendar;
use icu_calendar::{AnyCalendar, AnyCalendarPreferences};
use icu_calendar::{AnyCalendar, AnyCalendarKind, AnyCalendarPreferences};
use icu_decimal::FixedDecimalFormatterPreferences;
use icu_locale_core::preferences::extensions::unicode::keywords::{
CalendarAlgorithm, HourCycle, NumberingSystem,
Expand Down Expand Up @@ -765,6 +765,36 @@ impl<FSet: DateTimeMarkers> DateTimeFormatter<FSet> {
_calendar: PhantomData,
})
}

/// Returns the calendar system used in this formatter.
///
/// # Examples
///
/// ```
/// use icu::calendar::AnyCalendarKind;
/// use icu::calendar::Date;
/// use icu::datetime::fieldsets::YMD;
/// use icu::datetime::DateTimeFormatter;
/// use icu::locale::locale;
/// use writeable::assert_writeable_eq;
///
/// let formatter = DateTimeFormatter::try_new(
/// locale!("th").into(),
/// YMD::long(),
/// )
/// .unwrap();
///
/// assert_writeable_eq!(
/// formatter.format_any_calendar(&Date::try_new_iso(2024, 12, 16).unwrap()),
/// "16 ธันวาคม 2567"
/// );
///
/// assert_eq!(formatter.calendar_kind(), AnyCalendarKind::Buddhist);
/// assert_eq!(formatter.calendar_kind().as_bcp47_string(), "buddhist");
/// ```
pub fn calendar_kind(&self) -> AnyCalendarKind {
self.calendar.kind()
}
}

/// A formatter optimized for time and time zone formatting.
Expand Down Expand Up @@ -840,6 +870,9 @@ impl_display_with_writeable!(FormattedDateTime<'_>);

impl FormattedDateTime<'_> {
/// Gets the pattern used in this formatted value.
///
/// From the pattern, one can check the properties of the included components, such as
/// the hour cycle being used for formatting. See [`DateTimePattern`].
pub fn pattern(&self) -> DateTimePattern {
self.pattern.to_pattern()
}
Expand Down
28 changes: 28 additions & 0 deletions components/datetime/src/pattern/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@ size_test!(DateTimePattern, date_time_pattern_size, 32);
/// assert_eq!(actual_components_bag, expected_components_bag);
/// ```
///
/// Check the hour cycle of a resolved pattern:
///
/// ```
/// use icu::calendar::Time;
/// use icu::datetime::fields::components;
/// use icu::datetime::fieldsets::T;
/// use icu::datetime::pattern::DateTimePattern;
/// use icu::datetime::TimeFormatter;
/// use icu::locale::locale;
/// use icu::locale::preferences::extensions::unicode::keywords::HourCycle;
/// use writeable::assert_writeable_eq;
///
/// let pattern = TimeFormatter::try_new(
/// locale!("es-MX").into(),
/// T::medium(),
/// )
/// .unwrap()
/// // The pattern can depend on the datetime being formatted.
/// .format(&Time::try_new(12, 0, 0, 0).unwrap())
/// .pattern();
///
/// assert_writeable_eq!(pattern, "hh:mm:ss a");
///
/// // Get the hour cycle from the resolved components:
/// let components = components::Bag::from(&pattern);
/// assert_eq!(components.hour_cycle, Some(HourCycle::H12));
/// ```
///
/// [`DateTimeFormatter`]: crate::DateTimeFormatter
/// [`FormattedDateTime::pattern`]: crate::FormattedDateTime::pattern
/// [`TypedDateTimeNames`]: crate::pattern::TypedDateTimeNames
Expand Down
80 changes: 58 additions & 22 deletions components/decimal/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

//! Lower-level types for decimal formatting.
use core::fmt::Write;

use crate::grouper;
use crate::options::*;
use crate::parts;
use crate::provider::*;
use fixed_decimal::Sign;
use fixed_decimal::SignedFixedDecimal;
use writeable::Part;
use writeable::PartsWrite;
use writeable::Writeable;

/// An intermediate structure returned by [`FixedDecimalFormatter`](crate::FixedDecimalFormatter).
Expand All @@ -23,43 +28,74 @@ pub struct FormattedFixedDecimal<'l> {

impl FormattedFixedDecimal<'_> {
/// Returns the affixes needed for the current sign, as (prefix, suffix)
fn get_affixes(&self) -> Option<(&str, &str)> {
fn get_affixes(&self) -> Option<(Part, (&str, &str))> {
match self.value.sign() {
Sign::None => None,
Sign::Negative => Some(self.symbols.minus_sign_affixes()),
Sign::Positive => Some(self.symbols.plus_sign_affixes()),
Sign::Negative => Some((parts::MINUS_SIGN, self.symbols.minus_sign_affixes())),
Sign::Positive => Some((parts::PLUS_SIGN, self.symbols.plus_sign_affixes())),
}
}
}

impl Writeable for FormattedFixedDecimal<'_> {
fn write_to<W>(&self, sink: &mut W) -> core::result::Result<(), core::fmt::Error>
fn write_to_parts<W>(&self, w: &mut W) -> core::result::Result<(), core::fmt::Error>
where
W: core::fmt::Write + ?Sized,
W: writeable::PartsWrite + ?Sized,
{
let affixes = self.get_affixes();
if let Some(affixes) = affixes {
sink.write_str(affixes.0)?;
if let Some((part, affixes)) = affixes {
w.with_part(part, |w| w.write_str(affixes.0))?;
}
let range = self.value.absolute.magnitude_range();
let upper_magnitude = *range.end();
for m in range.rev() {
if m == -1 {
sink.write_str(self.symbols.decimal_separator())?;
}
#[allow(clippy::indexing_slicing)] // digit_at in 0..=9
sink.write_char(self.digits.digits[self.value.digit_at(m) as usize])?;
if grouper::check(
upper_magnitude,
m,
self.options.grouping_strategy,
&self.symbols.grouping_sizes,
) {
sink.write_str(self.symbols.grouping_separator())?;
let mut range = range.rev();
let mut has_fraction = false;
w.with_part(parts::INTEGER, |w| {
loop {
let m = match range.next() {
Some(m) if m < 0 => {
has_fraction = true;
break Ok(());
}
Some(m) => m,
None => {
break Ok(());
}
};
#[allow(clippy::indexing_slicing)] // digit_at in 0..=9
w.write_char(self.digits.digits[self.value.digit_at(m) as usize])?;
if grouper::check(
upper_magnitude,
m,
self.options.grouping_strategy,
&self.symbols.grouping_sizes,
) {
w.with_part(parts::GROUP, |w| {
w.write_str(self.symbols.grouping_separator())
})?;
}
}
})?;
if has_fraction {
w.with_part(parts::DECIMAL, |w| {
w.write_str(self.symbols.decimal_separator())
})?;
w.with_part(parts::FRACTION, |w| {
let mut m = -1; // read in the previous loop
loop {
#[allow(clippy::indexing_slicing)] // digit_at in 0..=9
w.write_char(self.digits.digits[self.value.digit_at(m) as usize])?;
m = match range.next() {
Some(m) => m,
None => {
break Ok(());
}
};
}
})?;
}
if let Some(affixes) = affixes {
sink.write_str(affixes.1)?;
if let Some((part, affixes)) = affixes {
w.with_part(part, |w| w.write_str(affixes.1))?;
}
Ok(())
}
Expand Down
45 changes: 45 additions & 0 deletions components/decimal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ extern crate alloc;
mod format;
mod grouper;
pub mod options;
pub mod parts;
pub mod provider;
pub(crate) mod size_test_macro;

pub use format::FormattedFixedDecimal;

use alloc::string::String;
use fixed_decimal::SignedFixedDecimal;
use icu_locale_core::extensions::unicode::Value;
use icu_locale_core::locale;
use icu_locale_core::preferences::{
define_preferences, extensions::unicode::keywords::NumberingSystem,
Expand Down Expand Up @@ -214,4 +216,47 @@ impl FixedDecimalFormatter {
pub fn format_to_string(&self, value: &SignedFixedDecimal) -> String {
self.format(value).write_to_string().into_owned()
}

/// Gets the resolved numbering system identifier of this formatter.
///
/// # Examples
///
/// ```
/// use icu::decimal::FixedDecimalFormatter;
/// use icu::locale::locale;
///
/// let fmt_en = FixedDecimalFormatter::try_new(
/// locale!("en").into(),
/// Default::default()
/// )
/// .unwrap();
///
/// let fmt_bn = FixedDecimalFormatter::try_new(
/// locale!("bn").into(),
/// Default::default()
/// )
/// .unwrap();
///
/// let fmt_zh_nu = FixedDecimalFormatter::try_new(
/// locale!("zh-u-nu-hanidec").into(),
/// Default::default()
/// )
/// .unwrap();
///
/// assert_eq!(fmt_en.numbering_system(), "latn");
/// assert_eq!(fmt_bn.numbering_system(), "beng");
/// assert_eq!(fmt_zh_nu.numbering_system(), "hanidec");
/// ```
pub fn numbering_system(&self) -> Value {
match Value::try_from_str(self.symbols.get().numsys()) {
Ok(v) => v,
Err(e) => {
debug_assert!(
false,
"Problem converting numbering system ID to Value: {e}"
);
Value::new_empty()
}
}
}
}
Loading

0 comments on commit 7d0033e

Please sign in to comment.