1616#[ cfg( feature = "alloc" ) ]
1717use core:: borrow:: Borrow ;
1818use core:: iter:: FusedIterator ;
19+ use core:: num:: NonZeroI32 ;
1920use core:: ops:: { Add , AddAssign , Sub , SubAssign } ;
2021use core:: { fmt, str} ;
2122
@@ -99,7 +100,7 @@ mod tests;
99100) ]
100101#[ cfg_attr( feature = "rkyv-validation" , archive( check_bytes) ) ]
101102pub 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
14101424impl 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