Skip to content

Commit bea8ec2

Browse files
committed
upgrade winnow to 0.7.10
1 parent 852e49e commit bea8ec2

File tree

9 files changed

+141
-120
lines changed

9 files changed

+141
-120
lines changed

Cargo.lock

+2-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@ readme = "README.md"
1010
[dependencies]
1111
regex = "1.10.4"
1212
chrono = { version="0.4.38", default-features=false, features=["std", "alloc", "clock"] }
13-
nom = "8.0.0"
14-
winnow = "0.5.34"
13+
winnow = "0.7.10"
1514
num-traits = "0.2.19"

src/items/combined.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
//! > seconds are allowed, with either comma or period preceding the fraction.
1414
//! > ISO 8601 fractional minutes and hours are not supported. Typically, hosts
1515
//! > support nanosecond timestamp resolution; excess precision is silently discarded.
16-
use winnow::{combinator::alt, seq, trace::trace, PResult, Parser};
16+
use winnow::{
17+
combinator::{alt, trace},
18+
seq, ModalResult, Parser,
19+
};
1720

1821
use crate::items::space;
1922

@@ -29,7 +32,7 @@ pub struct DateTime {
2932
pub(crate) time: Time,
3033
}
3134

32-
pub fn parse(input: &mut &str) -> PResult<DateTime> {
35+
pub fn parse(input: &mut &str) -> ModalResult<DateTime> {
3336
seq!(DateTime {
3437
date: trace("date iso", alt((date::iso1, date::iso2))),
3538
// Note: the `T` is lowercased by the main parse function

src/items/date.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,15 @@
2727
//! > ‘September’.
2828
2929
use winnow::{
30-
ascii::{alpha1, dec_uint},
31-
combinator::{alt, opt, preceded},
30+
ascii::alpha1,
31+
combinator::{alt, opt, preceded, trace},
3232
seq,
3333
stream::AsChar,
3434
token::{take, take_while},
35-
trace::trace,
36-
PResult, Parser,
35+
ModalResult, Parser,
3736
};
3837

39-
use super::s;
38+
use super::{dec_uint, s};
4039
use crate::ParseDateTimeError;
4140

4241
#[derive(PartialEq, Eq, Clone, Debug, Default)]
@@ -46,14 +45,14 @@ pub struct Date {
4645
pub year: Option<u32>,
4746
}
4847

49-
pub fn parse(input: &mut &str) -> PResult<Date> {
48+
pub fn parse(input: &mut &str) -> ModalResult<Date> {
5049
alt((iso1, iso2, us, literal1, literal2)).parse_next(input)
5150
}
5251

5352
/// Parse `YYYY-MM-DD` or `YY-MM-DD`
5453
///
5554
/// This is also used by [`combined`](super::combined).
56-
pub fn iso1(input: &mut &str) -> PResult<Date> {
55+
pub fn iso1(input: &mut &str) -> ModalResult<Date> {
5756
seq!(Date {
5857
year: year.map(Some),
5958
_: s('-'),
@@ -67,7 +66,7 @@ pub fn iso1(input: &mut &str) -> PResult<Date> {
6766
/// Parse `YYYYMMDD`
6867
///
6968
/// This is also used by [`combined`](super::combined).
70-
pub fn iso2(input: &mut &str) -> PResult<Date> {
69+
pub fn iso2(input: &mut &str) -> ModalResult<Date> {
7170
s((
7271
take(4usize).try_map(|s: &str| s.parse::<u32>()),
7372
take(2usize).try_map(|s: &str| s.parse::<u32>()),
@@ -82,7 +81,7 @@ pub fn iso2(input: &mut &str) -> PResult<Date> {
8281
}
8382

8483
/// Parse `MM/DD/YYYY`, `MM/DD/YY` or `MM/DD`
85-
fn us(input: &mut &str) -> PResult<Date> {
84+
fn us(input: &mut &str) -> ModalResult<Date> {
8685
seq!(Date {
8786
month: month,
8887
_: s('/'),
@@ -93,7 +92,7 @@ fn us(input: &mut &str) -> PResult<Date> {
9392
}
9493

9594
/// Parse `14 November 2022`, `14 Nov 2022`, "14nov2022", "14-nov-2022", "14-nov2022", "14nov-2022"
96-
fn literal1(input: &mut &str) -> PResult<Date> {
95+
fn literal1(input: &mut &str) -> ModalResult<Date> {
9796
seq!(Date {
9897
day: day,
9998
_: opt(s('-')),
@@ -104,7 +103,7 @@ fn literal1(input: &mut &str) -> PResult<Date> {
104103
}
105104

106105
/// Parse `November 14, 2022` and `Nov 14, 2022`
107-
fn literal2(input: &mut &str) -> PResult<Date> {
106+
fn literal2(input: &mut &str) -> ModalResult<Date> {
108107
seq!(Date {
109108
month: literal_month,
110109
day: day,
@@ -115,7 +114,7 @@ fn literal2(input: &mut &str) -> PResult<Date> {
115114
.parse_next(input)
116115
}
117116

118-
pub fn year(input: &mut &str) -> PResult<u32> {
117+
pub fn year(input: &mut &str) -> ModalResult<u32> {
119118
// 2147485547 is the maximum value accepted
120119
// by GNU, but chrono only behaves like GNU
121120
// for years in the range: [0, 9999], so we
@@ -140,7 +139,7 @@ pub fn year(input: &mut &str) -> PResult<u32> {
140139
.parse_next(input)
141140
}
142141

143-
fn month(input: &mut &str) -> PResult<u32> {
142+
fn month(input: &mut &str) -> ModalResult<u32> {
144143
s(dec_uint)
145144
.try_map(|x| {
146145
(1..=12)
@@ -151,7 +150,7 @@ fn month(input: &mut &str) -> PResult<u32> {
151150
.parse_next(input)
152151
}
153152

154-
fn day(input: &mut &str) -> PResult<u32> {
153+
fn day(input: &mut &str) -> ModalResult<u32> {
155154
s(dec_uint)
156155
.try_map(|x| {
157156
(1..=31)
@@ -163,7 +162,7 @@ fn day(input: &mut &str) -> PResult<u32> {
163162
}
164163

165164
/// Parse the name of a month (case-insensitive)
166-
fn literal_month(input: &mut &str) -> PResult<u32> {
165+
fn literal_month(input: &mut &str) -> ModalResult<u32> {
167166
s(alpha1)
168167
.verify_map(|s: &str| {
169168
Some(match s {

src/items/mod.rs

+75-42
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,33 @@ mod relative;
3434
mod time;
3535
mod weekday;
3636
mod epoch {
37-
use winnow::{ascii::dec_int, combinator::preceded, PResult, Parser};
37+
use winnow::{combinator::preceded, ModalResult, Parser};
3838

39-
use super::s;
40-
pub fn parse(input: &mut &str) -> PResult<i32> {
39+
use super::{dec_int, s};
40+
pub fn parse(input: &mut &str) -> ModalResult<i32> {
4141
s(preceded("@", dec_int)).parse_next(input)
4242
}
4343
}
4444
mod timezone {
4545
use super::time;
46-
use winnow::PResult;
46+
use winnow::ModalResult;
4747

48-
pub(crate) fn parse(input: &mut &str) -> PResult<time::Offset> {
48+
pub(crate) fn parse(input: &mut &str) -> ModalResult<time::Offset> {
4949
time::timezone(input)
5050
}
5151
}
5252

5353
use chrono::NaiveDate;
5454
use chrono::{DateTime, Datelike, FixedOffset, TimeZone, Timelike};
5555

56-
use winnow::error::{AddContext, ParserError, StrContext};
57-
use winnow::error::{ContextError, ErrMode};
58-
use winnow::trace::trace;
56+
use winnow::error::{StrContext, StrContextValue};
5957
use winnow::{
60-
ascii::multispace0,
61-
combinator::{alt, delimited, not, peek, preceded, repeat, separated},
58+
ascii::{digit1, multispace0},
59+
combinator::{alt, delimited, not, opt, peek, preceded, repeat, separated, trace},
60+
error::{ContextError, ErrMode, ParserError},
6261
stream::AsChar,
63-
token::{none_of, take_while},
64-
PResult, Parser,
62+
token::{none_of, one_of, take_while},
63+
ModalResult, Parser,
6564
};
6665

6766
use crate::ParseDateTimeError;
@@ -93,7 +92,7 @@ where
9392
/// Parse the space in-between tokens
9493
///
9594
/// You probably want to use the [`s`] combinator instead.
96-
fn space<'a, E>(input: &mut &'a str) -> PResult<(), E>
95+
fn space<'a, E>(input: &mut &'a str) -> winnow::Result<(), E>
9796
where
9897
E: ParserError<&'a str>,
9998
{
@@ -110,7 +109,7 @@ where
110109
/// The last comment should be ignored.
111110
///
112111
/// The plus is undocumented, but it seems to be ignored.
113-
fn ignored_hyphen_or_plus<'a, E>(input: &mut &'a str) -> PResult<(), E>
112+
fn ignored_hyphen_or_plus<'a, E>(input: &mut &'a str) -> winnow::Result<(), E>
114113
where
115114
E: ParserError<&'a str>,
116115
{
@@ -127,7 +126,7 @@ where
127126
///
128127
/// A comment is given between parentheses, which must be balanced. Any other
129128
/// tokens can be within the comment.
130-
fn comment<'a, E>(input: &mut &'a str) -> PResult<(), E>
129+
fn comment<'a, E>(input: &mut &'a str) -> winnow::Result<(), E>
131130
where
132131
E: ParserError<&'a str>,
133132
{
@@ -139,8 +138,45 @@ where
139138
.parse_next(input)
140139
}
141140

141+
/// Parse a signed decimal integer.
142+
///
143+
/// Rationale for not using `winnow::ascii::dec_int`: When upgrading winnow from
144+
/// 0.5 to 0.7, we discovered that `winnow::ascii::dec_int` now accepts only the
145+
/// following two forms:
146+
///
147+
/// - 0
148+
/// - [+-][1-9][0-9]*
149+
///
150+
/// Inputs like [+-]0[0-9]* (e.g., `+012`) are therefore rejected. We provide a
151+
/// custom implementation to support such zero-prefixed integers.
152+
fn dec_int<'a, E>(input: &mut &'a str) -> winnow::Result<i32, E>
153+
where
154+
E: ParserError<&'a str>,
155+
{
156+
(opt(one_of(['+', '-'])), digit1)
157+
.void()
158+
.take()
159+
.verify_map(|s: &str| s.parse().ok())
160+
.parse_next(input)
161+
}
162+
163+
/// Parse an unsigned decimal integer.
164+
///
165+
/// See the rationale for `dec_int` for why we don't use
166+
/// `winnow::ascii::dec_uint`.
167+
fn dec_uint<'a, E>(input: &mut &'a str) -> winnow::Result<u32, E>
168+
where
169+
E: ParserError<&'a str>,
170+
{
171+
digit1
172+
.void()
173+
.take()
174+
.verify_map(|s: &str| s.parse().ok())
175+
.parse_next(input)
176+
}
177+
142178
// Parse an item
143-
pub fn parse_one(input: &mut &str) -> PResult<Item> {
179+
pub fn parse_one(input: &mut &str) -> ModalResult<Item> {
144180
trace(
145181
"parse_one",
146182
alt((
@@ -157,7 +193,7 @@ pub fn parse_one(input: &mut &str) -> PResult<Item> {
157193
.parse_next(input)
158194
}
159195

160-
pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
196+
pub fn parse(input: &mut &str) -> ModalResult<Vec<Item>> {
161197
let mut items = Vec::new();
162198
let mut date_seen = false;
163199
let mut time_seen = false;
@@ -170,12 +206,13 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
170206
match item {
171207
Item::DateTime(ref dt) => {
172208
if date_seen || time_seen {
173-
return Err(ErrMode::Backtrack(ContextError::new().add_context(
174-
&input,
175-
StrContext::Expected(winnow::error::StrContextValue::Description(
209+
let mut ctx_err = ContextError::new();
210+
ctx_err.push(StrContext::Expected(
211+
winnow::error::StrContextValue::Description(
176212
"date or time cannot appear more than once",
177-
)),
178-
)));
213+
),
214+
));
215+
return Err(ErrMode::Backtrack(ctx_err));
179216
}
180217

181218
date_seen = true;
@@ -186,12 +223,11 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
186223
}
187224
Item::Date(ref d) => {
188225
if date_seen {
189-
return Err(ErrMode::Backtrack(ContextError::new().add_context(
190-
&input,
191-
StrContext::Expected(winnow::error::StrContextValue::Description(
192-
"date cannot appear more than once",
193-
)),
226+
let mut ctx_err = ContextError::new();
227+
ctx_err.push(StrContext::Expected(StrContextValue::Description(
228+
"date cannot appear more than once",
194229
)));
230+
return Err(ErrMode::Backtrack(ctx_err));
195231
}
196232

197233
date_seen = true;
@@ -201,34 +237,31 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
201237
}
202238
Item::Time(_) => {
203239
if time_seen {
204-
return Err(ErrMode::Backtrack(ContextError::new().add_context(
205-
&input,
206-
StrContext::Expected(winnow::error::StrContextValue::Description(
207-
"time cannot appear more than once",
208-
)),
240+
let mut ctx_err = ContextError::new();
241+
ctx_err.push(StrContext::Expected(StrContextValue::Description(
242+
"time cannot appear more than once",
209243
)));
244+
return Err(ErrMode::Backtrack(ctx_err));
210245
}
211246
time_seen = true;
212247
}
213248
Item::Year(_) => {
214249
if year_seen {
215-
return Err(ErrMode::Backtrack(ContextError::new().add_context(
216-
&input,
217-
StrContext::Expected(winnow::error::StrContextValue::Description(
218-
"year cannot appear more than once",
219-
)),
250+
let mut ctx_err = ContextError::new();
251+
ctx_err.push(StrContext::Expected(StrContextValue::Description(
252+
"year cannot appear more than once",
220253
)));
254+
return Err(ErrMode::Backtrack(ctx_err));
221255
}
222256
year_seen = true;
223257
}
224258
Item::TimeZone(_) => {
225259
if tz_seen {
226-
return Err(ErrMode::Backtrack(ContextError::new().add_context(
227-
&input,
228-
StrContext::Expected(winnow::error::StrContextValue::Description(
229-
"timezone cannot appear more than once",
230-
)),
260+
let mut ctx_err = ContextError::new();
261+
ctx_err.push(StrContext::Expected(StrContextValue::Description(
262+
"timezone cannot appear more than once",
231263
)));
264+
return Err(ErrMode::Backtrack(ctx_err));
232265
}
233266
tz_seen = true;
234267
}

0 commit comments

Comments
 (0)