Skip to content

Commit f06d41b

Browse files
Change ErrMode::Cut to ErrMode::Backtrack to allow alt parser flow
1 parent 29e3686 commit f06d41b

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

src/items/date.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ pub(super) fn parse(input: &mut &str) -> ModalResult<Date> {
135135
///
136136
/// This is also used by [`combined`](super::combined).
137137
pub(super) fn iso1(input: &mut &str) -> ModalResult<Date> {
138+
138139
let (year, _, month, _, day) =
139140
(year_str, s('-'), s(dec_uint), s('-'), s(dec_uint)).parse_next(input)?;
140141

142+
// Map err to Backtrack instead of Cut to avoid early termination of parsing
141143
(year, month, day)
142144
.try_into()
143-
.map_err(|e| ErrMode::Cut(ctx_err(e)))
145+
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
144146
}
145147

146148
/// Parse `[year][month][day]`
@@ -156,7 +158,7 @@ pub(super) fn iso2(input: &mut &str) -> ModalResult<Date> {
156158

157159
(year, month, day)
158160
.try_into()
159-
.map_err(|e| ErrMode::Cut(ctx_err(e)))
161+
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
160162
}
161163

162164
/// Parse `[year]/[month]/[day]` or `[month]/[day]/[year]` or `[month]/[day]`.
@@ -178,19 +180,19 @@ fn us(input: &mut &str) -> ModalResult<Date> {
178180
let day = day_from_str(s2)?;
179181
(s1, n, day)
180182
.try_into()
181-
.map_err(|e| ErrMode::Cut(ctx_err(e)))
183+
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
182184
}
183185
Some(s2) => {
184186
// [month]/[day]/[year]
185187
let month = month_from_str(s1)?;
186188
(s2, month, n)
187189
.try_into()
188-
.map_err(|e| ErrMode::Cut(ctx_err(e)))
190+
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
189191
}
190192
None => {
191193
// [month]/[day]
192194
let month = month_from_str(s1)?;
193-
(month, n).try_into().map_err(|e| ErrMode::Cut(ctx_err(e)))
195+
(month, n).try_into().map_err(|e| ErrMode::Backtrack(ctx_err(e)))
194196
}
195197
}
196198
}
@@ -213,10 +215,10 @@ fn literal1(input: &mut &str) -> ModalResult<Date> {
213215
match year {
214216
Some(year) => (year, month, day)
215217
.try_into()
216-
.map_err(|e| ErrMode::Cut(ctx_err(e))),
218+
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
217219
None => (month, day)
218220
.try_into()
219-
.map_err(|e| ErrMode::Cut(ctx_err(e))),
221+
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
220222
}
221223
}
222224

@@ -242,10 +244,10 @@ fn literal2(input: &mut &str) -> ModalResult<Date> {
242244
match year {
243245
Some(year) => (year, month, day)
244246
.try_into()
245-
.map_err(|e| ErrMode::Cut(ctx_err(e))),
247+
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
246248
None => (month, day)
247249
.try_into()
248-
.map_err(|e| ErrMode::Cut(ctx_err(e))),
250+
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
249251
}
250252
}
251253

@@ -274,12 +276,12 @@ fn literal_month(input: &mut &str) -> ModalResult<u8> {
274276

275277
fn month_from_str(s: &str) -> ModalResult<u8> {
276278
s.parse::<u8>()
277-
.map_err(|_| ErrMode::Cut(ctx_err("month must be a valid u8 number")))
279+
.map_err(|_| ErrMode::Backtrack(ctx_err("month must be a valid u8 number")))
278280
}
279281

280282
fn day_from_str(s: &str) -> ModalResult<u8> {
281283
s.parse::<u8>()
282-
.map_err(|_| ErrMode::Cut(ctx_err("day must be a valid u8 number")))
284+
.map_err(|_| ErrMode::Backtrack(ctx_err("day must be a valid u8 number")))
283285
}
284286

285287
#[cfg(test)]

tests/time.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,33 @@ fn test_time_invalid(#[case] input: &str) {
128128
"Input string '{input}' did not produce an error when parsing"
129129
);
130130
}
131+
132+
#[rstest]
133+
#[case::decimal_1_whole("1.123456789 seconds ago")]
134+
#[case::decimal_2_whole("12.123456789 seconds ago")]
135+
#[case::decimal_3_whole("123.123456789 seconds ago")]
136+
#[case::decimal_4_whole("1234.123456789 seconds ago")]
137+
#[case::decimal_5_whole("12345.123456789 seconds ago")]
138+
#[case::decimal_6_whole("123456.123456789 seconds ago")]
139+
#[case::decimal_7_whole("1234567.123456789 seconds ago")]
140+
#[case::decimal_8_whole("12345678.123456789 seconds ago")]
141+
#[case::decimal_9_whole("123456789.123456789 seconds ago")]
142+
#[case::decimal_10_whole("1234567891.123456789 seconds ago")]
143+
#[case::decimal_11_whole("12345678912.123456789 seconds ago")]
144+
#[case::decimal_12_whole("123456789123.123456789 seconds ago")]
145+
fn test_time_seconds_ago(#[case] input: &str) {
146+
let result = parse_datetime::parse_datetime(input);
147+
assert_eq!(result.is_ok(), true, "Input string '{input}', produced {result:?}, instead of Ok(Zoned)");
148+
}
149+
150+
#[rstest]
151+
#[case::decimal_13_whole("1234567891234.123456789 seconds ago")]
152+
#[case::decimal_14_whole("12345678912345.123456789 seconds ago")]
153+
#[case::decimal_15_whole("123456789123456.123456789 seconds ago")]
154+
fn test_time_seconds_ago_invalid(#[case] input: &str) {
155+
let result = parse_datetime::parse_datetime(input);
156+
assert_eq!(result,
157+
Err(parse_datetime::ParseDateTimeError::InvalidInput),
158+
"Input string '{input}' did not produce an error when parsing"
159+
);
160+
}

0 commit comments

Comments
 (0)