66#[ cfg( test) ]
77mod tests;
88
9+ use crate :: convert:: TryInto as _;
910use crate :: error:: Error ;
1011use crate :: fmt;
1112use crate :: net:: { IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr , SocketAddrV4 , SocketAddrV6 } ;
1213use crate :: str:: FromStr ;
1314
15+ trait ReadNumberHelper : crate :: marker:: Sized {
16+ const ZERO : Self ;
17+ fn checked_mul ( & self , other : u32 ) -> Option < Self > ;
18+ fn checked_add ( & self , other : u32 ) -> Option < Self > ;
19+ }
20+
21+ macro_rules! impl_helper {
22+ ( $( $t: ty) * ) => ( $( impl ReadNumberHelper for $t {
23+ const ZERO : Self = 0 ;
24+ #[ inline]
25+ fn checked_mul( & self , other: u32 ) -> Option <Self > {
26+ Self :: checked_mul( * self , other. try_into( ) . ok( ) ?)
27+ }
28+ #[ inline]
29+ fn checked_add( & self , other: u32 ) -> Option <Self > {
30+ Self :: checked_add( * self , other. try_into( ) . ok( ) ?)
31+ }
32+ } ) * )
33+ }
34+
35+ impl_helper ! { u8 u16 }
36+
1437struct Parser < ' a > {
1538 // parsing as ASCII, so can use byte array
1639 state : & ' a [ u8 ] ,
@@ -21,10 +44,6 @@ impl<'a> Parser<'a> {
2144 Parser { state : input. as_bytes ( ) }
2245 }
2346
24- fn is_eof ( & self ) -> bool {
25- self . state . is_empty ( )
26- }
27-
2847 /// Run a parser, and restore the pre-parse state if it fails
2948 fn read_atomically < T , F > ( & mut self , inner : F ) -> Option < T >
3049 where
@@ -40,26 +59,19 @@ impl<'a> Parser<'a> {
4059
4160 /// Run a parser, but fail if the entire input wasn't consumed.
4261 /// Doesn't run atomically.
43- fn read_till_eof < T , F > ( & mut self , inner : F ) -> Option < T >
44- where
45- F : FnOnce ( & mut Parser < ' _ > ) -> Option < T > ,
46- {
47- inner ( self ) . filter ( |_| self . is_eof ( ) )
48- }
49-
50- /// Same as read_till_eof, but returns a Result<AddrParseError> on failure
5162 fn parse_with < T , F > ( & mut self , inner : F ) -> Result < T , AddrParseError >
5263 where
5364 F : FnOnce ( & mut Parser < ' _ > ) -> Option < T > ,
5465 {
55- self . read_till_eof ( inner) . ok_or ( AddrParseError ( ( ) ) )
66+ let result = inner ( self ) ;
67+ if self . state . is_empty ( ) { result } else { None } . ok_or ( AddrParseError ( ( ) ) )
5668 }
5769
5870 /// Read the next character from the input
5971 fn read_char ( & mut self ) -> Option < char > {
6072 self . state . split_first ( ) . map ( |( & b, tail) | {
6173 self . state = tail;
62- b as char
74+ char:: from ( b )
6375 } )
6476 }
6577
@@ -84,25 +96,26 @@ impl<'a> Parser<'a> {
8496 } )
8597 }
8698
87- // Read a single digit in the given radix. For instance, 0-9 in radix 10;
88- // 0-9A-F in radix 16.
89- fn read_digit ( & mut self , radix : u32 ) -> Option < u32 > {
90- self . read_atomically ( move |p| p. read_char ( ) ?. to_digit ( radix) )
91- }
92-
9399 // Read a number off the front of the input in the given radix, stopping
94100 // at the first non-digit character or eof. Fails if the number has more
95- // digits than max_digits, or the value is >= upto, or if there is no number.
96- fn read_number ( & mut self , radix : u32 , max_digits : u32 , upto : u32 ) -> Option < u32 > {
101+ // digits than max_digits or if there is no number.
102+ fn read_number < T : ReadNumberHelper > (
103+ & mut self ,
104+ radix : u32 ,
105+ max_digits : Option < usize > ,
106+ ) -> Option < T > {
97107 self . read_atomically ( move |p| {
98- let mut result = 0 ;
108+ let mut result = T :: ZERO ;
99109 let mut digit_count = 0 ;
100110
101- while let Some ( digit) = p. read_digit ( radix) {
102- result = ( result * radix) + digit;
111+ while let Some ( digit) = p. read_atomically ( |p| p. read_char ( ) ?. to_digit ( radix) ) {
112+ result = result. checked_mul ( radix) ?;
113+ result = result. checked_add ( digit) ?;
103114 digit_count += 1 ;
104- if digit_count > max_digits || result >= upto {
105- return None ;
115+ if let Some ( max_digits) = max_digits {
116+ if digit_count > max_digits {
117+ return None ;
118+ }
106119 }
107120 }
108121
@@ -116,7 +129,7 @@ impl<'a> Parser<'a> {
116129 let mut groups = [ 0 ; 4 ] ;
117130
118131 for ( i, slot) in groups. iter_mut ( ) . enumerate ( ) {
119- * slot = p. read_separator ( '.' , i, |p| p. read_number ( 10 , 3 , 0x100 ) ) ? as u8 ;
132+ * slot = p. read_separator ( '.' , i, |p| p. read_number ( 10 , None ) ) ?;
120133 }
121134
122135 Some ( groups. into ( ) )
@@ -140,17 +153,17 @@ impl<'a> Parser<'a> {
140153 let ipv4 = p. read_separator ( ':' , i, |p| p. read_ipv4_addr ( ) ) ;
141154
142155 if let Some ( v4_addr) = ipv4 {
143- let octets = v4_addr. octets ( ) ;
144- groups[ i + 0 ] = ( ( octets [ 0 ] as u16 ) << 8 ) | ( octets [ 1 ] as u16 ) ;
145- groups[ i + 1 ] = ( ( octets [ 2 ] as u16 ) << 8 ) | ( octets [ 3 ] as u16 ) ;
156+ let [ one , two , three , four ] = v4_addr. octets ( ) ;
157+ groups[ i + 0 ] = u16:: from_be_bytes ( [ one , two ] ) ;
158+ groups[ i + 1 ] = u16:: from_be_bytes ( [ three , four ] ) ;
146159 return ( i + 2 , true ) ;
147160 }
148161 }
149162
150- let group = p. read_separator ( ':' , i, |p| p. read_number ( 16 , 4 , 0x10000 ) ) ;
163+ let group = p. read_separator ( ':' , i, |p| p. read_number ( 16 , Some ( 4 ) ) ) ;
151164
152165 match group {
153- Some ( g) => * slot = g as u16 ,
166+ Some ( g) => * slot = g,
154167 None => return ( i, false ) ,
155168 }
156169 }
@@ -195,12 +208,11 @@ impl<'a> Parser<'a> {
195208 self . read_ipv4_addr ( ) . map ( IpAddr :: V4 ) . or_else ( move || self . read_ipv6_addr ( ) . map ( IpAddr :: V6 ) )
196209 }
197210
198- /// Read a : followed by a port in base 10
211+ /// Read a : followed by a port in base 10.
199212 fn read_port ( & mut self ) -> Option < u16 > {
200213 self . read_atomically ( |p| {
201214 let _ = p. read_given_char ( ':' ) ?;
202- let port = p. read_number ( 10 , 5 , 0x10000 ) ?;
203- Some ( port as u16 )
215+ p. read_number ( 10 , None )
204216 } )
205217 }
206218
0 commit comments