@@ -34,34 +34,32 @@ mod relative;
34
34
mod time;
35
35
mod weekday;
36
36
mod epoch {
37
- use winnow:: { ascii :: dec_int , combinator:: preceded, PResult , Parser } ;
37
+ use winnow:: { combinator:: preceded, ModalResult , Parser } ;
38
38
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 > {
41
41
s ( preceded ( "@" , dec_int) ) . parse_next ( input)
42
42
}
43
43
}
44
44
mod timezone {
45
45
use super :: time;
46
- use winnow:: PResult ;
46
+ use winnow:: ModalResult ;
47
47
48
- pub ( crate ) fn parse ( input : & mut & str ) -> PResult < time:: Offset > {
48
+ pub ( crate ) fn parse ( input : & mut & str ) -> ModalResult < time:: Offset > {
49
49
time:: timezone ( input)
50
50
}
51
51
}
52
52
53
53
use chrono:: NaiveDate ;
54
54
use chrono:: { DateTime , Datelike , FixedOffset , TimeZone , Timelike } ;
55
55
56
- use winnow:: error:: { AddContext , ParserError , StrContext } ;
57
- use winnow:: error:: { ContextError , ErrMode } ;
58
- use winnow:: trace:: trace;
59
56
use winnow:: {
60
- ascii:: multispace0,
61
- combinator:: { alt, delimited, not, peek, preceded, repeat, separated} ,
57
+ ascii:: { digit1, multispace0} ,
58
+ combinator:: { alt, delimited, not, opt, peek, preceded, repeat, separated, trace} ,
59
+ error:: { ContextError , ErrMode , ParserError } ,
62
60
stream:: AsChar ,
63
- token:: { none_of, take_while} ,
64
- PResult , Parser ,
61
+ token:: { none_of, one_of , take_while} ,
62
+ ModalResult , Parser ,
65
63
} ;
66
64
67
65
use crate :: ParseDateTimeError ;
93
91
/// Parse the space in-between tokens
94
92
///
95
93
/// You probably want to use the [`s`] combinator instead.
96
- fn space < ' a , E > ( input : & mut & ' a str ) -> PResult < ( ) , E >
94
+ fn space < ' a , E > ( input : & mut & ' a str ) -> winnow :: Result < ( ) , E >
97
95
where
98
96
E : ParserError < & ' a str > ,
99
97
{
@@ -110,7 +108,7 @@ where
110
108
/// The last comment should be ignored.
111
109
///
112
110
/// The plus is undocumented, but it seems to be ignored.
113
- fn ignored_hyphen_or_plus < ' a , E > ( input : & mut & ' a str ) -> PResult < ( ) , E >
111
+ fn ignored_hyphen_or_plus < ' a , E > ( input : & mut & ' a str ) -> winnow :: Result < ( ) , E >
114
112
where
115
113
E : ParserError < & ' a str > ,
116
114
{
@@ -127,7 +125,7 @@ where
127
125
///
128
126
/// A comment is given between parentheses, which must be balanced. Any other
129
127
/// tokens can be within the comment.
130
- fn comment < ' a , E > ( input : & mut & ' a str ) -> PResult < ( ) , E >
128
+ fn comment < ' a , E > ( input : & mut & ' a str ) -> winnow :: Result < ( ) , E >
131
129
where
132
130
E : ParserError < & ' a str > ,
133
131
{
@@ -139,8 +137,45 @@ where
139
137
. parse_next ( input)
140
138
}
141
139
140
+ /// Parse a signed decimal integer.
141
+ ///
142
+ /// Rationale for not using `winnow::ascii::dec_int`: When upgrading winnow from
143
+ /// 0.5 to 0.7, we discovered that `winnow::ascii::dec_int` now accepts only the
144
+ /// following two forms:
145
+ ///
146
+ /// - 0
147
+ /// - [+-][1-9][0-9]*
148
+ ///
149
+ /// Inputs like [+-]0[0-9]* (e.g., `+012`) are therefore rejected. We provide a
150
+ /// custom implementation to support such zero-prefixed integers.
151
+ fn dec_int < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < i32 , E >
152
+ where
153
+ E : ParserError < & ' a str > ,
154
+ {
155
+ ( opt ( one_of ( [ '+' , '-' ] ) ) , digit1)
156
+ . void ( )
157
+ . take ( )
158
+ . verify_map ( |s : & str | s. parse ( ) . ok ( ) )
159
+ . parse_next ( input)
160
+ }
161
+
162
+ /// Parse an unsigned decimal integer.
163
+ ///
164
+ /// See the rationale for `dec_int` for why we don't use
165
+ /// `winnow::ascii::dec_uint`.
166
+ fn dec_uint < ' a , E > ( input : & mut & ' a str ) -> winnow:: Result < u32 , E >
167
+ where
168
+ E : ParserError < & ' a str > ,
169
+ {
170
+ digit1
171
+ . void ( )
172
+ . take ( )
173
+ . verify_map ( |s : & str | s. parse ( ) . ok ( ) )
174
+ . parse_next ( input)
175
+ }
176
+
142
177
// Parse an item
143
- pub fn parse_one ( input : & mut & str ) -> PResult < Item > {
178
+ pub fn parse_one ( input : & mut & str ) -> ModalResult < Item > {
144
179
trace (
145
180
"parse_one" ,
146
181
alt ( (
@@ -157,7 +192,7 @@ pub fn parse_one(input: &mut &str) -> PResult<Item> {
157
192
. parse_next ( input)
158
193
}
159
194
160
- pub fn parse ( input : & mut & str ) -> PResult < Vec < Item > > {
195
+ pub fn parse ( input : & mut & str ) -> ModalResult < Vec < Item > > {
161
196
let mut items = Vec :: new ( ) ;
162
197
let mut date_seen = false ;
163
198
let mut time_seen = false ;
@@ -170,12 +205,7 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
170
205
match item {
171
206
Item :: DateTime ( ref dt) => {
172
207
if date_seen || time_seen {
173
- return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) . add_context (
174
- & input,
175
- StrContext :: Expected ( winnow:: error:: StrContextValue :: Description (
176
- "date or time cannot appear more than once" ,
177
- ) ) ,
178
- ) ) ) ;
208
+ return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) ) ) ;
179
209
}
180
210
181
211
date_seen = true ;
@@ -186,12 +216,7 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
186
216
}
187
217
Item :: Date ( ref d) => {
188
218
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
- ) ) ,
194
- ) ) ) ;
219
+ return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) ) ) ;
195
220
}
196
221
197
222
date_seen = true ;
@@ -201,34 +226,19 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
201
226
}
202
227
Item :: Time ( _) => {
203
228
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
- ) ) ,
209
- ) ) ) ;
229
+ return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) ) ) ;
210
230
}
211
231
time_seen = true ;
212
232
}
213
233
Item :: Year ( _) => {
214
234
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
- ) ) ,
220
- ) ) ) ;
235
+ return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) ) ) ;
221
236
}
222
237
year_seen = true ;
223
238
}
224
239
Item :: TimeZone ( _) => {
225
240
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
- ) ) ,
231
- ) ) ) ;
241
+ return Err ( ErrMode :: Backtrack ( ContextError :: new ( ) ) ) ;
232
242
}
233
243
tz_seen = true ;
234
244
}
0 commit comments