Skip to content

Commit e8509eb

Browse files
committed
v0: introduce HexNibbles abstraction for leaf const parsing.
1 parent 9d8a7d8 commit e8509eb

File tree

1 file changed

+50
-31
lines changed

1 file changed

+50
-31
lines changed

src/v0.rs

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::convert::TryFrom;
12
use 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+
267292
fn 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

Comments
 (0)