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 data loading for chinese precomputed caches #4468

Merged
merged 20 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
40 changes: 26 additions & 14 deletions components/calendar/src/any_calendar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,9 @@ impl AnyCalendar {
pub const fn new(kind: AnyCalendarKind) -> Self {
match kind {
AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese::new()),
AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::new()),
AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
EthiopianEraStyle::AmeteMihret,
)),
Expand Down Expand Up @@ -613,9 +613,13 @@ impl AnyCalendar {
{
Ok(match kind {
AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese),
AnyCalendarKind::Chinese => {
AnyCalendar::Chinese(Chinese::try_new_with_any_provider(provider)?)
}
AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi),
AnyCalendarKind::Dangi => {
AnyCalendar::Dangi(Dangi::try_new_with_any_provider(provider)?)
}
AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
EthiopianEraStyle::AmeteMihret,
)),
Expand Down Expand Up @@ -654,9 +658,13 @@ impl AnyCalendar {
{
Ok(match kind {
AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese),
AnyCalendarKind::Chinese => {
AnyCalendar::Chinese(Chinese::try_new_with_buffer_provider(provider)?)
}
AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi),
AnyCalendarKind::Dangi => {
AnyCalendar::Dangi(Dangi::try_new_with_buffer_provider(provider)?)
}
AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
EthiopianEraStyle::AmeteMihret,
)),
Expand Down Expand Up @@ -689,13 +697,15 @@ impl AnyCalendar {
where
P: DataProvider<crate::provider::JapaneseErasV1Marker>
+ DataProvider<crate::provider::JapaneseExtendedErasV1Marker>
+ DataProvider<crate::provider::ChineseCacheV1Marker>
+ DataProvider<crate::provider::DangiCacheV1Marker>
+ ?Sized,
{
Ok(match kind {
AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese),
AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese::try_new_unstable(provider)?),
AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi),
AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::try_new_unstable(provider)?),
AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
EthiopianEraStyle::AmeteMihret,
)),
Expand Down Expand Up @@ -759,6 +769,8 @@ impl AnyCalendar {
where
P: DataProvider<crate::provider::JapaneseErasV1Marker>
+ DataProvider<crate::provider::JapaneseExtendedErasV1Marker>
+ DataProvider<crate::provider::ChineseCacheV1Marker>
+ DataProvider<crate::provider::DangiCacheV1Marker>
+ ?Sized,
{
let kind = AnyCalendarKind::from_data_locale_with_fallback(locale);
Expand Down Expand Up @@ -1026,9 +1038,9 @@ impl AnyCalendarKind {
fn debug_name(self) -> &'static str {
match self {
AnyCalendarKind::Buddhist => Buddhist.debug_name(),
AnyCalendarKind::Chinese => Chinese.debug_name(),
AnyCalendarKind::Chinese => Chinese::DEBUG_NAME,
AnyCalendarKind::Coptic => Coptic.debug_name(),
AnyCalendarKind::Dangi => Dangi.debug_name(),
AnyCalendarKind::Dangi => Dangi::DEBUG_NAME,
AnyCalendarKind::Ethiopian => Ethiopian(false).debug_name(),
AnyCalendarKind::EthiopianAmeteAlem => Ethiopian(true).debug_name(),
AnyCalendarKind::Gregorian => Gregorian.debug_name(),
Expand Down Expand Up @@ -1131,10 +1143,10 @@ impl IntoAnyCalendar for Buddhist {

impl IntoAnyCalendar for Chinese {
fn to_any(self) -> AnyCalendar {
AnyCalendar::Chinese(Chinese)
AnyCalendar::Chinese(self)
}
fn to_any_cloned(&self) -> AnyCalendar {
AnyCalendar::Chinese(Chinese)
AnyCalendar::Chinese(self.clone())
}
fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
AnyDateInner::Chinese(*d)
Expand All @@ -1155,10 +1167,10 @@ impl IntoAnyCalendar for Coptic {

impl IntoAnyCalendar for Dangi {
fn to_any(self) -> AnyCalendar {
AnyCalendar::Dangi(Dangi)
AnyCalendar::Dangi(self)
}
fn to_any_cloned(&self) -> AnyCalendar {
AnyCalendar::Dangi(Dangi)
AnyCalendar::Dangi(self.clone())
}
fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
AnyDateInner::Dangi(*d)
Expand Down
74 changes: 65 additions & 9 deletions components/calendar/src/chinese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ use crate::chinese_based::{
ChineseBasedPrecomputedData, ChineseBasedWithDataLoading, ChineseBasedYearInfo,
};
use crate::iso::Iso;
use crate::provider::chinese_based::ChineseCacheV1Marker;
use crate::types::{Era, FormattableYear};
use crate::AsCalendar;
use crate::{types, Calendar, CalendarError, Date, DateDuration, DateDurationUnit, DateTime};
use core::cmp::Ordering;
use core::num::NonZeroU8;
use icu_provider::prelude::*;
use tinystr::tinystr;

/// The Chinese Calendar
Expand Down Expand Up @@ -101,9 +104,10 @@ use tinystr::tinystr;
///
/// This calendar is currently in a preview state: formatting for this calendar is not
/// going to be perfect.
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive] // we'll be adding precompiled data to this
pub struct Chinese;
#[derive(Clone, Debug, Default)]
pub struct Chinese {
data: Option<DataPayload<ChineseCacheV1Marker>>,
}

/// The inner date type used for representing [`Date`]s of [`Chinese`]. See [`Date`] and [`Chinese`] for more details.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
Expand All @@ -119,14 +123,66 @@ impl Clone for ChineseDateInner {
}
}

// These impls just make custom derives on types containing C
// work. They're basically no-ops
impl PartialEq for Chinese {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl Eq for Chinese {}
impl PartialOrd for Chinese {
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
Some(Ordering::Equal)
}
}

impl Ord for Chinese {
fn cmp(&self, _: &Self) -> Ordering {
Ordering::Equal
}
}

impl Chinese {
/// Construct a new [`Chinese`] without any precomputed calendrical calculations.
/// Creates a new [`Chinese`] using only modern eras (post-meiji) from compiled data.
Manishearth marked this conversation as resolved.
Show resolved Hide resolved
///
/// This is the only mode currently possible, but once precomputing is available (#3933)
/// there will be additional constructors that load from data providers.
/// ✨ *Enabled with the `compiled_data` Cargo feature.*
///
/// [📚 Help choosing a constructor](icu_provider::constructors)
#[cfg(feature = "compiled_data")]
pub const fn new() -> Self {
Self {
data: Some(DataPayload::from_static_ref(
crate::provider::Baked::SINGLETON_CALENDAR_CHINESECACHE_V1,
)),
}
}

icu_provider::gen_any_buffer_data_constructors!(locale: skip, options: skip, error: CalendarError,
#[cfg(skip)]
functions: [
new,
try_new_with_any_provider,
try_new_with_buffer_provider,
try_new_unstable,
Self,
]);

#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new)]
pub fn try_new_unstable<D: DataProvider<ChineseCacheV1Marker> + ?Sized>(
provider: &D,
) -> Result<Self, CalendarError> {
Ok(Self {
data: Some(provider.load(Default::default())?.take_payload()?),
})
}

/// Construct a new [`Chinese`] without any precomputed calendrical calculations.
pub fn new_always_calculating() -> Self {
Chinese
Chinese { data: None }
}

pub(crate) const DEBUG_NAME: &'static str = "Chinese";
}

impl Calendar for Chinese {
Expand Down Expand Up @@ -211,7 +267,7 @@ impl Calendar for Chinese {

/// Obtain a name for the calendar for debug printing
fn debug_name(&self) -> &'static str {
"Chinese"
Self::DEBUG_NAME
}

/// The calendar-specific year represented by `date`
Expand Down Expand Up @@ -347,7 +403,7 @@ type ChineseCB = calendrical_calculations::chinese_based::Chinese;
impl ChineseBasedWithDataLoading for Chinese {
type CB = ChineseCB;
fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData<Self::CB> {
Default::default()
ChineseBasedPrecomputedData::new(self.data.as_ref().map(|d| d.get()))
}
}

Expand Down
9 changes: 8 additions & 1 deletion components/calendar/src/chinese_based.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{

use calendrical_calculations::chinese_based::{self, ChineseBased, YearBounds};
use calendrical_calculations::rata_die::RataDie;
use core::marker::PhantomData;
use core::num::NonZeroU8;
use tinystr::tinystr;

Expand Down Expand Up @@ -58,7 +59,7 @@ impl<C: CalendarArithmetic> Clone for ChineseBasedDateInner<C> {
#[derive(Default)]
pub(crate) struct ChineseBasedPrecomputedData<'a, CB: ChineseBased> {
data: Option<&'a ChineseBasedCacheV1<'a>>,
_cb: CB, // this is zero-sized
_cb: PhantomData<CB>,
}

/// Compute ChineseBasedYearInfo for a given extended year
Expand Down Expand Up @@ -136,6 +137,12 @@ impl<'b, CB: ChineseBased> PrecomputedDataSource<ChineseBasedYearInfo>
}

impl<'b, CB: ChineseBased> ChineseBasedPrecomputedData<'b, CB> {
pub(crate) fn new(data: Option<&'b ChineseBasedCacheV1<'b>>) -> Self {
Self {
data,
_cb: PhantomData,
}
}
/// Given an ISO date (in both ArithmeticDate and R.D. format), returns the ChineseBasedYearInfo and extended year for that date, loading
/// from cache or computing.
fn load_or_compute_info_for_iso(
Expand Down
73 changes: 65 additions & 8 deletions components/calendar/src/dangi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@ use crate::chinese_based::{
chinese_based_ordinal_lunar_month_from_code, ChineseBasedPrecomputedData,
ChineseBasedWithDataLoading, ChineseBasedYearInfo,
};
use crate::provider::chinese_based::DangiCacheV1Marker;
use crate::AsCalendar;
use crate::{
chinese_based::ChineseBasedDateInner,
types::{self, Era, FormattableYear},
AnyCalendarKind, Calendar, CalendarError, Date, DateTime, Iso,
};
use core::cmp::Ordering;
use core::num::NonZeroU8;
use icu_provider::prelude::*;
use tinystr::tinystr;

/// The Dangi Calendar
Expand Down Expand Up @@ -93,9 +96,11 @@ use tinystr::tinystr;
///
/// This calendar is a lunisolar calendar. It supports regular month codes `"M01" - "M12"` as well
/// as leap month codes `"M01L" - "M12L"`.
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Debug, Default)]
#[non_exhaustive] // we'll be adding precompiled data to this
pub struct Dangi;
pub struct Dangi {
data: Option<DataPayload<DangiCacheV1Marker>>,
}

/// The inner date type used for representing [`Date`]s of [`Dangi`]. See [`Date`] and [`Dangi`] for more detail.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
Expand All @@ -111,14 +116,66 @@ impl Clone for DangiDateInner {
}
}

// These impls just make custom derives on types containing C
// work. They're basically no-ops
impl PartialEq for Dangi {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl Eq for Dangi {}
impl PartialOrd for Dangi {
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
Some(Ordering::Equal)
}
}

impl Ord for Dangi {
fn cmp(&self, _: &Self) -> Ordering {
Ordering::Equal
}
}

impl Dangi {
/// Construct a new [`Dangi`] without any precomputed calendrical calculations.
/// Creates a new [`Dangi`] using only modern eras (post-meiji) from compiled data.
Manishearth marked this conversation as resolved.
Show resolved Hide resolved
///
/// This is the only mode currently possible, but once precomputing is available (#3933)
/// there will be additional constructors that load from data providers.
/// ✨ *Enabled with the `compiled_data` Cargo feature.*
///
/// [📚 Help choosing a constructor](icu_provider::constructors)
#[cfg(feature = "compiled_data")]
pub const fn new() -> Self {
Self {
data: Some(DataPayload::from_static_ref(
crate::provider::Baked::SINGLETON_CALENDAR_DANGICACHE_V1,
)),
}
}

icu_provider::gen_any_buffer_data_constructors!(locale: skip, options: skip, error: CalendarError,
#[cfg(skip)]
functions: [
new,
try_new_with_any_provider,
try_new_with_buffer_provider,
try_new_unstable,
Self,
]);

#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new)]
pub fn try_new_unstable<D: DataProvider<DangiCacheV1Marker> + ?Sized>(
provider: &D,
) -> Result<Self, CalendarError> {
Ok(Self {
data: Some(provider.load(Default::default())?.take_payload()?),
})
}

/// Construct a new [`Dangi`] without any precomputed calendrical calculations.
pub fn new_always_calculating() -> Self {
Dangi
Dangi { data: None }
}

pub(crate) const DEBUG_NAME: &'static str = "Dangi";
}

impl Calendar for Dangi {
Expand Down Expand Up @@ -194,7 +251,7 @@ impl Calendar for Dangi {
}

fn debug_name(&self) -> &'static str {
"Dangi"
Self::DEBUG_NAME
}

fn year(&self, date: &Self::DateInner) -> crate::types::FormattableYear {
Expand Down Expand Up @@ -322,7 +379,7 @@ type DangiCB = calendrical_calculations::chinese_based::Dangi;
impl ChineseBasedWithDataLoading for Dangi {
type CB = DangiCB;
fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData<Self::CB> {
Default::default()
ChineseBasedPrecomputedData::new(self.data.as_ref().map(|d| d.get()))
}
}

Expand Down
6 changes: 5 additions & 1 deletion components/datetime/src/any/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use crate::{input::DateInput, DateTimeError, FormattedDateTime};
use alloc::string::String;
use icu_calendar::any_calendar::{AnyCalendar, AnyCalendarKind};
use icu_calendar::provider::{
JapaneseErasV1Marker, JapaneseExtendedErasV1Marker, WeekDataV1Marker,
ChineseCacheV1Marker, DangiCacheV1Marker, JapaneseErasV1Marker, JapaneseExtendedErasV1Marker,
WeekDataV1Marker,
};
use icu_calendar::Date;
use icu_decimal::provider::DecimalSymbolsV1Marker;
Expand Down Expand Up @@ -165,10 +166,13 @@ impl DateFormatter {
+ DataProvider<DecimalSymbolsV1Marker>
+ DataProvider<BuddhistDateLengthsV1Marker>
+ DataProvider<BuddhistDateSymbolsV1Marker>
+ DataProvider<ChineseCacheV1Marker>
+ DataProvider<ChineseDateLengthsV1Marker>
+ DataProvider<ChineseDateSymbolsV1Marker>
+ DataProvider<CopticDateLengthsV1Marker>
+ DataProvider<CopticDateSymbolsV1Marker>
+ DataProvider<ChineseCacheV1Marker>
+ DataProvider<DangiCacheV1Marker>
+ DataProvider<DangiDateLengthsV1Marker>
+ DataProvider<DangiDateSymbolsV1Marker>
+ DataProvider<EthiopianDateLengthsV1Marker>
Expand Down
Loading