Skip to content

Commit 4373b5e

Browse files
committed
Revert "revert controversial any_calendar refactorings"
This reverts commit ed48da7.
1 parent 0a2a4cd commit 4373b5e

File tree

1 file changed

+136
-176
lines changed

1 file changed

+136
-176
lines changed

components/calendar/src/any_calendar.rs

Lines changed: 136 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -149,64 +149,103 @@ pub enum AnyDateInner {
149149
Roc(<Roc as Calendar>::DateInner),
150150
}
151151

152-
macro_rules! match_cal_and_date {
153-
(match ($cal:ident, $date:ident): ($cal_matched:ident, $date_matched:ident) => $e:expr) => {
154-
match ($cal, $date) {
155-
(&Self::Buddhist(ref $cal_matched), &AnyDateInner::Buddhist(ref $date_matched)) => $e,
156-
(&Self::Chinese(ref $cal_matched), &AnyDateInner::Chinese(ref $date_matched)) => $e,
157-
(&Self::Coptic(ref $cal_matched), &AnyDateInner::Coptic(ref $date_matched)) => $e,
158-
(&Self::Dangi(ref $cal_matched), &AnyDateInner::Dangi(ref $date_matched)) => $e,
159-
(&Self::Ethiopian(ref $cal_matched), &AnyDateInner::Ethiopian(ref $date_matched)) => $e,
160-
(&Self::Gregorian(ref $cal_matched), &AnyDateInner::Gregorian(ref $date_matched)) => $e,
161-
(&Self::Hebrew(ref $cal_matched), &AnyDateInner::Hebrew(ref $date_matched)) => $e,
162-
(&Self::Indian(ref $cal_matched), &AnyDateInner::Indian(ref $date_matched)) => $e,
163-
(
164-
&Self::HijriTabular(ref $cal_matched),
165-
&AnyDateInner::HijriTabular(ref $date_matched, sighting),
166-
) if $cal_matched.0 == sighting => $e,
167-
(
168-
&Self::HijriSimulated(ref $cal_matched),
169-
&AnyDateInner::HijriSimulated(ref $date_matched),
170-
) => $e,
171-
(
172-
&Self::HijriUmmAlQura(ref $cal_matched),
173-
&AnyDateInner::HijriUmmAlQura(ref $date_matched),
174-
) => $e,
175-
(&Self::Iso(ref $cal_matched), &AnyDateInner::Iso(ref $date_matched)) => $e,
176-
(&Self::Japanese(ref $cal_matched), &AnyDateInner::Japanese(ref $date_matched)) => $e,
177-
(
178-
&Self::JapaneseExtended(ref $cal_matched),
179-
&AnyDateInner::JapaneseExtended(ref $date_matched),
180-
) => $e,
181-
(&Self::Persian(ref $cal_matched), &AnyDateInner::Persian(ref $date_matched)) => $e,
182-
(&Self::Roc(ref $cal_matched), &AnyDateInner::Roc(ref $date_matched)) => $e,
183-
// This is only reached from misuse of from_raw, a semi-internal api
184-
_ => panic!("AnyCalendar with mismatched date type"),
152+
/// Generalized macro that generates a match statement over all AnyCalendar variants.
153+
///
154+
/// Parameters:
155+
///
156+
/// 1. `$cal`: The variables to be matched over: for example, `cal`, `(cal, date)`, or `(cal, date1, date2)`.
157+
/// 2. `$pattern`: The name of a macro that generates a pattern for the match statement. It is passed as arguments:
158+
/// - `$cal`
159+
/// - An ident to be used for matching the AnyCalendar, `c`.
160+
/// - A list of idents to be used for matching AnyDateInners and the Hijri tabular algorithm
161+
/// 3. `$expr`: The name of a macro that generates an expression for the match statement. It is passed the same
162+
/// arguments as `$pattern`, except without the Hijri tabular algorithm, since it is contained within `c`.
163+
/// 4. `[$d1, $alg1, $d2, $alg2, ...]`: A list of identifiers that are passed into `$pattern` and `$expr`.
164+
/// There should generally be 2 identifiers per date being matched. Can be omitted if no dates are being matched.
165+
/// 5. `$exhaustive_expr`: The expression for the `_` pattern. Can be omitted if no dates are being matched.
166+
#[rustfmt::skip]
167+
macro_rules! match_cal_general {
168+
($cal:expr, $pattern:ident, $expr:ident $(, [$($d:ident, $alg:ident),+], $exhaustive_expr:expr)?) => {
169+
match $cal {
170+
$pattern!(Buddhist, c $(,[$($d),*])?) => $expr!(Buddhist, c $(,[$($d),*])?),
171+
$pattern!(Chinese, c $(,[$($d),*])?) => $expr!(Chinese, c $(,[$($d),*])?),
172+
$pattern!(Coptic, c $(,[$($d),*])?) => $expr!(Coptic, c $(,[$($d),*])?),
173+
$pattern!(Dangi, c $(,[$($d),*])?) => $expr!(Dangi, c $(,[$($d),*])?),
174+
$pattern!(Ethiopian, c $(,[$($d),*])?) => $expr!(Ethiopian, c $(,[$($d),*])?),
175+
$pattern!(Gregorian, c $(,[$($d),*])?) => $expr!(Gregorian, c $(,[$($d),*])?),
176+
$pattern!(Hebrew, c $(,[$($d),*])?) => $expr!(Hebrew, c $(,[$($d),*])?),
177+
$pattern!(Indian, c $(,[$($d),*])?) => $expr!(Indian, c $(,[$($d),*])?),
178+
$pattern!(HijriSimulated, c $(,[$($d),*])?) => $expr!(HijriSimulated, c $(,[$($d),*])?),
179+
$pattern!(HijriUmmAlQura, c $(,[$($d),*])?) => $expr!(HijriUmmAlQura, c $(,[$($d),*])?),
180+
$pattern!(Iso, c $(,[$($d),*])?) => $expr!(Iso, c $(,[$($d),*])?),
181+
$pattern!(Japanese, c $(,[$($d),*])?) => $expr!(Japanese, c $(,[$($d),*])?),
182+
$pattern!(JapaneseExtended, c $(,[$($d),*])?) => $expr!(JapaneseExtended, c $(,[$($d),*])?),
183+
$pattern!(Persian, c $(,[$($d),*])?) => $expr!(Persian, c $(,[$($d),*])?),
184+
$pattern!(Roc, c $(,[$($d),*])?) => $expr!(Roc, c $(,[$($d),*])?),
185+
// HijriTabular is special because the DateInner has an extra field
186+
$pattern!(HijriTabular, c $(,[$($d, $alg),*])?) $(if $(c.0 == $alg)&&*)? => $expr!(HijriTabular, c $(,[$($d),*])?),
187+
// The exhaustive match is required when matching against DateInner
188+
$(_ => $exhaustive_expr)?
185189
}
186190
};
187191
}
188192

193+
/// Macro that generates a pattern match for a calendar only.
194+
macro_rules! pattern_cal {
195+
($cal:ident, $c:ident) => {
196+
&Self::$cal(ref $c)
197+
};
198+
}
199+
200+
/// Macro that generates a pattern match for a calendar and date.
201+
macro_rules! pattern_cal_date {
202+
(HijriTabular, $c:ident, [$d:ident, $alg:ident]) => {
203+
(&Self::HijriTabular(ref $c), &AnyDateInner::HijriTabular(ref $d, $alg))
204+
};
205+
($cal:ident, $c:ident, [$d:ident]) => {
206+
(&Self::$cal(ref $c), &AnyDateInner::$cal(ref $d))
207+
};
208+
}
209+
210+
/// Macro that generates a pattern match for a calendar and two dates.
211+
macro_rules! pattern_cal_date_date {
212+
(HijriTabular, $c:ident, [$d1:ident, $alg1:ident, $d2:ident, $alg2:ident]) => {
213+
(&Self::HijriTabular(ref $c), &AnyDateInner::HijriTabular(ref $d1, $alg1), &AnyDateInner::HijriTabular(ref $d2, $alg2))
214+
};
215+
($cal:ident, $c:ident, [$d1:ident, $d2:ident]) => {
216+
(&Self::$cal(ref $c), &AnyDateInner::$cal(ref $d1), &AnyDateInner::$cal(ref $d2))
217+
};
218+
}
219+
220+
/// Convenience macro that invokes [`match_cal_general`] with common arguments for
221+
/// matching the calendar only.
189222
macro_rules! match_cal {
190-
(match $cal:ident: ($cal_matched:ident) => $e:expr) => {
191-
match $cal {
192-
&Self::Buddhist(ref $cal_matched) => AnyDateInner::Buddhist($e),
193-
&Self::Chinese(ref $cal_matched) => AnyDateInner::Chinese($e),
194-
&Self::Coptic(ref $cal_matched) => AnyDateInner::Coptic($e),
195-
&Self::Dangi(ref $cal_matched) => AnyDateInner::Dangi($e),
196-
&Self::Ethiopian(ref $cal_matched) => AnyDateInner::Ethiopian($e),
197-
&Self::Gregorian(ref $cal_matched) => AnyDateInner::Gregorian($e),
198-
&Self::Hebrew(ref $cal_matched) => AnyDateInner::Hebrew($e),
199-
&Self::Indian(ref $cal_matched) => AnyDateInner::Indian($e),
200-
&Self::HijriSimulated(ref $cal_matched) => AnyDateInner::HijriSimulated($e),
201-
&Self::HijriTabular(ref $cal_matched) => AnyDateInner::HijriTabular($e, $cal_matched.0),
202-
&Self::HijriUmmAlQura(ref $cal_matched) => AnyDateInner::HijriUmmAlQura($e),
203-
&Self::Iso(ref $cal_matched) => AnyDateInner::Iso($e),
204-
&Self::Japanese(ref $cal_matched) => AnyDateInner::Japanese($e),
205-
&Self::JapaneseExtended(ref $cal_matched) => AnyDateInner::JapaneseExtended($e),
206-
&Self::Persian(ref $cal_matched) => AnyDateInner::Persian($e),
207-
&Self::Roc(ref $cal_matched) => AnyDateInner::Roc($e),
223+
($cal:expr, c.$($call:tt)+) => {{
224+
macro_rules! helper {
225+
(HijriTabular, $c:ident) => {
226+
AnyDateInner::HijriTabular($c.$($call)+, $c.0)
227+
};
228+
($cal_inner:ident, $c:ident) => {
229+
AnyDateInner::$cal_inner($c.$($call)+)
230+
};
208231
}
209-
};
232+
match_cal_general!($cal, pattern_cal, helper)
233+
}};
234+
}
235+
236+
/// Convenience macro that invokes [`match_cal_general`] with common arguments for
237+
/// matching the calendar and one date.
238+
macro_rules! match_cal_and_date {
239+
($cal:expr, c.$f:tt(d $($extra1:tt)*) $($extra2:tt)*) => {{
240+
macro_rules! helper {
241+
($cal_inner:ident, $c:ident, [$d:ident]) => {
242+
$c.$f($d $($extra1)*) $($extra2)*
243+
};
244+
}
245+
match_cal_general!($cal, pattern_cal_date, helper, [d, blah], {
246+
unreachable!("AnyCalendar with mismatched date type")
247+
})
248+
}};
210249
}
211250

212251
/// Error returned when comparing two [`Date`]s with [`AnyCalendar`].
@@ -254,35 +293,35 @@ impl Calendar for AnyCalendar {
254293
fields: DateFields,
255294
options: DateFromFieldsOptions,
256295
) -> Result<Self::DateInner, DateError> {
257-
Ok(match_cal!(match self: (c) => c.from_fields(fields, options)?))
296+
Ok(match_cal!(self, c.from_fields(fields, options)?))
258297
}
259298

260299
fn from_iso(&self, iso: IsoDateInner) -> AnyDateInner {
261-
match_cal!(match self: (c) => c.from_iso(iso))
300+
match_cal!(self, c.from_iso(iso))
262301
}
263302

264303
fn from_rata_die(&self, rd: calendrical_calculations::rata_die::RataDie) -> Self::DateInner {
265-
match_cal!(match self: (c) => c.from_rata_die(rd))
304+
match_cal!(self, c.from_rata_die(rd))
266305
}
267306

268307
fn to_rata_die(&self, date: &Self::DateInner) -> calendrical_calculations::rata_die::RataDie {
269-
match_cal_and_date!(match (self, date): (c, d) => c.to_rata_die(d))
308+
match_cal_and_date!((self, date), c.to_rata_die(d))
270309
}
271310

272311
fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner {
273-
match_cal_and_date!(match (self, date): (c, d) => c.to_iso(d))
312+
match_cal_and_date!((self, date), c.to_iso(d))
274313
}
275314

276315
fn months_in_year(&self, date: &Self::DateInner) -> u8 {
277-
match_cal_and_date!(match (self, date): (c, d) => c.months_in_year(d))
316+
match_cal_and_date!((self, date), c.months_in_year(d))
278317
}
279318

280319
fn days_in_year(&self, date: &Self::DateInner) -> u16 {
281-
match_cal_and_date!(match (self, date): (c, d) => c.days_in_year(d))
320+
match_cal_and_date!((self, date), c.days_in_year(d))
282321
}
283322

284323
fn days_in_month(&self, date: &Self::DateInner) -> u8 {
285-
match_cal_and_date!(match (self, date): (c, d) => c.days_in_month(d))
324+
match_cal_and_date!((self, date), c.days_in_month(d))
286325
}
287326

288327
fn add(
@@ -291,57 +330,24 @@ impl Calendar for AnyCalendar {
291330
duration: types::DateDuration,
292331
options: DateAddOptions,
293332
) -> Result<Self::DateInner, DateError> {
294-
let mut date = *date;
295-
match (self, &mut date) {
296-
(Self::Buddhist(c), AnyDateInner::Buddhist(ref mut d)) => {
297-
*d = c.add(d, duration, options)?
298-
}
299-
(Self::Chinese(c), AnyDateInner::Chinese(ref mut d)) => {
300-
*d = c.add(d, duration, options)?
301-
}
302-
(Self::Coptic(c), AnyDateInner::Coptic(ref mut d)) => {
303-
*d = c.add(d, duration, options)?
304-
}
305-
(Self::Dangi(c), AnyDateInner::Dangi(ref mut d)) => *d = c.add(d, duration, options)?,
306-
(Self::Ethiopian(c), AnyDateInner::Ethiopian(ref mut d)) => {
307-
*d = c.add(d, duration, options)?
308-
}
309-
(Self::Gregorian(c), AnyDateInner::Gregorian(ref mut d)) => {
310-
*d = c.add(d, duration, options)?
311-
}
312-
(Self::Hebrew(c), AnyDateInner::Hebrew(ref mut d)) => {
313-
*d = c.add(d, duration, options)?
314-
}
315-
(Self::Indian(c), AnyDateInner::Indian(ref mut d)) => {
316-
*d = c.add(d, duration, options)?
317-
}
318-
(Self::HijriTabular(c), AnyDateInner::HijriTabular(ref mut d, sighting))
319-
if c.0 == *sighting =>
320-
{
321-
*d = c.add(d, duration, options)?
322-
}
323-
(Self::HijriSimulated(c), AnyDateInner::HijriSimulated(ref mut d)) => {
324-
*d = c.add(d, duration, options)?
325-
}
326-
(Self::HijriUmmAlQura(c), AnyDateInner::HijriUmmAlQura(ref mut d)) => {
327-
*d = c.add(d, duration, options)?
328-
}
329-
(Self::Iso(c), AnyDateInner::Iso(ref mut d)) => *d = c.add(d, duration, options)?,
330-
(Self::Japanese(c), AnyDateInner::Japanese(ref mut d)) => {
331-
*d = c.add(d, duration, options)?
332-
}
333-
(Self::JapaneseExtended(c), AnyDateInner::JapaneseExtended(ref mut d)) => {
334-
*d = c.add(d, duration, options)?
335-
}
336-
(Self::Persian(c), AnyDateInner::Persian(ref mut d)) => {
337-
*d = c.add(d, duration, options)?
333+
macro_rules! expr_add {
334+
(HijriTabular, $c:ident, [$d:ident]) => {
335+
Some(AnyDateInner::HijriTabular(
336+
$c.add($d, duration, options)?,
337+
$c.0,
338+
))
339+
};
340+
($cal:ident, $c:ident, [$d:ident]) => {
341+
Some(AnyDateInner::$cal($c.add($d, duration, options)?))
342+
};
343+
}
344+
let result = match_cal_general!((self, date), pattern_cal_date, expr_add, [d, alg], None);
345+
match result {
346+
Some(result) => Ok(result),
347+
None => {
348+
unreachable!("AnyCalendar with mismatched date type")
338349
}
339-
(Self::Roc(c), AnyDateInner::Roc(ref mut d)) => *d = c.add(d, duration, options)?,
340-
// This is only reached from misuse of from_raw, a semi-internal api
341-
#[expect(clippy::panic)]
342-
_ => panic!("AnyCalendar with mismatched date type"),
343350
}
344-
Ok(date)
345351
}
346352

347353
fn until(
@@ -350,92 +356,46 @@ impl Calendar for AnyCalendar {
350356
date2: &Self::DateInner,
351357
options: DateDifferenceOptions,
352358
) -> Result<types::DateDuration, Self::DifferenceError> {
353-
let Ok(r) = match (self, date1, date2) {
354-
(Self::Buddhist(c1), AnyDateInner::Buddhist(d1), AnyDateInner::Buddhist(d2)) => {
355-
c1.until(d1, d2, options)
356-
}
357-
(Self::Chinese(c1), AnyDateInner::Chinese(d1), AnyDateInner::Chinese(d2)) => {
358-
c1.until(d1, d2, options)
359-
}
360-
(Self::Coptic(c1), AnyDateInner::Coptic(d1), AnyDateInner::Coptic(d2)) => {
361-
c1.until(d1, d2, options)
362-
}
363-
(Self::Dangi(c1), AnyDateInner::Dangi(d1), AnyDateInner::Dangi(d2)) => {
364-
c1.until(d1, d2, options)
365-
}
366-
(Self::Ethiopian(c1), AnyDateInner::Ethiopian(d1), AnyDateInner::Ethiopian(d2)) => {
367-
c1.until(d1, d2, options)
368-
}
369-
(Self::Gregorian(c1), AnyDateInner::Gregorian(d1), AnyDateInner::Gregorian(d2)) => {
370-
c1.until(d1, d2, options)
371-
}
372-
(Self::Hebrew(c1), AnyDateInner::Hebrew(d1), AnyDateInner::Hebrew(d2)) => {
373-
c1.until(d1, d2, options)
374-
}
375-
(Self::Indian(c1), AnyDateInner::Indian(d1), AnyDateInner::Indian(d2)) => {
376-
c1.until(d1, d2, options)
377-
}
378-
(
379-
Self::HijriTabular(c1),
380-
&AnyDateInner::HijriTabular(ref d1, s1),
381-
&AnyDateInner::HijriTabular(ref d2, s2),
382-
) if c1.0 == s1 && s1 == s2 => c1.until(d1, d2, options),
383-
(
384-
Self::HijriSimulated(c1),
385-
AnyDateInner::HijriSimulated(d1),
386-
AnyDateInner::HijriSimulated(d2),
387-
) => c1.until(d1, d2, options),
388-
(
389-
Self::HijriUmmAlQura(c1),
390-
AnyDateInner::HijriUmmAlQura(d1),
391-
AnyDateInner::HijriUmmAlQura(d2),
392-
) => c1.until(d1, d2, options),
393-
(Self::Iso(c1), AnyDateInner::Iso(d1), AnyDateInner::Iso(d2)) => {
394-
c1.until(d1, d2, options)
395-
}
396-
(Self::Japanese(c1), AnyDateInner::Japanese(d1), AnyDateInner::Japanese(d2)) => {
397-
c1.until(d1, d2, options)
398-
}
399-
(
400-
Self::JapaneseExtended(c1),
401-
AnyDateInner::JapaneseExtended(d1),
402-
AnyDateInner::JapaneseExtended(d2),
403-
) => c1.until(d1, d2, options),
404-
(Self::Persian(c1), AnyDateInner::Persian(d1), AnyDateInner::Persian(d2)) => {
405-
c1.until(d1, d2, options)
406-
}
407-
(Self::Roc(c1), AnyDateInner::Roc(d1), AnyDateInner::Roc(d2)) => {
408-
c1.until(d1, d2, options)
409-
}
410-
_ => {
411-
return Err(AnyCalendarDifferenceError::MismatchedCalendars);
412-
}
413-
};
414-
Ok(r)
359+
macro_rules! expr_until {
360+
($cal:ident, $c:ident, [$d1:ident, $d2:ident]) => {
361+
Some($c.until($d1, $d2, options))
362+
};
363+
}
364+
let result = match_cal_general!(
365+
(self, date1, date2),
366+
pattern_cal_date_date,
367+
expr_until,
368+
[d1, alg1, d2, alg2],
369+
None
370+
);
371+
match result {
372+
Some(Ok(result)) => Ok(result),
373+
None => Err(AnyCalendarDifferenceError::MismatchedCalendars),
374+
}
415375
}
416376

417377
fn year_info(&self, date: &Self::DateInner) -> types::YearInfo {
418-
match_cal_and_date!(match (self, date): (c, d) => c.year_info(d).into())
378+
match_cal_and_date!((self, date), c.year_info(d).into())
419379
}
420380

421381
/// The calendar-specific check if `date` is in a leap year
422382
fn is_in_leap_year(&self, date: &Self::DateInner) -> bool {
423-
match_cal_and_date!(match (self, date): (c, d) => c.is_in_leap_year(d))
383+
match_cal_and_date!((self, date), c.is_in_leap_year(d))
424384
}
425385

426386
/// The calendar-specific month represented by `date`
427387
fn month(&self, date: &Self::DateInner) -> types::MonthInfo {
428-
match_cal_and_date!(match (self, date): (c, d) => c.month(d))
388+
match_cal_and_date!((self, date), c.month(d))
429389
}
430390

431391
/// The calendar-specific day-of-month represented by `date`
432392
fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth {
433-
match_cal_and_date!(match (self, date): (c, d) => c.day_of_month(d))
393+
match_cal_and_date!((self, date), c.day_of_month(d))
434394
}
435395

436396
/// Information of the day of the year
437397
fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear {
438-
match_cal_and_date!(match (self, date): (c, d) => c.day_of_year(d))
398+
match_cal_and_date!((self, date), c.day_of_year(d))
439399
}
440400

441401
fn debug_name(&self) -> &'static str {

0 commit comments

Comments
 (0)