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 ] ,
@@ -59,7 +82,7 @@ impl<'a> Parser<'a> {
5982 fn read_char ( & mut self ) -> Option < char > {
6083 self . state . split_first ( ) . map ( |( & b, tail) | {
6184 self . state = tail;
62- b as char
85+ char:: from ( b )
6386 } )
6487 }
6588
@@ -84,25 +107,26 @@ impl<'a> Parser<'a> {
84107 } )
85108 }
86109
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-
93110 // Read a number off the front of the input in the given radix, stopping
94111 // 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 > {
112+ // digits than max_digits or if there is no number.
113+ fn read_number < T : ReadNumberHelper > (
114+ & mut self ,
115+ radix : u32 ,
116+ max_digits : Option < usize > ,
117+ ) -> Option < T > {
97118 self . read_atomically ( move |p| {
98- let mut result = 0 ;
119+ let mut result = T :: ZERO ;
99120 let mut digit_count = 0 ;
100121
101- while let Some ( digit) = p. read_digit ( radix) {
102- result = ( result * radix) + digit;
122+ while let Some ( digit) = p. read_atomically ( |p| p. read_char ( ) ?. to_digit ( radix) ) {
123+ result = result. checked_mul ( radix) ?;
124+ result = result. checked_add ( digit) ?;
103125 digit_count += 1 ;
104- if digit_count > max_digits || result >= upto {
105- return None ;
126+ if let Some ( max_digits) = max_digits {
127+ if digit_count > max_digits {
128+ return None ;
129+ }
106130 }
107131 }
108132
@@ -116,7 +140,7 @@ impl<'a> Parser<'a> {
116140 let mut groups = [ 0 ; 4 ] ;
117141
118142 for ( i, slot) in groups. iter_mut ( ) . enumerate ( ) {
119- * slot = p. read_separator ( '.' , i, |p| p. read_number ( 10 , 3 , 0x100 ) ) ? as u8 ;
143+ * slot = p. read_separator ( '.' , i, |p| p. read_number ( 10 , None ) ) ?;
120144 }
121145
122146 Some ( groups. into ( ) )
@@ -140,17 +164,17 @@ impl<'a> Parser<'a> {
140164 let ipv4 = p. read_separator ( ':' , i, |p| p. read_ipv4_addr ( ) ) ;
141165
142166 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 ) ;
167+ let [ one , two , three , four ] = v4_addr. octets ( ) ;
168+ groups[ i + 0 ] = u16:: from_be_bytes ( [ one , two ] ) ;
169+ groups[ i + 1 ] = u16:: from_be_bytes ( [ three , four ] ) ;
146170 return ( i + 2 , true ) ;
147171 }
148172 }
149173
150- let group = p. read_separator ( ':' , i, |p| p. read_number ( 16 , 4 , 0x10000 ) ) ;
174+ let group = p. read_separator ( ':' , i, |p| p. read_number ( 16 , Some ( 4 ) ) ) ;
151175
152176 match group {
153- Some ( g) => * slot = g as u16 ,
177+ Some ( g) => * slot = g,
154178 None => return ( i, false ) ,
155179 }
156180 }
@@ -195,12 +219,11 @@ impl<'a> Parser<'a> {
195219 self . read_ipv4_addr ( ) . map ( IpAddr :: V4 ) . or_else ( move || self . read_ipv6_addr ( ) . map ( IpAddr :: V6 ) )
196220 }
197221
198- /// Read a : followed by a port in base 10
222+ /// Read a : followed by a port in base 10.
199223 fn read_port ( & mut self ) -> Option < u16 > {
200224 self . read_atomically ( |p| {
201225 let _ = p. read_given_char ( ':' ) ?;
202- let port = p. read_number ( 10 , 5 , 0x10000 ) ?;
203- Some ( port as u16 )
226+ p. read_number ( 10 , None )
204227 } )
205228 }
206229
0 commit comments