@@ -2,101 +2,75 @@ pub(crate) mod function {
2
2
use bstr:: ByteSlice ;
3
3
use btoi:: btoi;
4
4
use gix_date:: { time:: Sign , OffsetInSeconds , SecondsSinceUnixEpoch , Time } ;
5
- use nom :: multi :: many1_count ;
6
- use nom :: {
7
- branch :: alt ,
8
- bytes :: complete :: { tag , take , take_until , take_while_m_n } ,
9
- character :: is_digit ,
10
- error :: { context , ContextError , ParseError } ,
11
- sequence :: { terminated , tuple } ,
12
- IResult ,
5
+ use winnow :: {
6
+ combinator :: alt ,
7
+ combinator :: separated_pair ,
8
+ combinator :: terminated ,
9
+ error :: { AddContext , ParserError , StrContext } ,
10
+ prelude :: * ,
11
+ stream :: AsChar ,
12
+ token :: { take , take_until0 , take_while } ,
13
13
} ;
14
- use std:: cell:: RefCell ;
15
14
16
15
use crate :: { IdentityRef , SignatureRef } ;
17
16
18
17
const SPACE : & [ u8 ] = b" " ;
19
18
20
19
/// Parse a signature from the bytes input `i` using `nom`.
21
- pub fn decode < ' a , E : ParseError < & ' a [ u8 ] > + ContextError < & ' a [ u8 ] > > (
22
- i : & ' a [ u8 ] ,
23
- ) -> IResult < & ' a [ u8 ] , SignatureRef < ' a > , E > {
24
- use nom:: Parser ;
25
- let tzsign = RefCell :: new ( b'-' ) ; // TODO: there should be no need for this.
26
- let ( i, ( identity, _, time, _tzsign_count, hours, minutes) ) = context (
27
- "<name> <<email>> <timestamp> <+|-><HHMM>" ,
28
- tuple ( (
29
- identity,
30
- tag ( b" " ) ,
31
- context ( "<timestamp>" , |i| {
32
- terminated ( take_until ( SPACE ) , take ( 1usize ) ) ( i) . and_then ( |( i, v) | {
33
- btoi :: < SecondsSinceUnixEpoch > ( v)
34
- . map ( |v| ( i, v) )
35
- . map_err ( |_| nom:: Err :: Error ( E :: from_error_kind ( i, nom:: error:: ErrorKind :: MapRes ) ) )
36
- } )
20
+ pub fn decode < ' a , E : ParserError < & ' a [ u8 ] > + AddContext < & ' a [ u8 ] , StrContext > > (
21
+ i : & mut & ' a [ u8 ] ,
22
+ ) -> PResult < SignatureRef < ' a > , E > {
23
+ separated_pair (
24
+ identity,
25
+ b" " ,
26
+ (
27
+ terminated ( take_until0 ( SPACE ) , take ( 1usize ) )
28
+ . verify_map ( |v| btoi :: < SecondsSinceUnixEpoch > ( v) . ok ( ) )
29
+ . context ( StrContext :: Expected ( "<timestamp>" . into ( ) ) ) ,
30
+ alt ( (
31
+ take_while ( 1 .., b'-' ) . map ( |_| Sign :: Minus ) ,
32
+ take_while ( 1 .., b'+' ) . map ( |_| Sign :: Plus ) ,
33
+ ) )
34
+ . context ( StrContext :: Expected ( "+|-" . into ( ) ) ) ,
35
+ take_while ( 2 , AsChar :: is_dec_digit)
36
+ . verify_map ( |v| btoi :: < OffsetInSeconds > ( v) . ok ( ) )
37
+ . context ( StrContext :: Expected ( "HH" . into ( ) ) ) ,
38
+ take_while ( 1 ..=2 , AsChar :: is_dec_digit)
39
+ . verify_map ( |v| btoi :: < OffsetInSeconds > ( v) . ok ( ) )
40
+ . context ( StrContext :: Expected ( "MM" . into ( ) ) ) ,
41
+ )
42
+ . map ( |( time, sign, hours, minutes) | {
43
+ let offset = ( hours * 3600 + minutes * 60 ) * if sign == Sign :: Minus { -1 } else { 1 } ;
44
+ Time {
45
+ seconds : time,
46
+ offset,
47
+ sign,
48
+ }
37
49
} ) ,
38
- context (
39
- "+|-" ,
40
- alt ( (
41
- many1_count ( tag ( b"-" ) ) . map ( |_| * tzsign. borrow_mut ( ) = b'-' ) , // TODO: this should be a non-allocating consumer of consecutive tags
42
- many1_count ( tag ( b"+" ) ) . map ( |_| * tzsign. borrow_mut ( ) = b'+' ) ,
43
- ) ) ,
44
- ) ,
45
- context ( "HH" , |i| {
46
- take_while_m_n ( 2usize , 2 , is_digit) ( i) . and_then ( |( i, v) | {
47
- btoi :: < OffsetInSeconds > ( v)
48
- . map ( |v| ( i, v) )
49
- . map_err ( |_| nom:: Err :: Error ( E :: from_error_kind ( i, nom:: error:: ErrorKind :: MapRes ) ) )
50
- } )
51
- } ) ,
52
- context ( "MM" , |i| {
53
- take_while_m_n ( 1usize , 2 , is_digit) ( i) . and_then ( |( i, v) | {
54
- btoi :: < OffsetInSeconds > ( v)
55
- . map ( |v| ( i, v) )
56
- . map_err ( |_| nom:: Err :: Error ( E :: from_error_kind ( i, nom:: error:: ErrorKind :: MapRes ) ) )
57
- } )
58
- } ) ,
59
- ) ) ,
60
- ) ( i) ?;
61
-
62
- let tzsign = tzsign. into_inner ( ) ;
63
- debug_assert ! ( tzsign == b'-' || tzsign == b'+' , "parser assure it's +|- only" ) ;
64
- let sign = if tzsign == b'-' { Sign :: Minus } else { Sign :: Plus } ; //
65
- let offset = ( hours * 3600 + minutes * 60 ) * if sign == Sign :: Minus { -1 } else { 1 } ;
66
-
67
- Ok ( (
68
- i,
69
- SignatureRef {
70
- name : identity. name ,
71
- email : identity. email ,
72
- time : Time {
73
- seconds : time,
74
- offset,
75
- sign,
76
- } ,
77
- } ,
78
- ) )
50
+ )
51
+ . context ( StrContext :: Expected ( "<name> <<email>> <timestamp> <+|-><HHMM>" . into ( ) ) )
52
+ . map ( |( identity, time) | SignatureRef {
53
+ name : identity. name ,
54
+ email : identity. email ,
55
+ time,
56
+ } )
57
+ . parse_next ( i)
79
58
}
80
59
81
60
/// Parse an identity from the bytes input `i` (like `name <email>`) using `nom`.
82
- pub fn identity < ' a , E : ParseError < & ' a [ u8 ] > + ContextError < & ' a [ u8 ] > > (
83
- i : & ' a [ u8 ] ,
84
- ) -> IResult < & ' a [ u8 ] , IdentityRef < ' a > , E > {
85
- let ( i, ( name, email) ) = context (
86
- "<name> <<email>>" ,
87
- tuple ( (
88
- context ( "<name>" , terminated ( take_until ( & b" <" [ ..] ) , take ( 2usize ) ) ) ,
89
- context ( "<email>" , terminated ( take_until ( & b">" [ ..] ) , take ( 1usize ) ) ) ,
90
- ) ) ,
91
- ) ( i) ?;
92
-
93
- Ok ( (
94
- i,
95
- IdentityRef {
61
+ pub fn identity < ' a , E : ParserError < & ' a [ u8 ] > + AddContext < & ' a [ u8 ] , StrContext > > (
62
+ i : & mut & ' a [ u8 ] ,
63
+ ) -> PResult < IdentityRef < ' a > , E > {
64
+ (
65
+ terminated ( take_until0 ( & b" <" [ ..] ) , take ( 2usize ) ) . context ( StrContext :: Expected ( "<name>" . into ( ) ) ) ,
66
+ terminated ( take_until0 ( & b">" [ ..] ) , take ( 1usize ) ) . context ( StrContext :: Expected ( "<email>" . into ( ) ) ) ,
67
+ )
68
+ . map ( |( name, email) : ( & [ u8 ] , & [ u8 ] ) | IdentityRef {
96
69
name : name. as_bstr ( ) ,
97
70
email : email. as_bstr ( ) ,
98
- } ,
99
- ) )
71
+ } )
72
+ . context ( StrContext :: Expected ( "<name> <<email>>" . into ( ) ) )
73
+ . parse_next ( i)
100
74
}
101
75
}
102
76
pub use function:: identity;
@@ -107,12 +81,14 @@ mod tests {
107
81
use bstr:: ByteSlice ;
108
82
use gix_date:: { time:: Sign , OffsetInSeconds , SecondsSinceUnixEpoch } ;
109
83
use gix_testtools:: to_bstr_err;
110
- use nom :: IResult ;
84
+ use winnow :: prelude :: * ;
111
85
112
86
use crate :: { signature, SignatureRef , Time } ;
113
87
114
- fn decode ( i : & [ u8 ] ) -> IResult < & [ u8 ] , SignatureRef < ' _ > , nom:: error:: VerboseError < & [ u8 ] > > {
115
- signature:: decode ( i)
88
+ fn decode < ' i > (
89
+ i : & mut & ' i [ u8 ] ,
90
+ ) -> PResult < SignatureRef < ' i > , winnow:: error:: TreeError < & ' i [ u8 ] , winnow:: error:: StrContext > > {
91
+ signature:: decode. parse_next ( i)
116
92
}
117
93
118
94
fn signature (
@@ -132,7 +108,8 @@ mod tests {
132
108
#[ test]
133
109
fn tz_minus ( ) {
134
110
assert_eq ! (
135
- decode
( b"Sebastian Thiel <[email protected] > 1528473343 -0230" )
111
+ decode
112
+ . parse_peek
( b"Sebastian Thiel <[email protected] > 1528473343 -0230" )
136
113
. expect( "parse to work" )
137
114
. 1 ,
138
115
signature
( "Sebastian Thiel" , "[email protected] " , 1528473343 , Sign :: Minus , -
9000 )
@@ -142,7 +119,8 @@ mod tests {
142
119
#[ test]
143
120
fn tz_plus ( ) {
144
121
assert_eq ! (
145
- decode
( b"Sebastian Thiel <[email protected] > 1528473343 +0230" )
122
+ decode
123
+ . parse_peek
( b"Sebastian Thiel <[email protected] > 1528473343 +0230" )
146
124
. expect( "parse to work" )
147
125
. 1 ,
148
126
signature
( "Sebastian Thiel" , "[email protected] " , 1528473343 , Sign :: Plus , 9000 )
@@ -152,7 +130,8 @@ mod tests {
152
130
#[ test]
153
131
fn negative_offset_0000 ( ) {
154
132
assert_eq ! (
155
- decode
( b"Sebastian Thiel <[email protected] > 1528473343 -0000" )
133
+ decode
134
+ . parse_peek
( b"Sebastian Thiel <[email protected] > 1528473343 -0000" )
156
135
. expect( "parse to work" )
157
136
. 1 ,
158
137
signature
( "Sebastian Thiel" , "[email protected] " , 1528473343 , Sign :: Minus , 0 )
@@ -162,7 +141,8 @@ mod tests {
162
141
#[ test]
163
142
fn negative_offset_double_dash ( ) {
164
143
assert_eq ! (
165
- decode
( b"name <[email protected] > 1288373970 --700" )
144
+ decode
145
+ . parse_peek
( b"name <[email protected] > 1288373970 --700" )
166
146
. expect( "parse to work" )
167
147
. 1 ,
168
148
signature
( "name" , "[email protected] " , 1288373970 , Sign :: Minus , -
252000 )
@@ -172,30 +152,30 @@ mod tests {
172
152
#[ test]
173
153
fn empty_name_and_email ( ) {
174
154
assert_eq ! (
175
- decode( b" <> 12345 -1215" ) . expect( "parse to work" ) . 1 ,
155
+ decode. parse_peek ( b" <> 12345 -1215" ) . expect( "parse to work" ) . 1 ,
176
156
signature( "" , "" , 12345 , Sign :: Minus , -44100 )
177
157
) ;
178
158
}
179
159
180
160
#[ test]
181
161
fn invalid_signature ( ) {
182
162
assert_eq ! (
183
- decode( b"hello < 12345 -1215" )
163
+ decode. parse_peek ( b"hello < 12345 -1215" )
184
164
. map_err( to_bstr_err)
185
165
. expect_err( "parse fails as > is missing" )
186
166
. to_string( ) ,
187
- "Parse error: \n TakeUntil at: 12345 -1215\n in section ' <email>', at: 12345 -1215\n in section ' <name> <<email>>', at: hello < 12345 -1215\n in section ' <name> <<email>> <timestamp> <+|-><HHMM>', at: hello < 12345 -1215\n "
167
+ "in slice at ' 12345 -1215' \n 0: expected ` <email>` at ' 12345 -1215' \n 1: expected ` <name> <<email>>` at ' 12345 -1215' \n 2: expected ` <name> <<email>> <timestamp> <+|-><HHMM>` at ' 12345 -1215' \n "
188
168
) ;
189
169
}
190
170
191
171
#[ test]
192
172
fn invalid_time ( ) {
193
173
assert_eq ! (
194
- decode( b"hello <> abc -1215" )
174
+ decode. parse_peek ( b"hello <> abc -1215" )
195
175
. map_err( to_bstr_err)
196
176
. expect_err( "parse fails as > is missing" )
197
177
. to_string( ) ,
198
- "Parse error: \n MapRes at: -1215\n in section ' <timestamp>', at: abc -1215\n in section ' <name> <<email>> <timestamp> <+|-><HHMM>', at: hello <> abc -1215\n "
178
+ "in predicate verification at 'abc -1215' \n 0: expected ` <timestamp>` at ' abc -1215' \n 1: expected ` <name> <<email>> <timestamp> <+|-><HHMM>` at ' abc -1215' \n "
199
179
) ;
200
180
}
201
181
}
0 commit comments