Skip to content

Commit

Permalink
Add total_cmp helper functions to icu_locid types and DataLocale (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sffc committed Mar 6, 2024
1 parent 49ff029 commit f5ee301
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- New `DateTime::local_unix_epoch()` convenience constructor (https://github.com/unicode-org/icu4x/pull/4479)
- `icu_datetime`
- `FormattedDateTime` and `FormattedZonedDateTime` now implement `Clone` and `Copy` (https://github.com/unicode-org/icu4x/pull/4476)
- `icu_locid`
- Added `total_cmp` functions to `Locale` and other types to make them easier to use in `BTreeSet` (https://github.com/unicode-org/icu4x/pull/4608)
- `icu_properties`
- Add `Aran` script code (https://github.com/unicode-org/icu4x/pull/4426)
- Mark additional constructors as `const` (https://github.com/unicode-org/icu4x/pull/4584, https://github.com/unicode-org/icu4x/pull/4574)
Expand Down
38 changes: 38 additions & 0 deletions components/locid/src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub mod private;
pub mod transform;
pub mod unicode;

use core::cmp::Ordering;

use other::Other;
use private::Private;
use transform::Transform;
Expand All @@ -58,6 +60,7 @@ use alloc::vec::Vec;

use crate::parser::ParserError;
use crate::parser::SubtagIterator;
use crate::subtags;

/// Defines the type of extension.
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)]
Expand Down Expand Up @@ -164,6 +167,41 @@ impl Extensions {
&& self.other.is_empty()
}

#[allow(clippy::type_complexity)]
pub(crate) fn as_tuple(
&self,
) -> (
(&unicode::Attributes, &unicode::Keywords),
(
Option<(
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
&subtags::Variants,
)>,
&transform::Fields,
),
&private::Private,
&[other::Other],
) {
(
self.unicode.as_tuple(),
self.transform.as_tuple(),
&self.private,
&self.other,
)
}

/// Returns an ordering suitable for use in [`BTreeSet`].
///
/// The ordering may or may not be equivalent to string ordering, and it
/// may or may not be stable across ICU4X releases.
///
/// [`BTreeSet`]: alloc::collections::BTreeSet
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.as_tuple().cmp(&other.as_tuple())
}

/// Retains the specified extension types, clearing all others.
///
/// # Examples
Expand Down
29 changes: 28 additions & 1 deletion components/locid/src/extensions/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ mod fields;
mod key;
mod value;

use core::cmp::Ordering;

pub use fields::Fields;
#[doc(inline)]
pub use key::{key, Key};
Expand All @@ -42,7 +44,7 @@ pub use value::Value;
use crate::parser::SubtagIterator;
use crate::parser::{parse_language_identifier_from_iter, ParserError, ParserMode};
use crate::shortvec::ShortBoxSlice;
use crate::subtags::Language;
use crate::subtags::{self, Language};
use crate::LanguageIdentifier;
use litemap::LiteMap;

Expand Down Expand Up @@ -131,6 +133,31 @@ impl Transform {
self.fields.clear();
}

#[allow(clippy::type_complexity)]
pub(crate) fn as_tuple(
&self,
) -> (
Option<(
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
&subtags::Variants,
)>,
&Fields,
) {
(self.lang.as_ref().map(|l| l.as_tuple()), &self.fields)
}

/// Returns an ordering suitable for use in [`BTreeSet`].
///
/// The ordering may or may not be equivalent to string ordering, and it
/// may or may not be stable across ICU4X releases.
///
/// [`BTreeSet`]: alloc::collections::BTreeSet
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.as_tuple().cmp(&other.as_tuple())
}

pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result<Self, ParserError> {
let mut tlang = None;
let mut tfields = LiteMap::new();
Expand Down
16 changes: 16 additions & 0 deletions components/locid/src/extensions/unicode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ mod key;
mod keywords;
mod value;

use core::cmp::Ordering;

#[doc(inline)]
pub use attribute::{attribute, Attribute};
pub use attributes::Attributes;
Expand Down Expand Up @@ -134,6 +136,20 @@ impl Unicode {
self.attributes.clear();
}

pub(crate) fn as_tuple(&self) -> (&Attributes, &Keywords) {
(&self.attributes, &self.keywords)
}

/// Returns an ordering suitable for use in [`BTreeSet`].
///
/// The ordering may or may not be equivalent to string ordering, and it
/// may or may not be stable across ICU4X releases.
///
/// [`BTreeSet`]: alloc::collections::BTreeSet
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.as_tuple().cmp(&other.as_tuple())
}

pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result<Self, ParserError> {
let mut attributes = ShortBoxSlice::new();

Expand Down
21 changes: 21 additions & 0 deletions components/locid/src/langid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,27 @@ impl LanguageIdentifier {
self.write_cmp_bytes(other)
}

pub(crate) fn as_tuple(
&self,
) -> (
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
&subtags::Variants,
) {
(self.language, self.script, self.region, &self.variants)
}

/// Compare this [`LanguageIdentifier`] with another [`LanguageIdentifier`] field-by-field.
/// The result is a total ordering sufficient for use in a [`BTreeMap`].
///
/// Unlike [`Self::strict_cmp`], this function's ordering may not equal string ordering.
///
/// [`BTreeMap`]: alloc::collections::BTreeMap
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.as_tuple().cmp(&other.as_tuple())
}

/// Compare this [`LanguageIdentifier`] with an iterator of BCP-47 subtags.
///
/// This function has the same equality semantics as [`LanguageIdentifier::strict_cmp`]. It is intended as
Expand Down
41 changes: 41 additions & 0 deletions components/locid/src/locale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,47 @@ impl Locale {
self.write_cmp_bytes(other)
}

#[allow(clippy::type_complexity)]
pub(crate) fn as_tuple(
&self,
) -> (
(
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
&subtags::Variants,
),
(
(
&extensions::unicode::Attributes,
&extensions::unicode::Keywords,
),
(
Option<(
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
&subtags::Variants,
)>,
&extensions::transform::Fields,
),
&extensions::private::Private,
&[extensions::other::Other],
),
) {
(self.id.as_tuple(), self.extensions.as_tuple())
}

/// Returns an ordering suitable for use in [`BTreeSet`].
///
/// The ordering may or may not be equivalent to string ordering, and it
/// may or may not be stable across ICU4X releases.
///
/// [`BTreeSet`]: alloc::collections::BTreeSet
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.as_tuple().cmp(&other.as_tuple())
}

/// Compare this [`Locale`] with an iterator of BCP-47 subtags.
///
/// This function has the same equality semantics as [`Locale::strict_cmp`]. It is intended as
Expand Down
2 changes: 2 additions & 0 deletions ffi/capi/bindings/c/ICU4XLocale.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ffi/capi/bindings/cpp/ICU4XLocale.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions ffi/capi/bindings/cpp/ICU4XLocale.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions ffi/capi/bindings/dart/Locale.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions ffi/capi/bindings/js/ICU4XLocale.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions ffi/capi/bindings/js/ICU4XLocale.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ffi/capi/src/locale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ pub mod ffi {
self.0.strict_cmp(other).into()
}

#[diplomat::rust_link(icu::locid::Locale::total_cmp, FnInStruct)]
pub fn total_cmp(&self, other: &Self) -> ICU4XOrdering {
self.0.total_cmp(&other.0).into()
}

/// Deprecated
///
/// Use `create_from_string("en").
Expand Down
34 changes: 33 additions & 1 deletion provider/core/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,24 @@ impl DataLocale {
self == <&DataLocale>::default()
}

/// Returns an ordering suitable for use in [`BTreeSet`].
///
/// The ordering may or may not be equivalent to string ordering, and it
/// may or may not be stable across ICU4X releases.
///
/// [`BTreeSet`]: alloc::collections::BTreeSet
pub fn total_cmp(&self, other: &Self) -> Ordering {
self.langid
.total_cmp(&other.langid)
.then_with(|| self.keywords.cmp(&other.keywords))
.then_with(|| {
#[cfg(feature = "experimental")]
return self.aux.cmp(&other.aux);
#[cfg(not(feature = "experimental"))]
return Ordering::Equal;
})
}

/// Returns whether this [`DataLocale`] is `und` in the locale and extensions portion.
///
/// This ignores auxiliary keys.
Expand Down Expand Up @@ -752,7 +770,7 @@ impl DataLocale {
/// ```
///
/// [`Keywords`]: unicode_ext::Keywords
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
#[derive(Debug, PartialEq, Clone, Eq, Hash, PartialOrd, Ord)]
#[cfg(feature = "experimental")]
pub struct AuxiliaryKeys {
value: AuxiliaryKeysInner,
Expand Down Expand Up @@ -790,6 +808,20 @@ impl PartialEq for AuxiliaryKeysInner {
#[cfg(feature = "experimental")]
impl Eq for AuxiliaryKeysInner {}

#[cfg(feature = "experimental")]
impl PartialOrd for AuxiliaryKeysInner {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

#[cfg(feature = "experimental")]
impl Ord for AuxiliaryKeysInner {
fn cmp(&self, other: &Self) -> Ordering {
self.deref().cmp(other.deref())
}
}

#[cfg(feature = "experimental")]
impl Debug for AuxiliaryKeysInner {
#[inline]
Expand Down

0 comments on commit f5ee301

Please sign in to comment.