Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add total_cmp helper functions to icu_locid types and DataLocale #4608

Merged
merged 7 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...wow that's a type

(
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 {
robertbastian marked this conversation as resolved.
Show resolved Hide resolved
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
Loading