@@ -34,34 +34,33 @@ 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;
56
+ use winnow:: error:: { StrContext , StrContextValue } ;
59
57
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 } ,
62
61
stream:: AsChar ,
63
- token:: { none_of, take_while} ,
64
- PResult , Parser ,
62
+ token:: { none_of, one_of , take_while} ,
63
+ ModalResult , Parser ,
65
64
} ;
66
65
67
66
use crate :: ParseDateTimeError ;
93
92
/// Parse the space in-between tokens
94
93
///
95
94
/// 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 >
97
96
where
98
97
E : ParserError < & ' a str > ,
99
98
{
@@ -110,7 +109,7 @@ where
110
109
/// The last comment should be ignored.
111
110
///
112
111
/// 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 >
114
113
where
115
114
E : ParserError < & ' a str > ,
116
115
{
@@ -127,7 +126,7 @@ where
127
126
///
128
127
/// A comment is given between parentheses, which must be balanced. Any other
129
128
/// 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 >
131
130
where
132
131
E : ParserError < & ' a str > ,
133
132
{
@@ -139,8 +138,45 @@ where
139
138
. parse_next ( input)
140
139
}
141
140
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
+
142
178
// Parse an item
143
- pub fn parse_one ( input : & mut & str ) -> PResult < Item > {
179
+ pub fn parse_one ( input : & mut & str ) -> ModalResult < Item > {
144
180
trace (
145
181
"parse_one" ,
146
182
alt ( (
@@ -157,7 +193,7 @@ pub fn parse_one(input: &mut &str) -> PResult<Item> {
157
193
. parse_next ( input)
158
194
}
159
195
160
- pub fn parse ( input : & mut & str ) -> PResult < Vec < Item > > {
196
+ pub fn parse ( input : & mut & str ) -> ModalResult < Vec < Item > > {
161
197
let mut items = Vec :: new ( ) ;
162
198
let mut date_seen = false ;
163
199
let mut time_seen = false ;
@@ -170,12 +206,13 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
170
206
match item {
171
207
Item :: DateTime ( ref dt) => {
172
208
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 (
176
212
"date or time cannot appear more than once" ,
177
- ) ) ,
178
- ) ) ) ;
213
+ ) ,
214
+ ) ) ;
215
+ return Err ( ErrMode :: Backtrack ( ctx_err) ) ;
179
216
}
180
217
181
218
date_seen = true ;
@@ -186,12 +223,11 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
186
223
}
187
224
Item :: Date ( ref d) => {
188
225
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" ,
194
229
) ) ) ;
230
+ return Err ( ErrMode :: Backtrack ( ctx_err) ) ;
195
231
}
196
232
197
233
date_seen = true ;
@@ -201,34 +237,31 @@ pub fn parse(input: &mut &str) -> PResult<Vec<Item>> {
201
237
}
202
238
Item :: Time ( _) => {
203
239
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" ,
209
243
) ) ) ;
244
+ return Err ( ErrMode :: Backtrack ( ctx_err) ) ;
210
245
}
211
246
time_seen = true ;
212
247
}
213
248
Item :: Year ( _) => {
214
249
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" ,
220
253
) ) ) ;
254
+ return Err ( ErrMode :: Backtrack ( ctx_err) ) ;
221
255
}
222
256
year_seen = true ;
223
257
}
224
258
Item :: TimeZone ( _) => {
225
259
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" ,
231
263
) ) ) ;
264
+ return Err ( ErrMode :: Backtrack ( ctx_err) ) ;
232
265
}
233
266
tz_seen = true ;
234
267
}
0 commit comments