1
+ use core:: convert:: TryFrom ;
1
2
use core:: { char, fmt, mem} ;
2
3
3
4
#[ allow( unused_macros) ]
@@ -264,6 +265,30 @@ impl<'s> fmt::Display for Ident<'s> {
264
265
}
265
266
}
266
267
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
+
267
292
fn basic_type ( tag : u8 ) -> Option < & ' static str > {
268
293
Some ( match tag {
269
294
b'b' => "bool" ,
@@ -331,7 +356,7 @@ impl<'s> Parser<'s> {
331
356
Ok ( b)
332
357
}
333
358
334
- fn hex_nibbles ( & mut self ) -> Result < & ' s str , ParseError > {
359
+ fn hex_nibbles ( & mut self ) -> Result < HexNibbles < ' s > , ParseError > {
335
360
let start = self . next ;
336
361
loop {
337
362
match self . next ( ) ? {
@@ -340,7 +365,9 @@ impl<'s> Parser<'s> {
340
365
_ => return Err ( ParseError :: Invalid ) ,
341
366
}
342
367
}
343
- Ok ( & self . sym [ start..self . next - 1 ] )
368
+ Ok ( HexNibbles {
369
+ nibbles : & self . sym [ start..self . next - 1 ] ,
370
+ } )
344
371
}
345
372
346
373
fn digit_10 ( & mut self ) -> Result < u8 , ParseError > {
@@ -976,16 +1003,14 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
976
1003
fn print_const_uint ( & mut self , ty_tag : u8 ) -> fmt:: Result {
977
1004
let hex = parse ! ( self , hex_nibbles) ;
978
1005
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 ) ?;
987
1013
}
988
- self . print ( v) ?;
989
1014
}
990
1015
991
1016
if let Some ( out) = & mut self . out {
@@ -1007,33 +1032,27 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
1007
1032
}
1008
1033
1009
1034
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" ) ,
1013
1038
_ => invalid ! ( self ) ,
1014
1039
}
1015
1040
}
1016
1041
1017
1042
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 ( ( ) )
1032
1053
}
1033
- } else {
1034
- invalid ! ( self ) ;
1054
+ None => invalid ! ( self ) ,
1035
1055
}
1036
- Ok ( ( ) )
1037
1056
}
1038
1057
}
1039
1058
0 commit comments