@@ -34,34 +34,33 @@ mod relative;
3434mod time;
3535mod weekday;
3636mod 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}
4444mod 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
5353use chrono:: NaiveDate ;
5454use 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 } ;
5957use 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
6766use crate :: ParseDateTimeError ;
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 >
9796where
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 >
114113where
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 >
131130where
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