fn print_const()

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(())
    }