Skip to content

Commit be01703

Browse files
committed
Reduce duplication, new hidden methods for macros
1 parent e19b951 commit be01703

3 files changed

Lines changed: 102 additions & 83 deletions

File tree

src/date.rs

Lines changed: 21 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use crate::no_std_prelude::*;
33
use crate::{
44
format::parse::{parse, ParseError, ParseResult, ParsedItems},
5-
ComponentRangeError, DeferredFormat, Duration, PrimitiveDateTime, Time,
5+
internals, ComponentRangeError, DeferredFormat, Duration, PrimitiveDateTime, Time,
66
Weekday::{self, Friday, Monday, Saturday, Sunday, Thursday, Tuesday, Wednesday},
77
};
88
use core::{
@@ -72,9 +72,7 @@ pub const fn days_in_year(year: i32) -> u16 {
7272
/// ```
7373
#[inline(always)]
7474
pub fn weeks_in_year(year: i32) -> u8 {
75-
let weekday = Date::try_from_yo(year, 1)
76-
.expect("date is always valid")
77-
.weekday();
75+
let weekday = internals::Date::from_yo(year, 1).weekday();
7876

7977
if (weekday == Thursday) || (weekday == Wednesday && is_leap_year(year)) {
8078
53
@@ -125,22 +123,10 @@ impl Date {
125123
#[cfg(feature = "panicking-api")]
126124
#[cfg_attr(doc, doc(cfg(feature = "panicking-api")))]
127125
pub fn from_ymd(year: i32, month: u8, day: u8) -> Self {
128-
/// Cumulative days through the beginning of a month in both common and
129-
/// leap years.
130-
const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
131-
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
132-
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
133-
];
134-
135126
assert_value_in_range!(month in 1 => 12);
136127
assert_value_in_range!(day in 1 => days_in_year_month(year, month), given year, month);
137128

138-
let ordinal = DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year(year) as usize][month as usize - 1];
139-
140-
Self {
141-
year,
142-
ordinal: ordinal + day as u16,
143-
}
129+
internals::Date::from_ymd(year, month, day)
144130
}
145131

146132
/// Attempt to create a `Date` from the year, month, and day.
@@ -159,22 +145,10 @@ impl Date {
159145
/// ```
160146
#[inline]
161147
pub fn try_from_ymd(year: i32, month: u8, day: u8) -> Result<Self, ComponentRangeError> {
162-
/// Cumulative days through the beginning of a month in both common and
163-
/// leap years.
164-
const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
165-
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
166-
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
167-
];
168-
169148
ensure_value_in_range!(month in 1 => 12);
170149
ensure_value_in_range!(day in 1 => days_in_year_month(year, month), given year, month);
171150

172-
let ordinal = DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year(year) as usize][month as usize - 1];
173-
174-
Ok(Self {
175-
year,
176-
ordinal: ordinal + day as u16,
177-
})
151+
Ok(internals::Date::from_ymd(year, month, day))
178152
}
179153

180154
/// Create a `Date` from the year and ordinal day number.
@@ -248,20 +222,7 @@ impl Date {
248222
#[cfg_attr(doc, doc(cfg(feature = "panicking-api")))]
249223
pub fn from_iso_ywd(year: i32, week: u8, weekday: Weekday) -> Self {
250224
assert_value_in_range!(week in 1 => weeks_in_year(year), given year);
251-
252-
let ordinal = week as u16 * 7 + weekday.iso_weekday_number() as u16
253-
- (Self::from_yo(year, 4).weekday().iso_weekday_number() as u16 + 3);
254-
255-
if ordinal < 1 {
256-
return Self::from_yo(year - 1, ordinal + days_in_year(year - 1));
257-
}
258-
259-
let days_in_cur_year = days_in_year(year);
260-
if ordinal > days_in_cur_year {
261-
Self::from_yo(year + 1, ordinal - days_in_cur_year)
262-
} else {
263-
Self::from_yo(year, ordinal)
264-
}
225+
internals::Date::from_iso_ywd(year, week, weekday)
265226
}
266227

267228
/// Attempt to create a `Date` from the ISO year, week, and weekday.
@@ -286,24 +247,7 @@ impl Date {
286247
weekday: Weekday,
287248
) -> Result<Self, ComponentRangeError> {
288249
ensure_value_in_range!(week in 1 => weeks_in_year(year), given year);
289-
290-
let ordinal = week as u16 * 7 + weekday.iso_weekday_number() as u16
291-
- (Self::try_from_yo(year, 4)
292-
.expect("date is always valid")
293-
.weekday()
294-
.iso_weekday_number() as u16
295-
+ 3);
296-
297-
if ordinal < 1 {
298-
return Self::try_from_yo(year - 1, ordinal + days_in_year(year - 1));
299-
}
300-
301-
let days_in_cur_year = days_in_year(year);
302-
if ordinal > days_in_cur_year {
303-
Self::try_from_yo(year + 1, ordinal - days_in_cur_year)
304-
} else {
305-
Self::try_from_yo(year, ordinal)
306-
}
250+
Ok(internals::Date::from_iso_ywd(year, week, weekday))
307251
}
308252

309253
/// Create a `Date` representing the current date.
@@ -674,8 +618,9 @@ impl Date {
674618
let month = (h / S + M).rem_euclid(N) + 1;
675619
let year = (e / P) - Y + (N + M - month) / N;
676620

621+
// TODO Seek out a formal proof that this always results in a valid value.
677622
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
678-
Self::try_from_ymd(year as i32, month as u8, day as u8).expect("date is always valid")
623+
internals::Date::from_ymd(year as i32, month as u8, day as u8)
679624
}
680625
}
681626

@@ -945,10 +890,7 @@ impl Date {
945890
/// Monday-based week numbering.
946891
#[inline(always)]
947892
fn adjustment(year: i32) -> i16 {
948-
match Date::try_from_yo(year, 1)
949-
.expect("date is always valid")
950-
.weekday()
951-
{
893+
match internals::Date::from_yo(year, 1).weekday() {
952894
Monday => 7,
953895
Tuesday => 1,
954896
Wednesday => 2,
@@ -959,37 +901,33 @@ impl Date {
959901
}
960902
}
961903

904+
// Verification for all components is done at parse time.
962905
match items {
963-
items!(year, month, day) => Ok(Self::try_from_ymd(year, month.get(), day.get())
964-
.expect("components are checked when parsing")),
965-
items!(year, ordinal_day) => Ok(Self::try_from_yo(year, ordinal_day.get())
966-
.expect("components are checked when parsing")),
967-
items!(week_based_year, iso_week, weekday) => {
968-
Ok(
969-
Self::try_from_iso_ywd(week_based_year, iso_week.get(), weekday)
970-
.expect("components are checked when parsing"),
971-
)
972-
}
973-
items!(year, sunday_week, weekday) => Ok(Self::try_from_yo(
906+
items!(year, month, day) => Ok(internals::Date::from_ymd(year, month.get(), day.get())),
907+
items!(year, ordinal_day) => Ok(internals::Date::from_yo(year, ordinal_day.get())),
908+
items!(week_based_year, iso_week, weekday) => Ok(internals::Date::from_iso_ywd(
909+
week_based_year,
910+
iso_week.get(),
911+
weekday,
912+
)),
913+
items!(year, sunday_week, weekday) => Ok(internals::Date::from_yo(
974914
year,
975915
#[allow(clippy::cast_sign_loss)]
976916
{
977917
(sunday_week as i16 * 7 + weekday.number_days_from_sunday() as i16
978918
- adjustment(year)
979919
+ 1) as u16
980920
},
981-
)
982-
.expect("components are checked when parsing")),
983-
items!(year, monday_week, weekday) => Ok(Self::try_from_yo(
921+
)),
922+
items!(year, monday_week, weekday) => Ok(internals::Date::from_yo(
984923
year,
985924
#[allow(clippy::cast_sign_loss)]
986925
{
987926
(monday_week as i16 * 7 + weekday.number_days_from_monday() as i16
988927
- adjustment(year)
989928
+ 1) as u16
990929
},
991-
)
992-
.expect("components are checked when parsing")),
930+
)),
993931
_ => Err(ParseError::InsufficientInformation),
994932
}
995933
}

src/internals.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! This module and its contents are not subject to stability guarantees and
2+
//! should not be be relied upon.
3+
//!
4+
//! These methods either exist to reduce duplication in code elsewhere or are
5+
//! public only for usage in macros. The reasoning for a method's existence is
6+
//! generally documented alongside the method.
7+
//!
8+
//! Failure to ensure that parameters to the contained functions are in range
9+
//! will likely result in invalid behavior.
10+
11+
#![doc(hidden)]
12+
#![allow(missing_debug_implementations, missing_copy_implementations)]
13+
14+
use crate::{days_in_year, is_leap_year, Weekday};
15+
16+
pub struct Time;
17+
18+
impl Time {
19+
/// Create a `Time` from its components.
20+
#[inline(always)]
21+
pub const fn from_hms_nanos_unchecked(
22+
hour: u8,
23+
minute: u8,
24+
second: u8,
25+
nanosecond: u32,
26+
) -> crate::Time {
27+
crate::Time {
28+
hour,
29+
minute,
30+
second,
31+
nanosecond,
32+
}
33+
}
34+
}
35+
36+
pub struct Date;
37+
38+
impl Date {
39+
// macros
40+
#[inline(always)]
41+
pub const fn from_yo(year: i32, ordinal: u16) -> crate::Date {
42+
crate::Date { year, ordinal }
43+
}
44+
45+
// reduce duplication
46+
#[inline]
47+
pub(crate) const fn from_ymd(year: i32, month: u8, day: u8) -> crate::Date {
48+
/// Cumulative days through the beginning of a month in both common and
49+
/// leap years.
50+
const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
51+
[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
52+
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
53+
];
54+
55+
let ordinal = DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year(year) as usize][month as usize - 1];
56+
57+
crate::Date {
58+
year,
59+
ordinal: ordinal + day as u16,
60+
}
61+
}
62+
63+
// reduce duplication
64+
#[inline]
65+
pub(crate) fn from_iso_ywd(year: i32, week: u8, weekday: Weekday) -> crate::Date {
66+
let ordinal = week as u16 * 7 + weekday.iso_weekday_number() as u16
67+
- (Self::from_yo(year, 4).weekday().iso_weekday_number() as u16 + 3);
68+
69+
if ordinal < 1 {
70+
return Self::from_yo(year - 1, ordinal + days_in_year(year - 1));
71+
}
72+
73+
let days_in_cur_year = days_in_year(year);
74+
if ordinal > days_in_cur_year {
75+
Self::from_yo(year + 1, ordinal - days_in_cur_year)
76+
} else {
77+
Self::from_yo(year, ordinal)
78+
}
79+
}
80+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ mod format;
272272
/// The `Instant` struct and its associated `impl`s.
273273
#[cfg(feature = "std")]
274274
mod instant;
275+
pub mod internals;
275276
/// A collection of traits extending built-in numerical types.
276277
mod numerical_traits;
277278
/// The `OffsetDateTime` struct and its associated `impl`s.

0 commit comments

Comments
 (0)