1+ use core:: convert:: TryFrom ;
12use core:: { char, fmt, mem} ;
23
34#[ allow( unused_macros) ]
@@ -264,6 +265,30 @@ impl<'s> fmt::Display for Ident<'s> {
264265 }
265266}
266267
268+ /// Sequence of lowercase hexadecimal nibbles (`0-9a-f`), used by leaf consts.
269+ struct HexNibbles < ' s > {
270+ nibbles : & ' s str ,
271+ }
272+
273+ impl < ' s > HexNibbles < ' s > {
274+ /// Decode an integer value (with the "most significant nibble" first),
275+ /// returning `None` if it can't fit in an `u64`.
276+ // FIXME(eddyb) should this "just" use `u128` instead?
277+ fn try_parse_uint ( & self ) -> Option < u64 > {
278+ let nibbles = self . nibbles . trim_start_matches ( "0" ) ;
279+
280+ if nibbles. len ( ) > 16 {
281+ return None ;
282+ }
283+
284+ let mut v = 0 ;
285+ for nibble in nibbles. chars ( ) {
286+ v = ( v << 4 ) | ( nibble. to_digit ( 16 ) . unwrap ( ) as u64 ) ;
287+ }
288+ Some ( v)
289+ }
290+ }
291+
267292fn basic_type ( tag : u8 ) -> Option < & ' static str > {
268293 Some ( match tag {
269294 b'b' => "bool" ,
@@ -331,7 +356,7 @@ impl<'s> Parser<'s> {
331356 Ok ( b)
332357 }
333358
334- fn hex_nibbles ( & mut self ) -> Result < & ' s str , ParseError > {
359+ fn hex_nibbles ( & mut self ) -> Result < HexNibbles < ' s > , ParseError > {
335360 let start = self . next ;
336361 loop {
337362 match self . next ( ) ? {
@@ -340,7 +365,9 @@ impl<'s> Parser<'s> {
340365 _ => return Err ( ParseError :: Invalid ) ,
341366 }
342367 }
343- Ok ( & self . sym [ start..self . next - 1 ] )
368+ Ok ( HexNibbles {
369+ nibbles : & self . sym [ start..self . next - 1 ] ,
370+ } )
344371 }
345372
346373 fn digit_10 ( & mut self ) -> Result < u8 , ParseError > {
@@ -976,16 +1003,14 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
9761003 fn print_const_uint ( & mut self , ty_tag : u8 ) -> fmt:: Result {
9771004 let hex = parse ! ( self , hex_nibbles) ;
9781005
979- // Print anything that doesn't fit in `u64` verbatim.
980- if hex. len ( ) > 16 {
981- self . print ( "0x" ) ?;
982- self . print ( hex) ?;
983- } else {
984- let mut v = 0 ;
985- for c in hex. chars ( ) {
986- v = ( v << 4 ) | ( c. to_digit ( 16 ) . unwrap ( ) as u64 ) ;
1006+ match hex. try_parse_uint ( ) {
1007+ Some ( v) => self . print ( v) ?,
1008+
1009+ // Print anything that doesn't fit in `u64` verbatim.
1010+ None => {
1011+ self . print ( "0x" ) ?;
1012+ self . print ( hex. nibbles ) ?;
9871013 }
988- self . print ( v) ?;
9891014 }
9901015
9911016 if let Some ( out) = & mut self . out {
@@ -1007,33 +1032,27 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
10071032 }
10081033
10091034 fn print_const_bool ( & mut self ) -> fmt:: Result {
1010- match parse ! ( self , hex_nibbles) . as_bytes ( ) {
1011- b"0" => self . print ( "false" ) ,
1012- b"1" => self . print ( "true" ) ,
1035+ match parse ! ( self , hex_nibbles) . try_parse_uint ( ) {
1036+ Some ( 0 ) => self . print ( "false" ) ,
1037+ Some ( 1 ) => self . print ( "true" ) ,
10131038 _ => invalid ! ( self ) ,
10141039 }
10151040 }
10161041
10171042 fn print_const_char ( & mut self ) -> fmt:: Result {
1018- let hex = parse ! ( self , hex_nibbles) ;
1019-
1020- // Valid `char`s fit in `u32`.
1021- if hex. len ( ) > 8 {
1022- invalid ! ( self ) ;
1023- }
1024-
1025- let mut v = 0 ;
1026- for c in hex. chars ( ) {
1027- v = ( v << 4 ) | ( c. to_digit ( 16 ) . unwrap ( ) as u32 ) ;
1028- }
1029- if let Some ( c) = char:: from_u32 ( v) {
1030- if let Some ( out) = & mut self . out {
1031- fmt:: Debug :: fmt ( & c, out) ?;
1043+ match parse ! ( self , hex_nibbles)
1044+ . try_parse_uint ( )
1045+ . and_then ( |v| u32:: try_from ( v) . ok ( ) )
1046+ . and_then ( char:: from_u32)
1047+ {
1048+ Some ( c) => {
1049+ if let Some ( out) = & mut self . out {
1050+ fmt:: Debug :: fmt ( & c, out) ?;
1051+ }
1052+ Ok ( ( ) )
10321053 }
1033- } else {
1034- invalid ! ( self ) ;
1054+ None => invalid ! ( self ) ,
10351055 }
1036- Ok ( ( ) )
10371056 }
10381057}
10391058
0 commit comments