Add support for `min_const_generics` constants (#39)
diff --git a/src/v0.rs b/src/v0.rs
index c941acd..8f0ff35 100644
--- a/src/v0.rs
+++ b/src/v0.rs
@@ -56,6 +56,21 @@
Ok((Demangle { inner }, &parser.sym[parser.next..]))
}
+fn supported_const_generic_type(ty_tag: u8) -> bool {
+ match ty_tag {
+ // Unsigned integer types.
+ b'h' | b't' | b'm' | b'y' | b'o' | b'j' |
+ // Signed integer types.
+ b'a' | b's' | b'l' | b'x' | b'n' | b'i' |
+ // Bool.
+ b'b' |
+ // Char.
+ b'c' => true,
+
+ _ => false,
+ }
+}
+
impl<'s> Display for Demangle<'s> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut printer = Printer {
@@ -532,16 +547,18 @@
return Ok(());
}
- match self.next()? {
- // Unsigned integer types.
- b'h' | b't' | b'm' | b'y' | b'o' | b'j' => {}
-
- _ => return Err(Invalid),
+ let ty_tag = self.next()?;
+ if !supported_const_generic_type(ty_tag) {
+ return Err(Invalid);
}
if self.eat(b'p') {
return Ok(());
}
+ // Negation on signed integers.
+ if let b'a' | b's' | b'l' | b'x' | b'n' | b'i' = ty_tag {
+ let _ = self.eat(b'n');
+ }
self.hex_nibbles()?;
Ok(())
}
@@ -936,21 +953,31 @@
}
let ty_tag = parse!(self, next);
- let ty = match ty_tag {
- // Unsigned integer types.
- b'h' | b't' | b'm' | b'y' | b'o' | b'j' => basic_type(ty_tag).unwrap(),
-
- _ => invalid!(self),
- };
+ if !supported_const_generic_type(ty_tag) {
+ invalid!(self);
+ }
if self.eat(b'p') {
self.out.write_str("_")?;
} else {
- self.print_const_uint()?;
+ match ty_tag {
+ // Unsigned integer types.
+ b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint()?,
+ // Signed integer types.
+ b'a' | b's' | b'l' | b'x' | b'n' | b'i' => self.print_const_int()?,
+ // Bool.
+ b'b' => self.print_const_bool()?,
+ // Char.
+ b'c' => self.print_const_char()?,
+
+ // This branch ought to be unreachable.
+ _ => invalid!(self),
+ };
}
if !self.out.alternate() {
self.out.write_str(": ")?;
+ let ty = basic_type(ty_tag).unwrap();
self.out.write_str(ty)?;
}
@@ -972,6 +999,41 @@
}
v.fmt(self.out)
}
+
+ fn print_const_int(&mut self) -> fmt::Result {
+ if self.eat(b'n') {
+ self.out.write_str("-")?;
+ }
+
+ self.print_const_uint()
+ }
+
+ fn print_const_bool(&mut self) -> fmt::Result {
+ match parse!(self, hex_nibbles).as_bytes() {
+ b"0" => self.out.write_str("false"),
+ b"1" => self.out.write_str("true"),
+ _ => invalid!(self),
+ }
+ }
+
+ fn print_const_char(&mut self) -> fmt::Result {
+ let hex = parse!(self, hex_nibbles);
+
+ // Valid `char`s fit in `u32`.
+ if hex.len() > 8 {
+ invalid!(self);
+ }
+
+ let mut v = 0;
+ for c in hex.chars() {
+ v = (v << 4) | (c.to_digit(16).unwrap() as u32);
+ }
+ if let Some(c) = char::from_u32(v) {
+ write!(self.out, "'{}'", c)
+ } else {
+ invalid!(self)
+ }
+ }
}
#[cfg(test)]
@@ -1028,6 +1090,34 @@
"INtC8arrayvec8ArrayVechKj7b_E",
"arrayvec::ArrayVec<u8, 123>"
);
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E",
+ "<const_generic::Unsigned<11>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E",
+ "<const_generic::Signed<152>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E",
+ "<const_generic::Signed<-11>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E",
+ "<const_generic::Bool<false>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E",
+ "<const_generic::Bool<true>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E",
+ "<const_generic::Char<'v'>>"
+ );
+ t_nohash!(
+ "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E",
+ "<const_generic::Char<'∂'>>"
+ );
}
#[test]