in sgx_demangle/src/v0.rs [1090:1217]
fn print_const(&mut self, in_value: bool) -> fmt::Result {
let tag = parse!(self, next);
parse!(self, push_depth);
// Only literals (and the names of `const` generic parameters, but they
// don't get mangled at all), can appear in generic argument position
// without any disambiguation, all other expressions require braces.
// To avoid duplicating the mapping between `tag` and what syntax gets
// used (especially any special-casing), every case that needs braces
// has to call `open_brace(self)?` (and the closing brace is automatic).
let mut opened_brace = false;
let mut open_brace_if_outside_expr = |this: &mut Self| {
// If this expression is nested in another, braces aren't required.
if in_value {
return Ok(());
}
opened_brace = true;
this.print("{")
};
match tag {
b'p' => self.print("_")?,
// Primitive leaves with hex-encoded values (see `basic_type`).
b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint(tag)?,
b'a' | b's' | b'l' | b'x' | b'n' | b'i' => {
if self.eat(b'n') {
self.print("-")?;
}
self.print_const_uint(tag)?;
}
b'b' => match parse!(self, hex_nibbles).try_parse_uint() {
Some(0) => self.print("false")?,
Some(1) => self.print("true")?,
_ => invalid!(self),
},
b'c' => {
let valid_char = parse!(self, hex_nibbles)
.try_parse_uint()
.and_then(|v| u32::try_from(v).ok())
.and_then(char::from_u32);
match valid_char {
Some(c) => self.print_quoted_escaped_chars('\'', iter::once(c))?,
None => invalid!(self),
}
}
b'e' => {
// NOTE(eddyb) a string literal `"..."` has type `&str`, so
// to get back the type `str`, `*"..."` syntax is needed
// (even if that may not be valid in Rust itself).
open_brace_if_outside_expr(self)?;
self.print("*")?;
self.print_const_str_literal()?;
}
b'R' | b'Q' => {
// NOTE(eddyb) this prints `"..."` instead of `&*"..."`, which
// is what `Re..._` would imply (see comment for `str` above).
if tag == b'R' && self.eat(b'e') {
self.print_const_str_literal()?;
} else {
open_brace_if_outside_expr(self)?;
self.print("&")?;
if tag != b'R' {
self.print("mut ")?;
}
self.print_const(true)?;
}
}
b'A' => {
open_brace_if_outside_expr(self)?;
self.print("[")?;
self.print_sep_list(|this| this.print_const(true), ", ")?;
self.print("]")?;
}
b'T' => {
open_brace_if_outside_expr(self)?;
self.print("(")?;
let count = self.print_sep_list(|this| this.print_const(true), ", ")?;
if count == 1 {
self.print(",")?;
}
self.print(")")?;
}
b'V' => {
open_brace_if_outside_expr(self)?;
self.print_path(true)?;
match parse!(self, next) {
b'U' => {}
b'T' => {
self.print("(")?;
self.print_sep_list(|this| this.print_const(true), ", ")?;
self.print(")")?;
}
b'S' => {
self.print(" { ")?;
self.print_sep_list(
|this| {
parse!(this, disambiguator);
let name = parse!(this, ident);
this.print(name)?;
this.print(": ")?;
this.print_const(true)
},
", ",
)?;
self.print(" }")?;
}
_ => invalid!(self),
}
}
b'B' => {
self.print_backref(|this| this.print_const(in_value))?;
}
_ => invalid!(self),
}
if opened_brace {
self.print("}")?;
}
self.pop_depth();
Ok(())
}