Skip to content

Commit a796272

Browse files
committed
Use NonZeroI32 inside NaiveDate
1 parent 926322d commit a796272

File tree

2 files changed

+42
-28
lines changed

2 files changed

+42
-28
lines changed

src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -642,20 +642,20 @@ mod tests {
642642
fn test_type_sizes() {
643643
use core::mem::size_of;
644644
assert_eq!(size_of::<NaiveDate>(), 4);
645-
assert_eq!(size_of::<Option<NaiveDate>>(), 8);
645+
assert_eq!(size_of::<Option<NaiveDate>>(), 4);
646646
assert_eq!(size_of::<NaiveTime>(), 8);
647647
assert_eq!(size_of::<Option<NaiveTime>>(), 12);
648648
assert_eq!(size_of::<NaiveDateTime>(), 12);
649-
assert_eq!(size_of::<Option<NaiveDateTime>>(), 16);
649+
assert_eq!(size_of::<Option<NaiveDateTime>>(), 12);
650650

651651
assert_eq!(size_of::<DateTime<Utc>>(), 12);
652652
assert_eq!(size_of::<DateTime<FixedOffset>>(), 16);
653653
assert_eq!(size_of::<DateTime<Local>>(), 16);
654-
assert_eq!(size_of::<Option<DateTime<FixedOffset>>>(), 20);
654+
assert_eq!(size_of::<Option<DateTime<FixedOffset>>>(), 16);
655655

656656
assert_eq!(size_of::<Date<Utc>>(), 4);
657-
assert_eq!(size_of::<Option<Date<Utc>>>(), 8);
657+
assert_eq!(size_of::<Option<Date<Utc>>>(), 4);
658658
assert_eq!(size_of::<Date<FixedOffset>>(), 8);
659-
assert_eq!(size_of::<Option<Date<FixedOffset>>>(), 12);
659+
assert_eq!(size_of::<Option<Date<FixedOffset>>>(), 8);
660660
}
661661
}

src/naive/date/mod.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#[cfg(feature = "alloc")]
1717
use core::borrow::Borrow;
1818
use core::iter::FusedIterator;
19+
use core::num::NonZeroI32;
1920
use core::ops::{Add, AddAssign, Sub, SubAssign};
2021
use core::{fmt, str};
2122

@@ -99,7 +100,7 @@ mod tests;
99100
)]
100101
#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
101102
pub struct NaiveDate {
102-
yof: i32, // (year << 13) | of
103+
yof: NonZeroI32, // (year << 13) | of
103104
}
104105

105106
/// The minimum possible `NaiveDate` (January 1, 262145 BCE).
@@ -140,7 +141,7 @@ impl NaiveDate {
140141
debug_assert!(YearFlags::from_year(year).0 == flags.0);
141142
let yof = (year << 13) | (ordinal << 4) as i32 | flags.0 as i32;
142143
match yof & OL_MASK <= MAX_OL {
143-
true => Some(NaiveDate { yof }),
144+
true => Some(NaiveDate::from_yof(yof)),
144145
false => None, // Does not exist: Ordinal 366 in a common year.
145146
}
146147
}
@@ -691,10 +692,10 @@ impl NaiveDate {
691692
pub(crate) const fn add_days(self, days: i32) -> Option<Self> {
692693
// fast path if the result is within the same year
693694
const ORDINAL_MASK: i32 = 0b1_1111_1111_0000;
694-
if let Some(ordinal) = ((self.yof & ORDINAL_MASK) >> 4).checked_add(days) {
695+
if let Some(ordinal) = ((self.yof() & ORDINAL_MASK) >> 4).checked_add(days) {
695696
if ordinal > 0 && ordinal <= 365 {
696-
let year_and_flags = self.yof & !ORDINAL_MASK;
697-
return Some(NaiveDate { yof: year_and_flags | (ordinal << 4) });
697+
let year_and_flags = self.yof() & !ORDINAL_MASK;
698+
return Some(NaiveDate::from_yof(year_and_flags | (ordinal << 4)));
698699
}
699700
}
700701
// do the full check
@@ -939,7 +940,7 @@ impl NaiveDate {
939940
/// Returns the packed month-day-flags.
940941
#[inline]
941942
const fn mdf(&self) -> Mdf {
942-
Mdf::from_ol((self.yof & OL_MASK) >> 3, self.year_flags())
943+
Mdf::from_ol((self.yof() & OL_MASK) >> 3, self.year_flags())
943944
}
944945

945946
/// Makes a new `NaiveDate` with the packed month-day-flags changed.
@@ -950,7 +951,7 @@ impl NaiveDate {
950951
debug_assert!(self.year_flags().0 == mdf.year_flags().0);
951952
match mdf.ordinal() {
952953
Some(ordinal) => {
953-
Some(NaiveDate { yof: (self.yof & !ORDINAL_MASK) | (ordinal << 4) as i32 })
954+
Some(NaiveDate::from_yof((self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32))
954955
}
955956
None => None, // Non-existing date
956957
}
@@ -986,9 +987,9 @@ impl NaiveDate {
986987
#[inline]
987988
#[must_use]
988989
pub const fn succ_opt(&self) -> Option<NaiveDate> {
989-
let new_ol = (self.yof & OL_MASK) + (1 << 4);
990+
let new_ol = (self.yof() & OL_MASK) + (1 << 4);
990991
match new_ol <= MAX_OL {
991-
true => Some(NaiveDate { yof: self.yof & !OL_MASK | new_ol }),
992+
true => Some(NaiveDate::from_yof(self.yof() & !OL_MASK | new_ol)),
992993
false => NaiveDate::from_yo_opt(self.year() + 1, 1),
993994
}
994995
}
@@ -1023,9 +1024,9 @@ impl NaiveDate {
10231024
#[inline]
10241025
#[must_use]
10251026
pub const fn pred_opt(&self) -> Option<NaiveDate> {
1026-
let new_shifted_ordinal = (self.yof & ORDINAL_MASK) - (1 << 4);
1027+
let new_shifted_ordinal = (self.yof() & ORDINAL_MASK) - (1 << 4);
10271028
match new_shifted_ordinal > 0 {
1028-
true => Some(NaiveDate { yof: self.yof & !ORDINAL_MASK | new_shifted_ordinal }),
1029+
true => Some(NaiveDate::from_yof(self.yof() & !ORDINAL_MASK | new_shifted_ordinal)),
10291030
false => NaiveDate::from_ymd_opt(self.year() - 1, 12, 31),
10301031
}
10311032
}
@@ -1330,20 +1331,20 @@ impl NaiveDate {
13301331
/// assert_eq!(NaiveDate::from_ymd_opt(2100, 1, 1).unwrap().leap_year(), false);
13311332
/// ```
13321333
pub const fn leap_year(&self) -> bool {
1333-
self.yof & (0b1000) == 0
1334+
self.yof() & (0b1000) == 0
13341335
}
13351336

13361337
// This duplicates `Datelike::year()`, because trait methods can't be const yet.
13371338
#[inline]
13381339
const fn year(&self) -> i32 {
1339-
self.yof >> 13
1340+
self.yof() >> 13
13401341
}
13411342

13421343
/// Returns the day of year starting from 1.
13431344
// This duplicates `Datelike::ordinal()`, because trait methods can't be const yet.
13441345
#[inline]
13451346
const fn ordinal(&self) -> u32 {
1346-
((self.yof & ORDINAL_MASK) >> 4) as u32
1347+
((self.yof() & ORDINAL_MASK) >> 4) as u32
13471348
}
13481349

13491350
// This duplicates `Datelike::month()`, because trait methods can't be const yet.
@@ -1362,7 +1363,7 @@ impl NaiveDate {
13621363
// This duplicates `Datelike::weekday()`, because trait methods can't be const yet.
13631364
#[inline]
13641365
pub(super) const fn weekday(&self) -> Weekday {
1365-
match (((self.yof & ORDINAL_MASK) >> 4) + (self.yof & WEEKDAY_FLAGS_MASK)) % 7 {
1366+
match (((self.yof() & ORDINAL_MASK) >> 4) + (self.yof() & WEEKDAY_FLAGS_MASK)) % 7 {
13661367
0 => Weekday::Mon,
13671368
1 => Weekday::Tue,
13681369
2 => Weekday::Wed,
@@ -1375,7 +1376,7 @@ impl NaiveDate {
13751376

13761377
#[inline]
13771378
const fn year_flags(&self) -> YearFlags {
1378-
YearFlags((self.yof & YEAR_FLAGS_MASK) as u8)
1379+
YearFlags((self.yof() & YEAR_FLAGS_MASK) as u8)
13791380
}
13801381

13811382
/// Counts the days in the proleptic Gregorian calendar, with January 1, Year 1 (CE) as day 1.
@@ -1394,17 +1395,30 @@ impl NaiveDate {
13941395
ndays + self.ordinal() as i32
13951396
}
13961397

1398+
/// Create a new `NaiveDate` from a raw year-ordinal-flags `i32`.
1399+
///
1400+
/// In a valid value an ordinal is never `0`, and neither are the year flags. This method
1401+
/// doesn't do any validation; it only panics if the value is `0`.
1402+
const fn from_yof(yof: i32) -> NaiveDate {
1403+
NaiveDate { yof: expect!(NonZeroI32::new(yof), "invalid internal value") }
1404+
}
1405+
1406+
/// Get the raw year-ordinal-flags `i32`.
1407+
const fn yof(&self) -> i32 {
1408+
self.yof.get()
1409+
}
1410+
13971411
/// The minimum possible `NaiveDate` (January 1, 262144 BCE).
1398-
pub const MIN: NaiveDate = NaiveDate { yof: (MIN_YEAR << 13) | (1 << 4) | 0o12 /*D*/ };
1412+
pub const MIN: NaiveDate = NaiveDate::from_yof((MIN_YEAR << 13) | (1 << 4) | 0o12 /*D*/);
13991413
/// The maximum possible `NaiveDate` (December 31, 262142 CE).
1400-
pub const MAX: NaiveDate = NaiveDate { yof: (MAX_YEAR << 13) | (365 << 4) | 0o16 /*G*/ };
1414+
pub const MAX: NaiveDate = NaiveDate::from_yof((MAX_YEAR << 13) | (365 << 4) | 0o16 /*G*/);
14011415

14021416
/// One day before the minimum possible `NaiveDate` (December 31, 262145 BCE).
14031417
pub(crate) const BEFORE_MIN: NaiveDate =
1404-
NaiveDate { yof: ((MIN_YEAR - 1) << 13) | (366 << 4) | 0o07 /*FE*/ };
1418+
NaiveDate::from_yof(((MIN_YEAR - 1) << 13) | (366 << 4) | 0o07 /*FE*/);
14051419
/// One day after the maximum possible `NaiveDate` (January 1, 262143 CE).
14061420
pub(crate) const AFTER_MAX: NaiveDate =
1407-
NaiveDate { yof: ((MAX_YEAR + 1) << 13) | (1 << 4) | 0o17 /*F*/ };
1421+
NaiveDate::from_yof(((MAX_YEAR + 1) << 13) | (1 << 4) | 0o17 /*F*/);
14081422
}
14091423

14101424
impl Datelike for NaiveDate {
@@ -1550,7 +1564,7 @@ impl Datelike for NaiveDate {
15501564
/// ```
15511565
#[inline]
15521566
fn ordinal(&self) -> u32 {
1553-
((self.yof & ORDINAL_MASK) >> 4) as u32
1567+
((self.yof() & ORDINAL_MASK) >> 4) as u32
15541568
}
15551569

15561570
/// Returns the day of year starting from 0.
@@ -1741,9 +1755,9 @@ impl Datelike for NaiveDate {
17411755
if ordinal == 0 || ordinal > 366 {
17421756
return None;
17431757
}
1744-
let yof = (self.yof & !ORDINAL_MASK) | (ordinal << 4) as i32;
1758+
let yof = (self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32;
17451759
match yof & OL_MASK <= MAX_OL {
1746-
true => Some(NaiveDate { yof }),
1760+
true => Some(NaiveDate::from_yof(yof)),
17471761
false => None, // Does not exist: Ordinal 366 in a common year.
17481762
}
17491763
}

0 commit comments

Comments
 (0)