Skip to content

Commit 459defd

Browse files
committed
Ensure Of is always valid
1 parent 9167548 commit 459defd

File tree

2 files changed

+104
-86
lines changed

2 files changed

+104
-86
lines changed

src/naive/date.rs

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -242,19 +242,29 @@ impl NaiveDate {
242242
pub(crate) fn weeks_from(&self, day: Weekday) -> i32 {
243243
(self.ordinal() as i32 - self.weekday().num_days_from(day) as i32 + 6) / 7
244244
}
245-
/// Makes a new `NaiveDate` from year and packed ordinal-flags, with a verification.
246-
fn from_of(year: i32, of: Of) -> Option<NaiveDate> {
247-
if (MIN_YEAR..=MAX_YEAR).contains(&year) && of.valid() {
248-
let Of(of) = of;
249-
Some(NaiveDate { ymdf: (year << 13) | (of as DateImpl) })
250-
} else {
251-
None
245+
246+
/// Makes a new `NaiveDate` from year, ordinal and flags.
247+
/// Does not check whether the flags are correct for the provided year.
248+
const fn from_of(year: i32, ordinal: u32, flags: YearFlags) -> Option<NaiveDate> {
249+
if year < MIN_YEAR || year > MAX_YEAR {
250+
return None; // Out-of-range
251+
}
252+
match Of::new(ordinal, flags) {
253+
Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
254+
None => None, // Invalid: Ordinal outside of the nr of days in a year with those flags.
252255
}
253256
}
254257

255-
/// Makes a new `NaiveDate` from year and packed month-day-flags, with a verification.
256-
fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
257-
NaiveDate::from_of(year, mdf.to_of())
258+
/// Makes a new `NaiveDate` from year and packed month-day-flags.
259+
/// Does not check whether the flags are correct for the provided year.
260+
const fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
261+
if year < MIN_YEAR || year > MAX_YEAR {
262+
return None; // Out-of-range
263+
}
264+
match mdf.to_of() {
265+
Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
266+
None => None, // Non-existing date
267+
}
258268
}
259269

260270
/// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
@@ -325,7 +335,7 @@ impl NaiveDate {
325335
#[must_use]
326336
pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> {
327337
let flags = YearFlags::from_year(year);
328-
NaiveDate::from_of(year, Of::new(ordinal, flags)?)
338+
NaiveDate::from_of(year, ordinal, flags)
329339
}
330340

331341
/// Makes a new `NaiveDate` from the [ISO week date](#week-date)
@@ -394,20 +404,17 @@ impl NaiveDate {
394404
if weekord <= delta {
395405
// ordinal < 1, previous year
396406
let prevflags = YearFlags::from_year(year - 1);
397-
NaiveDate::from_of(
398-
year - 1,
399-
Of::new(weekord + prevflags.ndays() - delta, prevflags)?,
400-
)
407+
NaiveDate::from_of(year - 1, weekord + prevflags.ndays() - delta, prevflags)
401408
} else {
402409
let ordinal = weekord - delta;
403410
let ndays = flags.ndays();
404411
if ordinal <= ndays {
405412
// this year
406-
NaiveDate::from_of(year, Of::new(ordinal, flags)?)
413+
NaiveDate::from_of(year, ordinal, flags)
407414
} else {
408415
// ordinal > ndays, next year
409416
let nextflags = YearFlags::from_year(year + 1);
410-
NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags)?)
417+
NaiveDate::from_of(year + 1, ordinal - ndays, nextflags)
411418
}
412419
}
413420
} else {
@@ -452,7 +459,7 @@ impl NaiveDate {
452459
let (year_div_400, cycle) = div_mod_floor(days, 146_097);
453460
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
454461
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
455-
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
462+
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
456463
}
457464

458465
/// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
@@ -925,28 +932,24 @@ impl NaiveDate {
925932
/// Returns the packed ordinal-flags.
926933
#[inline]
927934
const fn of(&self) -> Of {
928-
Of((self.ymdf & 0b1_1111_1111_1111) as u32)
935+
Of::from_date_impl(self.ymdf)
929936
}
930937

931938
/// Makes a new `NaiveDate` with the packed month-day-flags changed.
932939
///
933940
/// Returns `None` when the resulting `NaiveDate` would be invalid.
934941
#[inline]
935942
fn with_mdf(&self, mdf: Mdf) -> Option<NaiveDate> {
936-
self.with_of(mdf.to_of())
943+
Some(self.with_of(mdf.to_of()?))
937944
}
938945

939946
/// Makes a new `NaiveDate` with the packed ordinal-flags changed.
940947
///
941948
/// Returns `None` when the resulting `NaiveDate` would be invalid.
949+
/// Does not check if the year flags match the year.
942950
#[inline]
943-
fn with_of(&self, of: Of) -> Option<NaiveDate> {
944-
if of.valid() {
945-
let Of(of) = of;
946-
Some(NaiveDate { ymdf: (self.ymdf & !0b1_1111_1111_1111) | of as DateImpl })
947-
} else {
948-
None
949-
}
951+
const fn with_of(&self, of: Of) -> NaiveDate {
952+
NaiveDate { ymdf: (self.ymdf & !0b1_1111_1111_1111) | of.inner() as DateImpl }
950953
}
951954

952955
/// Makes a new `NaiveDate` for the next calendar date.
@@ -975,7 +978,10 @@ impl NaiveDate {
975978
#[inline]
976979
#[must_use]
977980
pub fn succ_opt(&self) -> Option<NaiveDate> {
978-
self.with_of(self.of().succ()).or_else(|| NaiveDate::from_ymd_opt(self.year() + 1, 1, 1))
981+
match self.of().succ() {
982+
Some(of) => Some(self.with_of(of)),
983+
None => NaiveDate::from_ymd_opt(self.year() + 1, 1, 1),
984+
}
979985
}
980986

981987
/// Makes a new `NaiveDate` for the previous calendar date.
@@ -1004,7 +1010,10 @@ impl NaiveDate {
10041010
#[inline]
10051011
#[must_use]
10061012
pub fn pred_opt(&self) -> Option<NaiveDate> {
1007-
self.with_of(self.of().pred()).or_else(|| NaiveDate::from_ymd_opt(self.year() - 1, 12, 31))
1013+
match self.of().pred() {
1014+
Some(of) => Some(self.with_of(of)),
1015+
None => NaiveDate::from_ymd_opt(self.year() - 1, 12, 31),
1016+
}
10081017
}
10091018

10101019
/// Adds the `days` part of given `Duration` to the current date.
@@ -1036,7 +1045,7 @@ impl NaiveDate {
10361045

10371046
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
10381047
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
1039-
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
1048+
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
10401049
}
10411050

10421051
/// Subtracts the `days` part of given `Duration` from the current date.
@@ -1068,7 +1077,7 @@ impl NaiveDate {
10681077

10691078
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
10701079
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
1071-
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
1080+
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
10721081
}
10731082

10741083
/// Subtracts another `NaiveDate` from the current date.
@@ -1623,7 +1632,7 @@ impl Datelike for NaiveDate {
16231632
/// ```
16241633
#[inline]
16251634
fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
1626-
self.with_of(self.of().with_ordinal(ordinal)?)
1635+
self.of().with_ordinal(ordinal).map(|of| self.with_of(of))
16271636
}
16281637

16291638
/// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
@@ -1648,7 +1657,7 @@ impl Datelike for NaiveDate {
16481657
#[inline]
16491658
fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
16501659
let ordinal = ordinal0.checked_add(1)?;
1651-
self.with_of(self.of().with_ordinal(ordinal)?)
1660+
self.with_ordinal(ordinal)
16521661
}
16531662
}
16541663

0 commit comments

Comments
 (0)