Skip to content

Commit 4cfa2da

Browse files
authored
implement utility methods on partial structs (#206)
This PR adds methods with the goal of making Partials structs a bit more ergonomic to work with rather than using only struct expressions. Before: ```rust let day = Some(24); let date = PartialDate { day, ..Default::default() }; ```` After: ```rust let day = Some(24); let date = PartialDate::default().with_day(day); ``` If this doesn't make much sense and it's preferred to keep the current method of `StructExpressions`
1 parent e820d04 commit 4cfa2da

File tree

6 files changed

+161
-10
lines changed

6 files changed

+161
-10
lines changed

src/builtins/core/calendar.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl IcuCalendar for Calendar {
134134

135135
impl Calendar {
136136
#[warn(clippy::wildcard_enum_match_arm)] // Warns if the calendar kind gets out of sync.
137-
pub fn new(kind: AnyCalendarKind) -> Self {
137+
pub const fn new(kind: AnyCalendarKind) -> Self {
138138
let cal = match kind {
139139
AnyCalendarKind::Buddhist => &AnyCalendar::Buddhist(Buddhist),
140140
AnyCalendarKind::Chinese => const { &AnyCalendar::Chinese(Chinese::new()) },
@@ -172,7 +172,8 @@ impl Calendar {
172172
}
173173
AnyCalendarKind::Persian => &AnyCalendar::Persian(Persian),
174174
AnyCalendarKind::Roc => &AnyCalendar::Roc(Roc),
175-
_ => unreachable!("match must handle all variants of `AnyCalendarKind`"),
175+
// NOTE: `unreachable!` is not const, but panic is.
176+
_ => panic!("Unreachable: match must handle all variants of `AnyCalendarKind`"),
176177
};
177178

178179
Self(Ref(cal))

src/builtins/core/date.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{
1616
};
1717
use alloc::{format, string::String};
1818
use core::{cmp::Ordering, str::FromStr};
19+
use icu_calendar::AnyCalendarKind;
1920

2021
use super::{
2122
calendar::month_to_month_code,
@@ -125,6 +126,56 @@ macro_rules! impl_with_fallback_method {
125126
};
126127
}
127128

129+
/// Convenience methods for building a `PartialDate`
130+
impl PartialDate {
131+
pub const fn new() -> Self {
132+
Self {
133+
year: None,
134+
month: None,
135+
month_code: None,
136+
day: None,
137+
era: None,
138+
era_year: None,
139+
calendar: Calendar::new(AnyCalendarKind::Iso),
140+
}
141+
}
142+
143+
pub const fn with_era(mut self, era: Option<TinyAsciiStr<19>>) -> Self {
144+
self.era = era;
145+
self
146+
}
147+
148+
pub const fn with_era_year(mut self, era_year: Option<i32>) -> Self {
149+
self.era_year = era_year;
150+
self
151+
}
152+
153+
pub const fn with_year(mut self, year: Option<i32>) -> Self {
154+
self.year = year;
155+
self
156+
}
157+
158+
pub const fn with_month(mut self, month: Option<u8>) -> Self {
159+
self.month = month;
160+
self
161+
}
162+
163+
pub const fn with_month_code(mut self, month_code: Option<MonthCode>) -> Self {
164+
self.month_code = month_code;
165+
self
166+
}
167+
168+
pub const fn with_day(mut self, day: Option<u8>) -> Self {
169+
self.day = day;
170+
self
171+
}
172+
173+
pub const fn with_calendar(mut self, calendar: Calendar) -> Self {
174+
self.calendar = calendar;
175+
self
176+
}
177+
}
178+
128179
/// The native Rust implementation of `Temporal.PlainDate`.
129180
#[non_exhaustive]
130181
#[derive(Debug, Default, Clone, PartialEq, Eq)]

src/builtins/core/datetime.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,29 @@ pub struct PartialDateTime {
2828
pub time: PartialTime,
2929
}
3030

31+
impl PartialDateTime {
32+
pub fn is_empty(&self) -> bool {
33+
self.date.is_empty() && self.time.is_empty()
34+
}
35+
36+
pub const fn new() -> Self {
37+
Self {
38+
date: PartialDate::new(),
39+
time: PartialTime::new(),
40+
}
41+
}
42+
43+
pub const fn with_partial_date(mut self, partial_date: PartialDate) -> Self {
44+
self.date = partial_date;
45+
self
46+
}
47+
48+
pub const fn with_partial_time(mut self, partial_time: PartialTime) -> Self {
49+
self.time = partial_time;
50+
self
51+
}
52+
}
53+
3154
/// The native Rust implementation of `Temporal.PlainDateTime`
3255
#[non_exhaustive]
3356
#[derive(Debug, Default, Clone, PartialEq, Eq)]
@@ -318,7 +341,7 @@ impl PlainDateTime {
318341
partial: PartialDateTime,
319342
overflow: Option<ArithmeticOverflow>,
320343
) -> TemporalResult<Self> {
321-
if partial.date.is_empty() && partial.time.is_empty() {
344+
if partial.is_empty() {
322345
return Err(TemporalError::r#type().with_message("PartialDateTime cannot be empty."));
323346
}
324347
let date = PlainDate::from_partial(partial.date, overflow)?;

src/builtins/core/duration.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,6 @@ impl Duration {
353353
&self.date
354354
}
355355

356-
/// Set this `DurationRecord`'s `TimeDuration`.
357-
#[inline]
358-
pub fn set_time_duration(&mut self, time: TimeDuration) {
359-
self.time = time;
360-
}
361-
362356
/// Returns the `years` field of duration.
363357
#[inline]
364358
#[must_use]

src/builtins/core/time.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,55 @@ pub struct PartialTime {
3535
}
3636

3737
impl PartialTime {
38-
pub(crate) fn is_empty(&self) -> bool {
38+
pub fn is_empty(&self) -> bool {
3939
*self == Self::default()
4040
}
4141
}
4242

43+
/// Convenience methods for building a `PartialTime`
44+
impl PartialTime {
45+
pub const fn new() -> Self {
46+
Self {
47+
hour: None,
48+
minute: None,
49+
second: None,
50+
millisecond: None,
51+
microsecond: None,
52+
nanosecond: None,
53+
}
54+
}
55+
56+
pub const fn with_hour(mut self, hour: Option<u8>) -> Self {
57+
self.hour = hour;
58+
self
59+
}
60+
61+
pub const fn with_minute(mut self, minute: Option<u8>) -> Self {
62+
self.minute = minute;
63+
self
64+
}
65+
66+
pub const fn with_second(mut self, second: Option<u8>) -> Self {
67+
self.second = second;
68+
self
69+
}
70+
71+
pub const fn with_millisecond(mut self, millisecond: Option<u16>) -> Self {
72+
self.millisecond = millisecond;
73+
self
74+
}
75+
76+
pub const fn with_microsecond(mut self, microsecond: Option<u16>) -> Self {
77+
self.microsecond = microsecond;
78+
self
79+
}
80+
81+
pub const fn with_nanosecond(mut self, nanosecond: Option<u16>) -> Self {
82+
self.nanosecond = nanosecond;
83+
self
84+
}
85+
}
86+
4387
/// The native Rust implementation of `Temporal.PlainTime`.
4488
#[non_exhaustive]
4589
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]

src/builtins/core/zoneddatetime.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,44 @@ pub struct PartialZonedDateTime {
4343
pub timezone: Option<TimeZone>,
4444
}
4545

46+
impl PartialZonedDateTime {
47+
pub fn is_empty(&self) -> bool {
48+
self.date.is_empty()
49+
&& self.time.is_empty()
50+
&& self.offset.is_none()
51+
&& self.timezone.is_none()
52+
}
53+
54+
pub const fn new() -> Self {
55+
Self {
56+
date: PartialDate::new(),
57+
time: PartialTime::new(),
58+
offset: None,
59+
timezone: None,
60+
}
61+
}
62+
63+
pub const fn with_date(mut self, partial_date: PartialDate) -> Self {
64+
self.date = partial_date;
65+
self
66+
}
67+
68+
pub const fn with_time(mut self, partial_time: PartialTime) -> Self {
69+
self.time = partial_time;
70+
self
71+
}
72+
73+
pub fn with_offset(mut self, offset: Option<String>) -> Self {
74+
self.offset = offset;
75+
self
76+
}
77+
78+
pub fn with_timezone(mut self, timezone: Option<TimeZone>) -> Self {
79+
self.timezone = timezone;
80+
self
81+
}
82+
}
83+
4684
/// The native Rust implementation of `Temporal.ZonedDateTime`.
4785
#[non_exhaustive]
4886
#[derive(Debug, Clone, PartialEq, Eq)]

0 commit comments

Comments
 (0)