Skip to content

Commit 490a17b

Browse files
committed
Mark error paths in well-known formats as cold
1 parent 6cb1896 commit 490a17b

File tree

2 files changed

+443
-338
lines changed

2 files changed

+443
-338
lines changed

time/src/parsing/iso8601.rs

Lines changed: 132 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::error;
55
use crate::error::ParseFromDescription::{InvalidComponent, InvalidLiteral};
66
use crate::format_description::well_known::Iso8601;
77
use crate::format_description::well_known::iso8601::EncodedConfig;
8+
use crate::internal_macros::try_likely_ok;
89
use crate::parsing::combinator::rfc::iso8601::{
910
ExtendedKind, day, dayk, dayo, float, hour, min, month, week, year,
1011
};
@@ -25,7 +26,8 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
2526
) -> impl FnMut(&[u8]) -> Result<&[u8], error::Parse> + use<'a, CONFIG> {
2627
move |input| {
2728
// Same for any acceptable format.
28-
let ParsedItem(mut input, year) = year(input).ok_or(InvalidComponent("year"))?;
29+
let ParsedItem(mut input, year) =
30+
try_likely_ok!(year(input).ok_or(InvalidComponent("year")));
2931
*extended_kind = match ascii_char::<b'-'>(input) {
3032
Some(ParsedItem(new_input, ())) => {
3133
input = new_input;
@@ -35,63 +37,69 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
3537
};
3638

3739
let parsed_month_day = (|| {
38-
let ParsedItem(mut input, month) = month(input).ok_or(InvalidComponent("month"))?;
40+
let ParsedItem(mut input, month) =
41+
try_likely_ok!(month(input).ok_or(InvalidComponent("month")));
3942
if extended_kind.is_extended() {
40-
input = ascii_char::<b'-'>(input)
41-
.ok_or(InvalidLiteral)?
43+
input = try_likely_ok!(ascii_char::<b'-'>(input).ok_or(InvalidLiteral))
4244
.into_inner();
4345
}
44-
let ParsedItem(input, day) = day(input).ok_or(InvalidComponent("day"))?;
46+
let ParsedItem(input, day) =
47+
try_likely_ok!(day(input).ok_or(InvalidComponent("day")));
4548
Ok(ParsedItem(input, (month, day)))
4649
})();
4750
let mut ret_error = match parsed_month_day {
4851
Ok(ParsedItem(input, (month, day))) => {
49-
*parsed = parsed
50-
.with_year(year)
51-
.ok_or(InvalidComponent("year"))?
52-
.with_month(month)
53-
.ok_or(InvalidComponent("month"))?
52+
*parsed = try_likely_ok!(
53+
try_likely_ok!(
54+
try_likely_ok!(parsed.with_year(year).ok_or(InvalidComponent("year")))
55+
.with_month(month)
56+
.ok_or(InvalidComponent("month"))
57+
)
5458
.with_day(day)
55-
.ok_or(InvalidComponent("day"))?;
59+
.ok_or(InvalidComponent("day"))
60+
);
5661
return Ok(input);
5762
}
5863
Err(err) => err,
5964
};
6065

6166
// Don't check for `None`, as the error from year-month-day will always take priority.
6267
if let Some(ParsedItem(input, ordinal)) = dayo(input) {
63-
*parsed = parsed
64-
.with_year(year)
65-
.ok_or(InvalidComponent("year"))?
66-
.with_ordinal(ordinal)
67-
.ok_or(InvalidComponent("ordinal"))?;
68+
*parsed = try_likely_ok!(
69+
try_likely_ok!(parsed.with_year(year).ok_or(InvalidComponent("year")))
70+
.with_ordinal(ordinal)
71+
.ok_or(InvalidComponent("ordinal"))
72+
);
6873
return Ok(input);
6974
}
7075

7176
let parsed_week_weekday = (|| {
72-
let input = ascii_char::<b'W'>(input)
73-
.ok_or((false, InvalidLiteral))?
74-
.into_inner();
77+
let input =
78+
try_likely_ok!(ascii_char::<b'W'>(input).ok_or((false, InvalidLiteral)))
79+
.into_inner();
7580
let ParsedItem(mut input, week) =
76-
week(input).ok_or((true, InvalidComponent("week")))?;
81+
try_likely_ok!(week(input).ok_or((true, InvalidComponent("week"))));
7782
if extended_kind.is_extended() {
78-
input = ascii_char::<b'-'>(input)
79-
.ok_or((true, InvalidLiteral))?
83+
input = try_likely_ok!(ascii_char::<b'-'>(input).ok_or((true, InvalidLiteral)))
8084
.into_inner();
8185
}
8286
let ParsedItem(input, weekday) =
83-
dayk(input).ok_or((true, InvalidComponent("weekday")))?;
87+
try_likely_ok!(dayk(input).ok_or((true, InvalidComponent("weekday"))));
8488
Ok(ParsedItem(input, (week, weekday)))
8589
})();
8690
match parsed_week_weekday {
8791
Ok(ParsedItem(input, (week, weekday))) => {
88-
*parsed = parsed
89-
.with_iso_year(year)
90-
.ok_or(InvalidComponent("year"))?
91-
.with_iso_week_number(week)
92-
.ok_or(InvalidComponent("week"))?
92+
*parsed = try_likely_ok!(
93+
try_likely_ok!(
94+
try_likely_ok!(
95+
parsed.with_iso_year(year).ok_or(InvalidComponent("year"))
96+
)
97+
.with_iso_week_number(week)
98+
.ok_or(InvalidComponent("week"))
99+
)
93100
.with_weekday(weekday)
94-
.ok_or(InvalidComponent("weekday"))?;
101+
.ok_or(InvalidComponent("weekday"))
102+
);
95103
return Ok(input);
96104
}
97105
Err((false, _err)) => {}
@@ -115,64 +123,77 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
115123
) -> impl FnMut(&[u8]) -> Result<&[u8], error::Parse> + use<'a, CONFIG> {
116124
move |mut input| {
117125
if date_is_present {
118-
input = ascii_char::<b'T'>(input)
119-
.ok_or(InvalidLiteral)?
120-
.into_inner();
126+
input =
127+
try_likely_ok!(ascii_char::<b'T'>(input).ok_or(InvalidLiteral)).into_inner();
121128
}
122129

123-
let ParsedItem(mut input, hour) = float(input).ok_or(InvalidComponent("hour"))?;
130+
let ParsedItem(mut input, hour) =
131+
try_likely_ok!(float(input).ok_or(InvalidComponent("hour")));
124132
match hour {
125-
(hour, None) => parsed.set_hour_24(hour).ok_or(InvalidComponent("hour"))?,
133+
(hour, None) => {
134+
try_likely_ok!(parsed.set_hour_24(hour).ok_or(InvalidComponent("hour")))
135+
}
126136
(hour, Some(fractional_part)) => {
127-
*parsed = parsed
128-
.with_hour_24(hour)
129-
.ok_or(InvalidComponent("hour"))?
130-
.with_minute((fractional_part * Second::per_t::<f64>(Minute)) as u8)
131-
.ok_or(InvalidComponent("minute"))?
132-
.with_second(
133-
(fractional_part * Second::per_t::<f64>(Hour)
134-
% Minute::per_t::<f64>(Hour)) as u8,
137+
*parsed = try_likely_ok!(
138+
try_likely_ok!(
139+
try_likely_ok!(
140+
try_likely_ok!(
141+
parsed.with_hour_24(hour).ok_or(InvalidComponent("hour"))
142+
)
143+
.with_minute((fractional_part * Second::per_t::<f64>(Minute)) as u8)
144+
.ok_or(InvalidComponent("minute"))
145+
)
146+
.with_second(
147+
(fractional_part * Second::per_t::<f64>(Hour)
148+
% Minute::per_t::<f64>(Hour))
149+
as u8,
150+
)
151+
.ok_or(InvalidComponent("second"))
135152
)
136-
.ok_or(InvalidComponent("second"))?
137153
.with_subsecond(
138154
(fractional_part * Nanosecond::per_t::<f64>(Hour)
139155
% Nanosecond::per_t::<f64>(Second))
140156
as u32,
141157
)
142-
.ok_or(InvalidComponent("subsecond"))?;
158+
.ok_or(InvalidComponent("subsecond"))
159+
);
143160
return Ok(input);
144161
}
145162
};
146163

147164
if let Some(ParsedItem(new_input, ())) = ascii_char::<b':'>(input) {
148-
extended_kind
149-
.coerce_extended()
150-
.ok_or(InvalidComponent("minute"))?;
165+
try_likely_ok!(
166+
extended_kind
167+
.coerce_extended()
168+
.ok_or(InvalidComponent("minute"))
169+
);
151170
input = new_input;
152171
};
153172

154173
let mut input = match float(input) {
155174
Some(ParsedItem(input, (minute, None))) => {
156175
extended_kind.coerce_basic();
157-
parsed
158-
.set_minute(minute)
159-
.ok_or(InvalidComponent("minute"))?;
176+
try_likely_ok!(parsed.set_minute(minute).ok_or(InvalidComponent("minute")));
160177
input
161178
}
162179
Some(ParsedItem(input, (minute, Some(fractional_part)))) => {
163180
// `None` is valid behavior, so don't error if this fails.
164181
extended_kind.coerce_basic();
165-
*parsed = parsed
166-
.with_minute(minute)
167-
.ok_or(InvalidComponent("minute"))?
168-
.with_second((fractional_part * Second::per_t::<f64>(Minute)) as u8)
169-
.ok_or(InvalidComponent("second"))?
182+
*parsed = try_likely_ok!(
183+
try_likely_ok!(
184+
try_likely_ok!(
185+
parsed.with_minute(minute).ok_or(InvalidComponent("minute"))
186+
)
187+
.with_second((fractional_part * Second::per_t::<f64>(Minute)) as u8)
188+
.ok_or(InvalidComponent("second"))
189+
)
170190
.with_subsecond(
171191
(fractional_part * Nanosecond::per_t::<f64>(Minute)
172192
% Nanosecond::per_t::<f64>(Second))
173193
as u32,
174194
)
175-
.ok_or(InvalidComponent("subsecond"))?;
195+
.ok_or(InvalidComponent("subsecond"))
196+
);
176197
return Ok(input);
177198
}
178199
// colon was present, so minutes are required
@@ -183,13 +204,15 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
183204
}
184205
None => {
185206
// Missing components are assumed to be zero.
186-
*parsed = parsed
187-
.with_minute(0)
188-
.ok_or(InvalidComponent("minute"))?
189-
.with_second(0)
190-
.ok_or(InvalidComponent("second"))?
207+
*parsed = try_likely_ok!(
208+
try_likely_ok!(
209+
try_likely_ok!(parsed.with_minute(0).ok_or(InvalidComponent("minute")))
210+
.with_second(0)
211+
.ok_or(InvalidComponent("second"))
212+
)
191213
.with_subsecond(0)
192-
.ok_or(InvalidComponent("subsecond"))?;
214+
.ok_or(InvalidComponent("subsecond"))
215+
);
193216
return Ok(input);
194217
}
195218
};
@@ -198,11 +221,11 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
198221
match ascii_char::<b':'>(input) {
199222
Some(ParsedItem(new_input, ())) => input = new_input,
200223
None => {
201-
*parsed = parsed
202-
.with_second(0)
203-
.ok_or(InvalidComponent("second"))?
204-
.with_subsecond(0)
205-
.ok_or(InvalidComponent("subsecond"))?;
224+
*parsed = try_likely_ok!(
225+
try_likely_ok!(parsed.with_second(0).ok_or(InvalidComponent("second")))
226+
.with_subsecond(0)
227+
.ok_or(InvalidComponent("subsecond"))
228+
);
206229
return Ok(input);
207230
}
208231
}
@@ -223,11 +246,11 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
223246
// Missing components are assumed to be zero.
224247
None => (input, 0, 0),
225248
};
226-
*parsed = parsed
227-
.with_second(second)
228-
.ok_or(InvalidComponent("second"))?
229-
.with_subsecond(subsecond)
230-
.ok_or(InvalidComponent("subsecond"))?;
249+
*parsed = try_likely_ok!(
250+
try_likely_ok!(parsed.with_second(second).ok_or(InvalidComponent("second")))
251+
.with_subsecond(subsecond)
252+
.ok_or(InvalidComponent("subsecond"))
253+
);
231254

232255
Ok(input)
233256
}
@@ -243,46 +266,59 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
243266
) -> impl FnMut(&[u8]) -> Result<&[u8], error::Parse> + use<'a, CONFIG> {
244267
move |input| {
245268
if let Some(ParsedItem(input, ())) = ascii_char::<b'Z'>(input) {
246-
*parsed = parsed
247-
.with_offset_hour(0)
248-
.ok_or(InvalidComponent("offset hour"))?
249-
.with_offset_minute_signed(0)
250-
.ok_or(InvalidComponent("offset minute"))?
269+
*parsed = try_likely_ok!(
270+
try_likely_ok!(
271+
try_likely_ok!(
272+
parsed
273+
.with_offset_hour(0)
274+
.ok_or(InvalidComponent("offset hour"))
275+
)
276+
.with_offset_minute_signed(0)
277+
.ok_or(InvalidComponent("offset minute"))
278+
)
251279
.with_offset_second_signed(0)
252-
.ok_or(InvalidComponent("offset second"))?;
280+
.ok_or(InvalidComponent("offset second"))
281+
);
253282
return Ok(input);
254283
}
255284

256-
let ParsedItem(input, sign) = sign(input).ok_or(InvalidComponent("offset hour"))?;
257-
let mut input = hour(input)
258-
.and_then(|parsed_item| {
259-
parsed_item.consume_value(|hour| {
260-
parsed.set_offset_hour(match sign {
261-
Sign::Negative => -hour.cast_signed(),
262-
Sign::Positive => hour.cast_signed(),
285+
let ParsedItem(input, sign) =
286+
try_likely_ok!(sign(input).ok_or(InvalidComponent("offset hour")));
287+
let mut input = try_likely_ok!(
288+
hour(input)
289+
.and_then(|parsed_item| {
290+
parsed_item.consume_value(|hour| {
291+
parsed.set_offset_hour(match sign {
292+
Sign::Negative => -hour.cast_signed(),
293+
Sign::Positive => hour.cast_signed(),
294+
})
263295
})
264296
})
265-
})
266-
.ok_or(InvalidComponent("offset hour"))?;
297+
.ok_or(InvalidComponent("offset hour"))
298+
);
267299

268300
if extended_kind.maybe_extended()
269301
&& let Some(ParsedItem(new_input, ())) = ascii_char::<b':'>(input)
270302
{
271-
extended_kind
272-
.coerce_extended()
273-
.ok_or(InvalidComponent("offset minute"))?;
303+
try_likely_ok!(
304+
extended_kind
305+
.coerce_extended()
306+
.ok_or(InvalidComponent("offset minute"))
307+
);
274308
input = new_input;
275309
};
276310

277311
match min(input) {
278312
Some(ParsedItem(new_input, min)) => {
279313
input = new_input;
280-
parsed
281-
.set_offset_minute_signed(match sign {
282-
Sign::Negative => -min.cast_signed(),
283-
Sign::Positive => min.cast_signed(),
284-
})
285-
.ok_or(InvalidComponent("offset minute"))?;
314+
try_likely_ok!(
315+
parsed
316+
.set_offset_minute_signed(match sign {
317+
Sign::Negative => -min.cast_signed(),
318+
Sign::Positive => min.cast_signed(),
319+
})
320+
.ok_or(InvalidComponent("offset minute"))
321+
);
286322
}
287323
None => {
288324
// Omitted offset minute is assumed to be zero.

0 commit comments

Comments
 (0)