msvc_demangler/
lib.rs

1//! msvc-demangler is a crate for Rust that can demangle C++ symbols which use
2//! the MSVC mangling scheme.  These are emitted by the Microsoft C++ compiler
3//! for Windows as well as some others.
4//!
5//! # Example
6//!
7//! ```
8//! use msvc_demangler;
9//! let flags = msvc_demangler::DemangleFlags::llvm();
10//! let result = msvc_demangler::demangle("??_0klass@@QEAAHH@Z", flags).unwrap();
11//! println!("{}", result);
12//! ```
13//!
14//! # Behavior
15//!
16//! It's functionality is similar to `undname` on Windows and the underlying
17//! `UnDecorateSymbolName` function.  Since Microsoft does not document the
18//! mangling scheme this is likely not to be entirely accurate.  When unclear
19//! the implementation tries to follow what LLVM does.
20//!
21//! # License
22//!
23//! This msvc-demangler is dual licensed under the MIT and the University of
24//! Illinois Open Source Licenses.
25
26#![no_std]
27#![deny(missing_debug_implementations)]
28#![deny(unsafe_code)]
29
30extern crate alloc;
31
32use alloc::borrow::Cow;
33use alloc::boxed::Box;
34use alloc::string::String;
35use alloc::string::{FromUtf8Error, ToString};
36use alloc::vec::Vec;
37use alloc::{format, vec};
38use bitflags::bitflags;
39use core::cmp::min;
40use core::error;
41use core::fmt;
42use core::mem;
43use core::result;
44use core::str;
45use core::str::Utf8Error;
46
47pub struct Error {
48    repr: ErrorRepr,
49}
50
51impl fmt::Debug for Error {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        fmt::Debug::fmt(&self.repr, f)
54    }
55}
56
57#[derive(Debug)]
58pub enum ErrorRepr {
59    FromUtf8(FromUtf8Error),
60    Utf8(Utf8Error),
61    ParseError(Cow<'static, str>, String, usize),
62    Other(String),
63}
64
65impl Error {
66    /// Creates a simple error message.
67    pub fn new<S: Into<String>>(s: S) -> Error {
68        Error {
69            repr: ErrorRepr::Other(s.into()),
70        }
71    }
72
73    fn new_parse_error(s: Cow<'static, str>, input: &str, offset: usize) -> Error {
74        let context = Cow::Borrowed(input.as_bytes().get(offset..).unwrap_or(&[]));
75        let context = if context.len() > 20 {
76            Cow::Owned(format!("{}...", String::from_utf8_lossy(&context[..20])))
77        } else {
78            String::from_utf8_lossy(&context)
79        };
80        Error {
81            repr: ErrorRepr::ParseError(s, context.to_string(), offset),
82        }
83    }
84
85    /// Returns the offset in the input where the error happened.
86    pub fn offset(&self) -> Option<usize> {
87        match self.repr {
88            ErrorRepr::ParseError(_, _, offset) => Some(offset),
89            _ => None,
90        }
91    }
92}
93
94impl From<Utf8Error> for Error {
95    fn from(err: Utf8Error) -> Error {
96        Error {
97            repr: ErrorRepr::Utf8(err),
98        }
99    }
100}
101
102impl From<FromUtf8Error> for Error {
103    fn from(err: FromUtf8Error) -> Error {
104        Error {
105            repr: ErrorRepr::FromUtf8(err),
106        }
107    }
108}
109
110impl error::Error for Error {
111    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
112        match self.repr {
113            ErrorRepr::FromUtf8(ref e) => Some(e),
114            ErrorRepr::Utf8(ref e) => Some(e),
115            ErrorRepr::ParseError(..) => None,
116            ErrorRepr::Other(_) => None,
117        }
118    }
119}
120
121impl fmt::Display for Error {
122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123        match self.repr {
124            ErrorRepr::FromUtf8(ref e) => fmt::Display::fmt(e, f),
125            ErrorRepr::Utf8(ref e) => fmt::Display::fmt(e, f),
126            ErrorRepr::ParseError(ref msg, ref context, offset) => {
127                write!(f, "{} (offset: {}, remaining: {:?})", msg, offset, context)
128            }
129            ErrorRepr::Other(ref msg) => write!(f, "{}", msg),
130        }
131    }
132}
133
134type Result<T> = result::Result<T, Error>;
135
136bitflags! {
137    #[derive(Clone, Copy, Debug, PartialEq)]
138    pub struct StorageClass: u32 {
139        const CONST       = 0b0_0000_0001;
140        const VOLATILE    = 0b0_0000_0010;
141        const FAR         = 0b0_0000_0100;
142        const HUGE        = 0b0_0000_1000;
143        const UNALIGNED   = 0b0_0001_0000;
144        const RESTRICT    = 0b0_0010_0000;
145        const PTR64       = 0b0_0100_0000;
146        const LVALUE_QUAL = 0b0_1000_0000;
147        const RVALUE_QUAL = 0b1_0000_0000;
148    }
149}
150
151bitflags! {
152    #[derive(Clone, Copy)]
153    pub struct DemangleFlags: u32 {
154        /// Undecorate 32-bit decorated names.
155        const DECODE_32_BIT = 0x0800;
156        /// Enable full undecoration.
157        const COMPLETE = 0x0000;
158        /// Undecorate only the name for primary declaration. Returns [scope::]name. Does expand template parameters.
159        const NAME_ONLY = 0x1000;
160        /// Disable expansion of access specifiers for members.
161        const NO_ACCESS_SPECIFIERS = 0x0080;
162        // /// Disable expansion of the declaration language specifier.
163        // const NO_ALLOCATION_LANGUAGE = 0x0010;
164        // /// Disable expansion of the declaration model.
165        // const NO_ALLOCATION_MODEL = 0x0008;
166        // /// Do not undecorate function arguments.
167        // const NO_ARGUMENTS = 0x2000;
168        /// Disable expansion of CodeView modifiers on the this type for primary declaration.
169        const NO_CV_THISTYPE = 0x0040;
170        /// Disable expansion of return types for primary declarations.
171        const NO_FUNCTION_RETURNS = 0x0004;
172        // /// Remove leading underscores from Microsoft keywords.
173        // const NO_LEADING_UNDERSCORES = 0x0001;
174        /// Disable expansion of the static or virtual attribute of members.
175        const NO_MEMBER_TYPE = 0x0200;
176        /// Disable expansion of Microsoft keywords.
177        const NO_MS_KEYWORDS = 0x0002;
178        /// Disable expansion of Microsoft keywords on the this type for primary declaration.
179        const NO_MS_THISTYPE = 0x0020;
180        /// Enable Microsoft type names.
181        const MS_TYPENAMES = 0x0400;
182        // /// Disable expansion of the Microsoft model for user-defined type returns.
183        // const NO_RETURN_UDT_MODEL = 0x0400;
184        // /// Do not undecorate special names, such as vtable, vcall, vector, metatype, and so on.
185        // const NO_SPECIAL_SYMS = 0x4000;
186        /// Disable all modifiers on the this type.
187        const NO_THISTYPE = Self::NO_MS_THISTYPE.bits() | Self::NO_CV_THISTYPE.bits();
188        // /// Disable expansion of throw-signatures for functions and pointers to functions.
189        // const NO_THROW_SIGNATURES = 0x0100;
190        /// Disable output of struct/union/class/enum specifiers.
191        // (Not sure if this duplicates an existing flag)
192        const NO_CLASS_TYPE = 0x10_0000;
193        /// Insert a space after each comma.
194        const SPACE_AFTER_COMMA = 0x20_0000;
195        /// Make * and & hug the type name.
196        const HUG_TYPE = 0x40_0000;
197        /// Insert a space before pointers.
198        const SPACE_BEFORE_POINTER = 0x80_0000;
199        /// Add ptr64 to output.  This is disabled by default because it's also not
200        /// added by LLVM.  This is in a way the inverse of the DIA `UNDNAME_NO_PTR64`
201        const WITH_PTR64 = 0x100_0000;
202    }
203}
204
205impl DemangleFlags {
206    pub fn llvm() -> DemangleFlags {
207        DemangleFlags::COMPLETE
208            | DemangleFlags::SPACE_AFTER_COMMA
209            | DemangleFlags::SPACE_BEFORE_POINTER
210            | DemangleFlags::MS_TYPENAMES
211            | DemangleFlags::HUG_TYPE
212    }
213}
214
215// Calling conventions
216#[derive(Clone, Copy, Debug, PartialEq)]
217pub enum CallingConv {
218    Cdecl,
219    Pascal,
220    Thiscall,
221    Stdcall,
222    Fastcall,
223    _Regcall,
224}
225
226bitflags! {
227    #[derive(Clone, Debug, PartialEq)]
228    pub struct FuncClass: u32 {
229        const PUBLIC     = 0b0000_0001;
230        const PROTECTED  = 0b0000_0010;
231        const PRIVATE    = 0b0000_0100;
232        const GLOBAL     = 0b0000_1000;
233        const STATIC     = 0b0001_0000;
234        const VIRTUAL    = 0b0010_0000;
235        const FAR        = 0b0100_0000;
236        const THUNK      = 0b1000_0000;
237    }
238}
239
240// The kind of variable storage. In LLVM this is called storage class.
241#[derive(Clone, Copy, Debug, PartialEq)]
242pub enum VarStorageKind {
243    PrivateStatic,
244    ProtectedStatic,
245    PublicStatic,
246    Global,
247    FunctionLocalStatic,
248}
249
250// Represents an identifier which may be a template.
251#[derive(Clone, PartialEq)]
252pub enum Name<'a> {
253    Md5(&'a [u8]),
254    Operator(Operator<'a>),
255    NonTemplate(&'a [u8]),
256    AsInterface(&'a [u8]),
257    Template(Box<Name<'a>>, Params<'a>),
258    Discriminator(i32),
259    ParsedName(Box<ParseResult<'a>>),
260    AnonymousNamespace(Option<String>),
261}
262
263impl fmt::Debug for Name<'_> {
264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265        match *self {
266            Name::Md5(s) => f
267                .debug_tuple("Md5")
268                .field(&String::from_utf8_lossy(s))
269                .finish(),
270            Name::Operator(ref op) => f.debug_tuple("Operator").field(&op).finish(),
271            Name::NonTemplate(s) => f
272                .debug_tuple("NonTemplate")
273                .field(&String::from_utf8_lossy(s))
274                .finish(),
275            Name::AsInterface(s) => f
276                .debug_tuple("AsInterface")
277                .field(&String::from_utf8_lossy(s))
278                .finish(),
279            Name::Template(ref name, ref params) => {
280                f.debug_tuple("Template").field(name).field(params).finish()
281            }
282            Name::Discriminator(i) => f.debug_tuple("Discriminator").field(&i).finish(),
283            Name::ParsedName(ref res) => f.debug_tuple("ParsedName").field(res).finish(),
284            Name::AnonymousNamespace(ref name) => {
285                f.debug_tuple("AnonymousNamespace").field(name).finish()
286            }
287        }
288    }
289}
290
291#[derive(Clone, Debug, PartialEq)]
292pub enum Operator<'a> {
293    Ctor,
294    Dtor,
295    New,
296    Delete,
297    Equal,
298    RShift,
299    LShift,
300    Bang,
301    EqualEqual,
302    BangEqual,
303    Subscript,
304    Conversion, // TODO
305    Arrow,
306    Star,
307    PlusPlus,
308    MinusMinus,
309    Minus,
310    Plus,
311    Amp,
312    ArrowStar,
313    Slash,
314    Percent,
315    Less,
316    LessEqual,
317    Greater,
318    GreaterEqual,
319    Comma,
320    Call,
321    Tilde,
322    Caret,
323    Pipe,
324    AmpAmp,
325    PipePipe,
326    StarEqual,
327    PlusEqual,
328    MinusEqual,
329    SlashEqual,
330    PercentEqual,
331    GreaterGreaterEqual,
332    LessLessEqual,
333    AmpEqual,
334    PipeEqual,
335    CaretEqual,
336
337    VFTable,
338    VBTable,
339    VCall,
340    Typeof,
341    LocalStaticGuard(Option<u32>),
342    String,
343    VBaseDtor,
344    VectorDeletingDtor,
345    DefaultCtorClosure,
346    ScalarDeletingDtor,
347    VectorCtorIterator,
348    VectorDtorIterator,
349    VectorVBaseCtorIterator,
350    VirtualDisplacementMap,
351    EHVectorCtorIterator,
352    EHVectorDtorIterator,
353    EHVectorVBaseCtorIterator,
354    CopyCtorClosure,
355
356    LocalVFTable,
357    LocalVFTableCtorClosure,
358    ArrayNew,
359    ArrayDelete,
360    PlacementDeleteClosure,
361    PlacementArrayDeleteClosure,
362
363    CoroutineAwait,
364    LiteralOperatorName,
365
366    RTTITypeDescriptor(StorageClass, Box<Type<'a>>),
367    RTTIBaseClassDescriptor(i32, i32, i32, i32),
368    RTTIBaseClassArray,
369    RTTIClassHierarchyDescriptor,
370    RTTIClassCompleteObjectLocator,
371
372    DynamicInitializer,
373    DynamicAtexitDtor,
374    LocalStaticThreadGuard(Option<u32>),
375}
376
377#[derive(Clone, Debug, PartialEq)]
378pub struct NameSequence<'a> {
379    pub names: Vec<Name<'a>>,
380}
381
382#[derive(Clone, Debug, PartialEq)]
383pub struct Params<'a> {
384    pub types: Vec<Type<'a>>,
385}
386
387#[derive(Clone, Debug, PartialEq)]
388pub struct Symbol<'a> {
389    pub name: Name<'a>,
390    pub scope: NameSequence<'a>,
391}
392
393// The type class. Mangled symbols are first parsed and converted to
394// this type and then converted to string.
395#[derive(Clone, Debug, PartialEq)]
396pub enum Type<'a> {
397    None,
398    MemberFunction(
399        FuncClass,
400        CallingConv,
401        Params<'a>,
402        StorageClass,
403        Box<Type<'a>>,
404    ), // StorageClass is for the 'this' pointer
405    MemberFunctionPointer(
406        Symbol<'a>,
407        FuncClass,
408        CallingConv,
409        Params<'a>,
410        StorageClass,
411        Box<Type<'a>>,
412    ),
413    NonMemberFunction(CallingConv, Params<'a>, StorageClass, Box<Type<'a>>),
414    CXXVBTable(NameSequence<'a>, StorageClass),
415    CXXVFTable(NameSequence<'a>, StorageClass),
416    VCallThunk(i32, CallingConv),
417    TemplateParameterWithIndex(i32),
418    ThreadSafeStaticGuard(i32),
419    Constant(i32),
420    ConstantString(Vec<u8>),
421    Ptr(Box<Type<'a>>, StorageClass),
422    Ref(Box<Type<'a>>, StorageClass),
423    RValueRef(Box<Type<'a>>, StorageClass),
424    Array(i32, Box<Type<'a>>, StorageClass),
425    Var(Box<Type<'a>>, VarStorageKind, StorageClass),
426
427    Alias(Symbol<'a>, StorageClass),
428    Struct(Symbol<'a>, StorageClass),
429    Union(Symbol<'a>, StorageClass),
430    Class(Symbol<'a>, StorageClass),
431    Enum(Symbol<'a>, StorageClass),
432
433    Void(StorageClass),
434    Bool(StorageClass),
435    Char(StorageClass),
436    Schar(StorageClass),
437    Uchar(StorageClass),
438    Short(StorageClass),
439    Ushort(StorageClass),
440    Int(StorageClass),
441    Uint(StorageClass),
442    Long(StorageClass),
443    Ulong(StorageClass),
444    Int64(StorageClass),
445    Uint64(StorageClass),
446    Int128(StorageClass),
447    Uint128(StorageClass),
448    Wchar(StorageClass),
449    Char8(StorageClass),
450    Char16(StorageClass),
451    Char32(StorageClass),
452    Float(StorageClass),
453    Double(StorageClass),
454    Ldouble(StorageClass),
455    VarArgs,
456    EmptyParameterPack,
457    Nullptr,
458    RTTIType,
459}
460
461#[derive(Debug, Clone, PartialEq)]
462pub struct ParseResult<'a> {
463    pub symbol: Symbol<'a>,
464    pub symbol_type: Type<'a>,
465}
466
467// Demangler class takes the main role in demangling symbols.
468// It has a set of functions to parse mangled symbols into Type instnaces.
469// It also has a set of functions to cnovert Type instances to strings.
470struct ParserState<'a> {
471    // Mangled symbol. read_* functions shorten this string
472    // as they parse it.
473    remaining: &'a [u8],
474
475    // The original input
476    input: &'a str,
477
478    // how many bytes we advanced
479    offset: usize,
480
481    // The first 10 names in a mangled name can be back-referenced by
482    // special name @[0-9]. This is a storage for the first 10 names.
483    memorized_names: Vec<Name<'a>>,
484
485    memorized_types: Vec<Type<'a>>,
486}
487
488impl<'a> ParserState<'a> {
489    fn fail(&self, s: &'static str) -> Error {
490        Error::new_parse_error(Cow::Borrowed(s), self.input, self.offset)
491    }
492
493    fn fail_args(&self, args: fmt::Arguments) -> Error {
494        Error::new_parse_error(Cow::Owned(format!("{}", args)), self.input, self.offset)
495    }
496
497    fn parse(&mut self) -> Result<ParseResult<'a>> {
498        // MSVC-style mangled symbols must start with b'?'.
499        if !self.consume(b"?") {
500            return Err(self.fail("does not start with b'?'"));
501        }
502
503        if self.consume(b"?@") {
504            let name = self.read_md5_name()?;
505            return Ok(ParseResult {
506                symbol: Symbol {
507                    name,
508                    scope: NameSequence { names: Vec::new() },
509                },
510                symbol_type: Type::None,
511            });
512        }
513
514        if self.consume(b"$") {
515            if self.consume(b"TSS") {
516                let mut guard_num: i32 = i32::from(
517                    self.read_digit()
518                        .ok_or_else(|| self.fail("missing digit"))?,
519                );
520                while !self.consume(b"@") {
521                    guard_num = guard_num * 10
522                        + i32::from(
523                            self.read_digit()
524                                .ok_or_else(|| self.fail("missing digit"))?,
525                        );
526                }
527                let name = self.read_nested_name()?;
528                let scope = self.read_scope()?;
529                self.expect(b"4HA")?;
530                return Ok(ParseResult {
531                    symbol: Symbol { name, scope },
532                    symbol_type: Type::ThreadSafeStaticGuard(guard_num),
533                });
534            }
535            let name = self.read_template_name()?;
536            return Ok(ParseResult {
537                symbol: Symbol {
538                    name,
539                    scope: NameSequence { names: Vec::new() },
540                },
541                symbol_type: Type::None,
542            });
543        }
544
545        // What follows is a main symbol name. This may include
546        // namespaces or class names.
547        let mut symbol = self.read_name(true)?;
548
549        // Special case for some weird cases where extra data is tacked on
550        // after the main symbol but belongs into the symbol.
551        match symbol.name {
552            Name::Operator(Operator::LocalStaticGuard(ref mut scope_index))
553            | Name::Operator(Operator::LocalStaticThreadGuard(ref mut scope_index)) => {
554                let _is_visible = if self.consume(b"4IA") {
555                    false
556                } else if self.consume(b"5") {
557                    true
558                } else {
559                    return Err(self.fail("unexpected local guard marker"));
560                };
561                if !self.remaining.is_empty() {
562                    *scope_index = Some(self.read_unsigned()?);
563                };
564            }
565            _ => {}
566        }
567
568        if let Ok(c) = self.get() {
569            let symbol_type = match c {
570                b'0'..=b'4' => {
571                    // Read a variable.
572                    let kind = match c {
573                        b'0' => VarStorageKind::PrivateStatic,
574                        b'1' => VarStorageKind::ProtectedStatic,
575                        b'2' => VarStorageKind::PublicStatic,
576                        b'3' => VarStorageKind::Global,
577                        b'4' => VarStorageKind::FunctionLocalStatic,
578                        _ => unreachable!(),
579                    };
580                    let ty = self.read_var_type(StorageClass::empty())?;
581                    let sc = self.read_storage_class();
582                    Type::Var(Box::new(ty), kind, sc)
583                }
584                b'6' => {
585                    let access_class = self.read_qualifier();
586                    let scope = self.read_scope()?;
587                    Type::CXXVFTable(scope, access_class)
588                }
589                b'7' => {
590                    let access_class = self.read_qualifier();
591                    let scope = self.read_scope()?;
592                    Type::CXXVBTable(scope, access_class)
593                }
594                b'9' => {
595                    // extern "C" names have their class and type omitted.
596                    Type::None
597                }
598                b'Y' => {
599                    // Read a non-member function.
600                    let calling_conv = self.read_calling_conv()?;
601                    let storage_class = self.read_storage_class_for_return()?;
602                    let return_type = self.read_var_type(storage_class)?;
603                    let params = self.read_func_params()?;
604                    Type::NonMemberFunction(
605                        calling_conv,
606                        params,
607                        StorageClass::empty(),
608                        Box::new(return_type),
609                    )
610                }
611                b'_' => {
612                    // Read an encoded string.
613                    let char_bytes = match self.get()? {
614                        b'0' => 1, // char
615                        b'1' => 2, // wchar_t
616                        _ => {
617                            return Err(self.fail("unknown string character type"));
618                        }
619                    };
620                    self.read_encoded_string(char_bytes)?
621                }
622                b'$' => {
623                    self.expect(b"B")?;
624                    let vftable_offset = self.read_number()?;
625                    self.expect(b"A")?;
626                    let calling_conv = self.read_calling_conv()?;
627                    Type::VCallThunk(vftable_offset, calling_conv)
628                }
629                b'8' => Type::RTTIType,
630                c => {
631                    // Read a member function.
632                    let func_class = self.read_func_class(c)?;
633                    let access_class = if func_class.contains(FuncClass::STATIC) {
634                        StorageClass::empty()
635                    } else {
636                        self.read_func_qualifiers()?
637                    };
638
639                    let calling_conv = self.read_calling_conv()?;
640                    let storage_class_for_return = self.read_storage_class_for_return()?;
641                    let return_type = self.read_func_return_type(storage_class_for_return)?;
642                    let params = self.read_func_params()?;
643                    Type::MemberFunction(
644                        func_class,
645                        calling_conv,
646                        params,
647                        access_class,
648                        Box::new(return_type),
649                    )
650                }
651            };
652            Ok(ParseResult {
653                symbol,
654                symbol_type,
655            })
656        } else {
657            Ok(ParseResult {
658                symbol,
659                symbol_type: Type::None,
660            })
661        }
662    }
663
664    fn peek(&self) -> Option<u8> {
665        self.remaining.first().cloned()
666    }
667
668    fn get(&mut self) -> Result<u8> {
669        match self.peek() {
670            Some(first) => {
671                self.advance(1);
672                Ok(first)
673            }
674            None => Err(self.fail("unexpected end of input")),
675        }
676    }
677
678    fn consume(&mut self, s: &[u8]) -> bool {
679        if self.remaining.starts_with(s) {
680            self.advance(s.len());
681            true
682        } else {
683            false
684        }
685    }
686
687    fn advance(&mut self, len: usize) {
688        let new_remaining = self.remaining.get(len..).unwrap_or(&[]);
689        self.offset += self.remaining.len() - new_remaining.len();
690        self.remaining = new_remaining;
691    }
692
693    fn expect(&mut self, s: &[u8]) -> Result<()> {
694        if !self.consume(s) {
695            Err(self.fail_args(format_args!("{} expected", str::from_utf8(s)?,)))
696        } else {
697            Ok(())
698        }
699    }
700
701    /// An MD5 mangled name is `??@` followed by 32 characters and a terminating `@`.
702    ///
703    /// See https://github.com/llvm/llvm-project/blob/818cf30b83305fa4a2f75821349210b0f7aff4a4/llvm/lib/Demangle/MicrosoftDemangle.cpp#L754
704    fn read_md5_name(&mut self) -> Result<Name<'a>> {
705        let start_offset = self.offset;
706
707        while self.read_hex_digit().is_some() {}
708        let end_offset = self.offset;
709
710        if self.offset - start_offset != 32 || !self.consume(b"@") {
711            return Err(self.fail("expected MD5 mangled name of length 32"));
712        }
713        Ok(Name::Md5(&self.input.as_bytes()[start_offset..end_offset]))
714    }
715
716    fn read_digit(&mut self) -> Option<u8> {
717        match self.peek() {
718            Some(first) => {
719                if char::from(first).is_ascii_digit() {
720                    self.advance(1);
721                    Some(first - b'0')
722                } else {
723                    None
724                }
725            }
726            None => None,
727        }
728    }
729
730    fn read_hex_digit(&mut self) -> Option<char> {
731        match self.peek() {
732            Some(first) => {
733                if char::from(first).is_ascii_hexdigit() {
734                    self.advance(1);
735                    Some(first as char)
736                } else {
737                    None
738                }
739            }
740            None => None,
741        }
742    }
743
744    fn read_encoded_string(&mut self, char_bytes: i32) -> Result<Type<'a>> {
745        let byte_length = self.read_number()?; // including null terminator
746        let _crc = self.read_number()?;
747        let bytes = min(byte_length, char_bytes * 32);
748
749        let mut collected = vec![];
750        for _i in 0..bytes {
751            let c = self.get()?;
752            let byte: u8 = match c {
753                b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'_' | b'$' => c,
754                b'?' => {
755                    let c = self.get()?;
756                    match c {
757                        b'A'..=b'Z' => c - b'A' + 0xe1,
758                        b'a'..=b'z' => c - b'A' + 0xc1,
759                        b'0'..=b'9' => {
760                            let v = b",/\\:. \n\t'-";
761                            v[(c - b'0') as usize]
762                        }
763                        b'$' => {
764                            let high = self.get()? - b'A';
765                            let low = self.get()? - b'A';
766                            (high << 4) | low
767                        }
768                        _ => {
769                            return Err(self.fail_args(format_args!(
770                                "unknown escaped encoded string character {}",
771                                char::from(c)
772                            )));
773                        }
774                    }
775                }
776                _ => {
777                    return Err(self.fail_args(format_args!(
778                        "unknown escaped encoded string character {}",
779                        char::from(c)
780                    )));
781                }
782            };
783            collected.push(byte);
784        }
785
786        Ok(Type::ConstantString(collected))
787    }
788
789    // Sometimes numbers are encoded in mangled symbols. For example,
790    // "int (*x)[20]" is a valid C type (x is a pointer to an array of
791    // length 20), so we need some way to embed numbers as part of symbols.
792    // This function parses it.
793    //
794    // <number>               ::= [?] <non-negative integer>
795    //
796    // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
797    //                        ::= <hex digit>+ @  # when Numbrer == 0 or >= 10
798    //
799    // <hex-digit>            ::= [A-P]           # A = 0, B = 1, ...
800    fn read_number(&mut self) -> Result<i32> {
801        let neg = self.consume(b"?");
802
803        if let Some(digit) = self.read_digit() {
804            let ret = digit + 1;
805            return Ok(if neg { -i32::from(ret) } else { i32::from(ret) });
806        }
807
808        let mut i = 0;
809        let mut ret = 0i32;
810        for c in self.remaining {
811            match *c {
812                b'@' => {
813                    self.advance(i + 1);
814                    return Ok(if neg { ret.wrapping_neg() } else { ret });
815                }
816                b'A'..=b'P' => {
817                    ret = (ret << 4) + i32::from(c - b'A');
818                    i += 1;
819                }
820                _ => {
821                    return Err(self.fail("bad number"));
822                }
823            }
824        }
825        Err(self.fail("bad number"))
826    }
827
828    fn read_unsigned(&mut self) -> Result<u32> {
829        let num = self.read_number()?;
830        if num < 0 {
831            return Err(self.fail("expected unsigned"));
832        }
833        Ok(num as u32)
834    }
835
836    // Read until the next b'@'.
837    fn read_string(&mut self) -> Result<&'a [u8]> {
838        if let Some(pos) = self.remaining.iter().position(|&x| x == b'@') {
839            let ret = &self.remaining[0..pos];
840            self.advance(pos + 1);
841            Ok(ret)
842        } else {
843            Err(self.fail("read_string: missing b'@'"))
844        }
845    }
846
847    // First 10 strings can be referenced by special names ?0, ?1, ..., ?9.
848    // Memorize it.
849    fn memorize_name(&mut self, n: &Name<'a>) {
850        // TODO: the contains check does an equality check on the Name enum, which
851        // might do unexpected things in subtle cases. It's not a pure string equality check.
852        if self.memorized_names.len() < 10 && !self.memorized_names.contains(n) {
853            self.memorized_names.push(n.clone());
854        }
855    }
856    fn memorize_type(&mut self, t: &Type<'a>) {
857        // TODO: the contains check does an equality check on the Type enum, which
858        // might do unexpected things in subtle cases. It's not a pure string equality check.
859        if self.memorized_types.len() < 10 && !self.memorized_types.contains(t) {
860            self.memorized_types.push(t.clone());
861        }
862    }
863
864    fn read_template_name(&mut self) -> Result<Name<'a>> {
865        // Templates have their own context for backreferences.
866        let saved_memorized_names = mem::take(&mut self.memorized_names);
867        let saved_memorized_types = mem::take(&mut self.memorized_types);
868        let name = self.read_unqualified_name(false)?; // how does wine deal with ??$?DM@std@@YA?AV?$complex@M@0@ABMABV10@@Z
869        let template_params = self.read_params()?;
870        let _ = mem::replace(&mut self.memorized_names, saved_memorized_names);
871        let _ = mem::replace(&mut self.memorized_types, saved_memorized_types);
872        Ok(Name::Template(Box::new(name), template_params))
873    }
874
875    fn read_nested_name(&mut self) -> Result<Name<'a>> {
876        let name = if let Some(i) = self.read_digit() {
877            let i = i as usize;
878            if i >= self.memorized_names.len() {
879                return Err(self.fail("name reference too large"));
880            }
881            self.memorized_names[i].clone()
882        } else if self.consume(b"?") {
883            match self.peek() {
884                Some(b'?') => Name::ParsedName(Box::new(self.parse()?)),
885                _ => {
886                    if self.consume(b"$") {
887                        let name = self.read_template_name()?;
888                        self.memorize_name(&name);
889                        name
890                    } else if self.consume(b"A") {
891                        let id = if self.consume(b"0x") {
892                            let mut name = String::from("0x");
893                            while let Some(c) = self.read_hex_digit() {
894                                name.push(c);
895                            }
896                            Some(name)
897                        } else {
898                            None
899                        };
900                        self.expect(b"@")?;
901                        let memorize = id.is_some();
902                        let name = Name::AnonymousNamespace(id);
903                        if memorize {
904                            self.memorize_name(&name);
905                        }
906                        name
907                    } else if self.consume(b"Q") {
908                        let name = self.read_string()?;
909                        self.expect(b"@")?;
910                        let name = Name::AsInterface(name);
911                        self.memorize_name(&name);
912                        name
913                    } else {
914                        let discriminator = self.read_number()?;
915                        Name::Discriminator(discriminator)
916                    }
917                }
918            }
919        } else {
920            // Non-template functions or classes.
921            let name = self.read_string()?;
922            let name = Name::NonTemplate(name);
923            self.memorize_name(&name);
924            name
925        };
926        Ok(name)
927    }
928
929    fn read_unqualified_name(&mut self, function: bool) -> Result<Name<'a>> {
930        let name = if let Some(i) = self.read_digit() {
931            let i = i as usize;
932            if i >= self.memorized_names.len() {
933                return Err(self.fail("name reference too large"));
934            }
935            self.memorized_names[i].clone()
936        } else if self.consume(b"?$") {
937            let name = self.read_template_name()?;
938            if !function {
939                self.memorize_name(&name);
940            }
941            name
942        } else if self.consume(b"?") {
943            self.read_special_name()?
944        } else {
945            // Non-template functions or classes.
946            let name = self.read_string()?;
947            let name = Name::NonTemplate(name);
948            self.memorize_name(&name);
949            name
950        };
951        Ok(name)
952    }
953
954    fn read_scope(&mut self) -> Result<NameSequence<'a>> {
955        let mut names = Vec::new();
956        while !self.consume(b"@") {
957            let name = self.read_nested_name()?;
958            names.push(name);
959        }
960        Ok(NameSequence { names })
961    }
962
963    // Parses a name in the form of A@B@C@@ which represents C::B::A.
964    fn read_name(&mut self, function: bool) -> Result<Symbol<'a>> {
965        let name = self.read_unqualified_name(function)?;
966        let scope = self.read_scope()?;
967
968        Ok(Symbol { name, scope })
969    }
970
971    fn read_func_qualifiers(&mut self) -> Result<StorageClass> {
972        let ptr64 = if self.consume(b"E") {
973            StorageClass::PTR64
974        } else {
975            StorageClass::empty()
976        };
977        let restrict = if self.consume(b"I") {
978            StorageClass::RESTRICT
979        } else {
980            StorageClass::empty()
981        };
982        let unaligned = if self.consume(b"F") {
983            StorageClass::UNALIGNED
984        } else {
985            StorageClass::empty()
986        };
987        let ref_qualifiers = match self.peek() {
988            Some(b'G') => {
989                self.expect(b"G")?;
990                StorageClass::LVALUE_QUAL
991            }
992            Some(b'H') => {
993                self.expect(b"H")?;
994                StorageClass::RVALUE_QUAL
995            }
996            _ => StorageClass::empty(),
997        };
998        Ok(self.read_qualifier() | ptr64 | restrict | unaligned | ref_qualifiers)
999    }
1000
1001    fn read_func_type(&mut self, read_qualifiers: bool) -> Result<Type<'a>> {
1002        let sc = if read_qualifiers {
1003            self.read_func_qualifiers()?
1004        } else {
1005            StorageClass::empty()
1006        };
1007        let calling_conv = self.read_calling_conv()?;
1008        // this might have to be conditional on template context.  For now
1009        // this does not cause issues.  For more information see
1010        // https://github.com/mstange/msvc-demangler-rust/issues/21
1011        let var_sc = if self.consume(b"?") {
1012            self.read_storage_class()
1013        } else {
1014            StorageClass::empty()
1015        };
1016        let return_type = self.read_var_type(var_sc)?;
1017        let params = self.read_func_params()?;
1018        Ok(Type::NonMemberFunction(
1019            calling_conv,
1020            params,
1021            sc,
1022            Box::new(return_type),
1023        ))
1024    }
1025
1026    fn read_special_name(&mut self) -> Result<Name<'a>> {
1027        Ok(Name::Operator(match self.get()? {
1028            b'0' => Operator::Ctor,
1029            b'1' => Operator::Dtor,
1030            b'2' => Operator::New,
1031            b'3' => Operator::Delete,
1032            b'4' => Operator::Equal,
1033            b'5' => Operator::RShift,
1034            b'6' => Operator::LShift,
1035            b'7' => Operator::Bang,
1036            b'8' => Operator::EqualEqual,
1037            b'9' => Operator::BangEqual,
1038            b'A' => Operator::Subscript,
1039            b'B' => Operator::Conversion,
1040            b'C' => Operator::Arrow,
1041            b'D' => Operator::Star,
1042            b'E' => Operator::PlusPlus,
1043            b'F' => Operator::MinusMinus,
1044            b'G' => Operator::Minus,
1045            b'H' => Operator::Plus,
1046            b'I' => Operator::Amp,
1047            b'J' => Operator::ArrowStar,
1048            b'K' => Operator::Slash,
1049            b'L' => Operator::Percent,
1050            b'M' => Operator::Less,
1051            b'N' => Operator::LessEqual,
1052            b'O' => Operator::Greater,
1053            b'P' => Operator::GreaterEqual,
1054            b'Q' => Operator::Comma,
1055            b'R' => Operator::Call,
1056            b'S' => Operator::Tilde,
1057            b'T' => Operator::Caret,
1058            b'U' => Operator::Pipe,
1059            b'V' => Operator::AmpAmp,
1060            b'W' => Operator::PipePipe,
1061            b'X' => Operator::StarEqual,
1062            b'Y' => Operator::PlusEqual,
1063            b'Z' => Operator::MinusEqual,
1064            b'_' => match self.get()? {
1065                b'0' => Operator::SlashEqual,
1066                b'1' => Operator::PercentEqual,
1067                b'2' => Operator::GreaterGreaterEqual,
1068                b'3' => Operator::LessLessEqual,
1069                b'4' => Operator::AmpEqual,
1070                b'5' => Operator::PipeEqual,
1071                b'6' => Operator::CaretEqual,
1072                b'7' => Operator::VFTable,
1073                b'8' => Operator::VBTable,
1074                b'9' => Operator::VCall,
1075                b'A' => Operator::Typeof,
1076                b'B' => Operator::LocalStaticGuard(None),
1077                b'C' => Operator::String,
1078                b'D' => Operator::VBaseDtor,
1079                b'E' => Operator::VectorDeletingDtor,
1080                b'F' => Operator::DefaultCtorClosure,
1081                b'G' => Operator::ScalarDeletingDtor,
1082                b'H' => Operator::VectorCtorIterator,
1083                b'I' => Operator::VectorDtorIterator,
1084                b'J' => Operator::VectorVBaseCtorIterator,
1085                b'K' => Operator::VirtualDisplacementMap,
1086                b'L' => Operator::EHVectorCtorIterator,
1087                b'M' => Operator::EHVectorDtorIterator,
1088                b'N' => Operator::EHVectorVBaseCtorIterator,
1089                b'O' => Operator::CopyCtorClosure,
1090                b'R' => {
1091                    let c = self.get()?;
1092                    match c {
1093                        b'0' => {
1094                            self.expect(b"?")?;
1095                            let storage_class = self.read_storage_class();
1096                            let t = self.read_var_type(storage_class)?;
1097                            Operator::RTTITypeDescriptor(storage_class, Box::new(t))
1098                        }
1099                        b'1' => {
1100                            let nv_offset = self.read_number()?;
1101                            let vbptr_offset = self.read_number()?;
1102                            let vbtable_offset = self.read_number()?;
1103                            let flags = self.read_number()?;
1104                            Operator::RTTIBaseClassDescriptor(
1105                                nv_offset,
1106                                vbptr_offset,
1107                                vbtable_offset,
1108                                flags,
1109                            )
1110                        }
1111                        b'2' => Operator::RTTIBaseClassArray,
1112                        b'3' => Operator::RTTIClassHierarchyDescriptor,
1113                        b'4' => Operator::RTTIClassCompleteObjectLocator,
1114                        _ => {
1115                            return Err(self.fail("unknown RTTI Operator name"));
1116                        }
1117                    }
1118                }
1119                b'S' => Operator::LocalVFTable,
1120                b'T' => Operator::LocalVFTableCtorClosure,
1121                b'U' => Operator::ArrayNew,
1122                b'V' => Operator::ArrayDelete,
1123                b'X' => Operator::PlacementDeleteClosure,
1124                b'Y' => Operator::PlacementArrayDeleteClosure,
1125                b'_' => {
1126                    if self.consume(b"L") {
1127                        Operator::CoroutineAwait
1128                    } else if self.consume(b"E") {
1129                        Operator::DynamicInitializer
1130                    } else if self.consume(b"F") {
1131                        Operator::DynamicAtexitDtor
1132                    } else if self.consume(b"J") {
1133                        Operator::LocalStaticThreadGuard(None)
1134                    } else if self.consume(b"K") {
1135                        Operator::LiteralOperatorName // TODO: read <source-name>, that's the operator name
1136                    } else {
1137                        return Err(self.fail("unknown operator name"));
1138                    }
1139                }
1140                _ => {
1141                    return Err(self.fail("unknown operator name"));
1142                }
1143            },
1144            _ => {
1145                return Err(self.fail("unknown operator name"));
1146            }
1147        }))
1148    }
1149
1150    fn read_func_class(&mut self, c: u8) -> Result<FuncClass> {
1151        // TODO: need to figure out how to wrap up the adjustment.
1152        let mut read_thunk = |func_class| -> Result<FuncClass> {
1153            let _adjustment = self.read_number()?;
1154            Ok(func_class | FuncClass::THUNK)
1155        };
1156
1157        Ok(match c {
1158            b'A' => FuncClass::PRIVATE,
1159            b'B' => FuncClass::PRIVATE | FuncClass::FAR,
1160            b'C' => FuncClass::PRIVATE | FuncClass::STATIC,
1161            b'D' => FuncClass::PRIVATE | FuncClass::STATIC,
1162            b'E' => FuncClass::PRIVATE | FuncClass::VIRTUAL,
1163            b'F' => FuncClass::PRIVATE | FuncClass::VIRTUAL,
1164            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1165            b'G' => read_thunk(FuncClass::PRIVATE | FuncClass::VIRTUAL)?,
1166            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1167            b'H' => read_thunk(FuncClass::PRIVATE | FuncClass::VIRTUAL | FuncClass::FAR)?,
1168            b'I' => FuncClass::PROTECTED,
1169            b'J' => FuncClass::PROTECTED | FuncClass::FAR,
1170            b'K' => FuncClass::PROTECTED | FuncClass::STATIC,
1171            b'L' => FuncClass::PROTECTED | FuncClass::STATIC | FuncClass::FAR,
1172            b'M' => FuncClass::PROTECTED | FuncClass::VIRTUAL,
1173            b'N' => FuncClass::PROTECTED | FuncClass::VIRTUAL | FuncClass::FAR,
1174            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1175            b'O' => read_thunk(FuncClass::PROTECTED | FuncClass::VIRTUAL)?,
1176            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1177            b'P' => read_thunk(FuncClass::PROTECTED | FuncClass::VIRTUAL | FuncClass::FAR)?,
1178            b'Q' => FuncClass::PUBLIC,
1179            b'R' => FuncClass::PUBLIC | FuncClass::FAR,
1180            b'S' => FuncClass::PUBLIC | FuncClass::STATIC,
1181            b'T' => FuncClass::PUBLIC | FuncClass::STATIC | FuncClass::FAR,
1182            b'U' => FuncClass::PUBLIC | FuncClass::VIRTUAL,
1183            b'V' => FuncClass::PUBLIC | FuncClass::VIRTUAL | FuncClass::FAR,
1184            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1185            b'W' => read_thunk(FuncClass::PUBLIC | FuncClass::VIRTUAL)?,
1186            // TODO(mitsuhiko): llvm uses adjustor here instead of virtual
1187            b'X' => read_thunk(FuncClass::PUBLIC | FuncClass::VIRTUAL | FuncClass::FAR)?,
1188            b'Y' => FuncClass::GLOBAL,
1189            b'Z' => FuncClass::GLOBAL | FuncClass::FAR,
1190            _ => {
1191                return Err(self.fail("unknown func class"));
1192            }
1193        })
1194    }
1195
1196    fn read_qualifier(&mut self) -> StorageClass {
1197        let access_class = match self.peek() {
1198            Some(b'A') => StorageClass::empty(),
1199            Some(b'B') => StorageClass::CONST,
1200            Some(b'C') => StorageClass::VOLATILE,
1201            Some(b'D') => StorageClass::CONST | StorageClass::VOLATILE,
1202            Some(b'Q') => StorageClass::empty(),
1203            Some(b'R') => StorageClass::CONST,
1204            Some(b'S') => StorageClass::VOLATILE,
1205            Some(b'T') => StorageClass::CONST | StorageClass::VOLATILE,
1206            _ => return StorageClass::empty(),
1207        };
1208        self.advance(1);
1209        access_class
1210    }
1211
1212    fn read_calling_conv(&mut self) -> Result<CallingConv> {
1213        Ok(match self.get()? {
1214            b'A' => CallingConv::Cdecl,
1215            b'B' => CallingConv::Cdecl,
1216            b'C' => CallingConv::Pascal,
1217            b'E' => CallingConv::Thiscall,
1218            b'G' => CallingConv::Stdcall,
1219            b'I' => CallingConv::Fastcall,
1220            _ => {
1221                return Err(self.fail("unknown calling conv"));
1222            }
1223        })
1224    }
1225
1226    // <return-type> ::= <type>
1227    //               ::= @ # structors (they have no declared return type)
1228    fn read_func_return_type(&mut self, storage_class: StorageClass) -> Result<Type<'a>> {
1229        if self.consume(b"@") {
1230            Ok(Type::None)
1231        } else {
1232            self.read_var_type(storage_class)
1233        }
1234    }
1235
1236    fn read_storage_class(&mut self) -> StorageClass {
1237        let storage_class = match self.peek() {
1238            Some(b'A') => StorageClass::empty(),
1239            Some(b'B') => StorageClass::CONST,
1240            Some(b'C') => StorageClass::VOLATILE,
1241            Some(b'D') => StorageClass::CONST | StorageClass::VOLATILE,
1242            Some(b'E') => StorageClass::FAR,
1243            Some(b'F') => StorageClass::CONST | StorageClass::FAR,
1244            Some(b'G') => StorageClass::VOLATILE | StorageClass::FAR,
1245            Some(b'H') => StorageClass::CONST | StorageClass::VOLATILE | StorageClass::FAR,
1246            Some(b'Q') => StorageClass::empty(),
1247            Some(b'R') => StorageClass::CONST,
1248            Some(b'S') => StorageClass::VOLATILE,
1249            Some(b'T') => StorageClass::CONST | StorageClass::VOLATILE,
1250            _ => return StorageClass::empty(),
1251        };
1252        self.advance(1);
1253        storage_class
1254    }
1255
1256    fn read_storage_class_for_return(&mut self) -> Result<StorageClass> {
1257        if !self.consume(b"?") {
1258            return Ok(StorageClass::empty());
1259        }
1260
1261        Ok(match self.get()? {
1262            b'A' => StorageClass::empty(),
1263            b'B' => StorageClass::CONST,
1264            b'C' => StorageClass::VOLATILE,
1265            b'D' => StorageClass::CONST | StorageClass::VOLATILE,
1266            _ => {
1267                return Err(self.fail("unknown storage class"));
1268            }
1269        })
1270    }
1271
1272    fn read_member_function_pointer(&mut self, read_qualifiers: bool) -> Result<Type<'a>> {
1273        let symbol = self.read_name(true)?;
1274        let ptr64 = if self.consume(b"E") {
1275            StorageClass::PTR64
1276        } else {
1277            StorageClass::empty()
1278        };
1279        let (access_class, func_class) = if read_qualifiers {
1280            (self.read_qualifier() | ptr64, FuncClass::empty())
1281        } else {
1282            let c = self.get()?;
1283            (ptr64, self.read_func_class(c)?)
1284        };
1285        let calling_conv = self.read_calling_conv()?;
1286        let storage_class_for_return = self.read_storage_class_for_return()?;
1287        let return_type = self.read_func_return_type(storage_class_for_return)?;
1288        let params = self.read_func_params()?;
1289        Ok(Type::MemberFunctionPointer(
1290            symbol,
1291            func_class,
1292            calling_conv,
1293            params,
1294            access_class,
1295            Box::new(return_type),
1296        ))
1297    }
1298
1299    // Reads a variable type.
1300    fn read_var_type(&mut self, mut sc: StorageClass) -> Result<Type<'a>> {
1301        if self.consume(b"W4") {
1302            let name = self.read_name(false)?;
1303            return Ok(Type::Enum(name, sc));
1304        }
1305
1306        if self.consume(b"A6") {
1307            let func_type = self.read_func_type(false)?;
1308            return Ok(Type::Ref(Box::new(func_type), sc));
1309        }
1310
1311        if self.consume(b"P6") {
1312            let func_type = self.read_func_type(false)?;
1313            return Ok(Type::Ptr(Box::new(func_type), sc));
1314        }
1315
1316        if self.consume(b"P8") {
1317            return self.read_member_function_pointer(true);
1318        }
1319
1320        if self.consume(b"$") {
1321            if self.consume(b"0") {
1322                let n = self.read_number()?;
1323                return Ok(Type::Constant(n));
1324            }
1325            if self.consume(b"D") {
1326                let n = self.read_number()?;
1327                return Ok(Type::TemplateParameterWithIndex(n));
1328            }
1329            if self.consume(b"$BY") {
1330                return self.read_array();
1331            }
1332            if self.consume(b"$Q") {
1333                return Ok(Type::RValueRef(Box::new(self.read_pointee()?), sc));
1334            }
1335            if self.consume(b"S")
1336                || self.consume(b"$V")
1337                || self.consume(b"$Z")
1338                || self.consume(b"$$V")
1339            {
1340                return Ok(Type::EmptyParameterPack);
1341            }
1342            if self.consume(b"$T") {
1343                return Ok(Type::Nullptr);
1344            }
1345            if self.consume(b"$A6") {
1346                return self.read_func_type(false);
1347            }
1348            if self.consume(b"$A8@@") {
1349                return self.read_func_type(true);
1350            }
1351            if self.consume(b"$Y") {
1352                let name = self.read_name(true)?;
1353                return Ok(Type::Alias(name, sc));
1354            }
1355            // These next cases can fallthrough, so be careful adding new ones!
1356            if self.consume(b"$C") {
1357                sc = self.read_qualifier();
1358            } else if let Some(b'1' | b'H' | b'I' | b'J') = self.peek() {
1359                // Inheritance specifiers, which we don't need to remember.
1360                self.advance(1);
1361                self.expect(b"?")?;
1362                return self.read_member_function_pointer(false);
1363            }
1364        }
1365
1366        if self.consume(b"?") {
1367            let n = self.read_number()?;
1368            return Ok(Type::TemplateParameterWithIndex(-n));
1369        }
1370
1371        if let Some(n) = self.read_digit() {
1372            if n as usize >= self.memorized_types.len() {
1373                return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
1374            }
1375
1376            return Ok(self.memorized_types[n as usize].clone());
1377        }
1378
1379        Ok(match self.get()? {
1380            b'T' => Type::Union(self.read_name(false)?, sc),
1381            b'U' => Type::Struct(self.read_name(false)?, sc),
1382            b'V' => Type::Class(self.read_name(false)?, sc),
1383            b'A' => Type::Ref(Box::new(self.read_pointee()?), sc),
1384            b'B' => Type::Ref(Box::new(self.read_pointee()?), StorageClass::VOLATILE),
1385            b'P' => Type::Ptr(Box::new(self.read_pointee()?), sc),
1386            b'Q' => Type::Ptr(Box::new(self.read_pointee()?), StorageClass::CONST),
1387            b'R' => Type::Ptr(Box::new(self.read_pointee()?), StorageClass::VOLATILE),
1388            b'S' => Type::Ptr(
1389                Box::new(self.read_pointee()?),
1390                StorageClass::CONST | StorageClass::VOLATILE,
1391            ),
1392            b'Y' => self.read_array()?,
1393            b'X' => Type::Void(sc),
1394            b'D' => Type::Char(sc),
1395            b'C' => Type::Schar(sc),
1396            b'E' => Type::Uchar(sc),
1397            b'F' => Type::Short(sc),
1398            b'G' => Type::Ushort(sc),
1399            b'H' => Type::Int(sc),
1400            b'I' => Type::Uint(sc),
1401            b'J' => Type::Long(sc),
1402            b'K' => Type::Ulong(sc),
1403            b'M' => Type::Float(sc),
1404            b'N' => Type::Double(sc),
1405            b'O' => Type::Ldouble(sc),
1406            b'_' => match self.get()? {
1407                b'N' => Type::Bool(sc),
1408                b'J' => Type::Int64(sc),
1409                b'K' => Type::Uint64(sc),
1410                b'L' => Type::Int128(sc),
1411                b'M' => Type::Uint128(sc),
1412                b'W' => Type::Wchar(sc),
1413                b'Q' => Type::Char8(sc),
1414                b'S' => Type::Char16(sc),
1415                b'U' => Type::Char32(sc),
1416                _ => {
1417                    return Err(self.fail("unknown primitive type"));
1418                }
1419            },
1420            _c => {
1421                return Err(self.fail("unknown primitive type"));
1422            }
1423        })
1424    }
1425
1426    fn read_pointee(&mut self) -> Result<Type<'a>> {
1427        let ptr64 = if self.consume(b"E") {
1428            StorageClass::PTR64
1429        } else {
1430            StorageClass::empty()
1431        };
1432        let storage_class = self.read_storage_class();
1433        self.read_var_type(storage_class | ptr64)
1434    }
1435
1436    fn read_array(&mut self) -> Result<Type<'a>> {
1437        let dimension = self.read_number()?;
1438        if dimension <= 0 {
1439            return Err(self.fail_args(format_args!("invalid array dimension: {}", dimension)));
1440        }
1441        let (array, _) = self.read_nested_array(dimension)?;
1442        Ok(array)
1443    }
1444
1445    fn read_nested_array(&mut self, dimension: i32) -> Result<(Type<'a>, StorageClass)> {
1446        if dimension > 0 {
1447            let len = self.read_number()?;
1448            let (inner_array, storage_class) = self.read_nested_array(dimension - 1)?;
1449            Ok((
1450                Type::Array(len, Box::new(inner_array), storage_class),
1451                storage_class,
1452            ))
1453        } else {
1454            let storage_class = if self.consume(b"$$C") {
1455                if self.consume(b"B") {
1456                    StorageClass::CONST
1457                } else if self.consume(b"C") || self.consume(b"D") {
1458                    StorageClass::CONST | StorageClass::VOLATILE
1459                } else if !self.consume(b"A") {
1460                    return Err(self.fail("unknown storage class"));
1461                } else {
1462                    StorageClass::empty()
1463                }
1464            } else {
1465                StorageClass::empty()
1466            };
1467
1468            Ok((self.read_var_type(StorageClass::empty())?, storage_class))
1469        }
1470    }
1471
1472    // Reads a function or a template parameters.
1473    fn read_params(&mut self) -> Result<Params<'a>> {
1474        // println!("read_params on {}", str::from_utf8(self.input)?);
1475        // Within the same parameter list, you can backreference the first 10 types.
1476        // let mut backref: Vec<Type<'a>> = Vec::with_capacity(10);
1477
1478        let mut params: Vec<Type<'a>> = Vec::new();
1479
1480        while !self.remaining.starts_with(b"@")
1481            && !self.remaining.starts_with(b"Z")
1482            && !self.remaining.is_empty()
1483        {
1484            if let Some(n) = self.read_digit() {
1485                if n as usize >= self.memorized_types.len() {
1486                    return Err(self.fail_args(format_args!("invalid backreference: {}", n)));
1487                }
1488                // println!("reading a type from memorized_types[{}]. full list: {:#?}", n, self.memorized_types);
1489                params.push(self.memorized_types[n as usize].clone());
1490                continue;
1491            }
1492
1493            let len = self.remaining.len();
1494
1495            let param_type = self.read_var_type(StorageClass::empty())?;
1496
1497            // Single-letter types are ignored for backreferences because
1498            // memorizing them doesn't save anything.
1499            if len - self.remaining.len() > 1 {
1500                self.memorize_type(&param_type);
1501            }
1502            params.push(param_type);
1503        }
1504
1505        if self.consume(b"Z") {
1506            params.push(Type::VarArgs);
1507        } else if self.remaining.is_empty() {
1508            // this is needed to handle the weird standalone template manglings
1509        } else {
1510            self.expect(b"@")?;
1511        }
1512        Ok(Params { types: params })
1513    }
1514
1515    // Reads a function parameters.
1516    fn read_func_params(&mut self) -> Result<Params<'a>> {
1517        let params = if self.consume(b"X") {
1518            Params {
1519                types: vec![Type::Void(StorageClass::empty())],
1520            }
1521        } else {
1522            self.read_params()?
1523        };
1524
1525        self.expect(b"Z")?;
1526
1527        Ok(params)
1528    }
1529}
1530
1531pub fn demangle(input: &str, flags: DemangleFlags) -> Result<String> {
1532    Ok(serialize(&parse(input)?, flags))
1533}
1534
1535pub fn parse(input: &str) -> Result<ParseResult> {
1536    let mut state = ParserState {
1537        remaining: input.as_bytes(),
1538        input,
1539        offset: 0,
1540        memorized_names: Vec::with_capacity(10),
1541        memorized_types: Vec::with_capacity(10),
1542    };
1543    state.parse()
1544}
1545
1546pub fn serialize(input: &ParseResult, flags: DemangleFlags) -> String {
1547    let mut s = Vec::new();
1548    {
1549        let mut serializer = Serializer { flags, w: &mut s };
1550        serializer.serialize(input);
1551    }
1552    String::from_utf8(s).unwrap_or_else(|s| String::from_utf8_lossy(s.as_bytes()).into_owned())
1553}
1554
1555// Converts an AST to a string.
1556//
1557// Converting an AST representing a C++ type to a string is tricky due
1558// to the bad grammar of the C++ declaration inherited from C. You have
1559// to construct a string from inside to outside. For example, if a type
1560// X is a pointer to a function returning int, the order you create a
1561// string becomes something like this:
1562//
1563//   (1) X is a pointer: *X
1564//   (2) (1) is a function returning int: int (*X)()
1565//
1566// So you cannot construct a result just by appending strings to a result.
1567//
1568// To deal with this, we split the function into two. write_pre() writes
1569// the "first half" of type declaration, and write_post() writes the
1570// "second half". For example, write_pre() writes a return type for a
1571// function and write_post() writes an parameter list.
1572struct Serializer<'a> {
1573    flags: DemangleFlags,
1574    w: &'a mut Vec<u8>,
1575}
1576
1577impl Serializer<'_> {
1578    fn serialize(&mut self, parse_result: &ParseResult) {
1579        if !self
1580            .flags
1581            .intersects(DemangleFlags::NAME_ONLY | DemangleFlags::NO_FUNCTION_RETURNS)
1582        {
1583            self.write_pre(&parse_result.symbol_type);
1584        }
1585        self.write_name(&parse_result.symbol, Some(&parse_result.symbol_type));
1586        if !self.flags.contains(DemangleFlags::NAME_ONLY) {
1587            self.write_post(&parse_result.symbol_type);
1588        }
1589    }
1590
1591    fn write_calling_conv(&mut self, calling_conv: &CallingConv) {
1592        match self.w.last() {
1593            Some(b' ') | Some(b'(') => {}
1594            _ => self.w.push(b' '),
1595        }
1596        if !self.flags.contains(DemangleFlags::NO_MS_KEYWORDS) {
1597            match calling_conv {
1598                CallingConv::Cdecl => {
1599                    self.w.extend(b"__cdecl ");
1600                }
1601                CallingConv::Pascal => {
1602                    self.w.extend(b"__pascal ");
1603                }
1604                CallingConv::Thiscall => {
1605                    self.w.extend(b"__thiscall ");
1606                }
1607                CallingConv::Stdcall => {
1608                    self.w.extend(b"__stdcall ");
1609                }
1610                CallingConv::Fastcall => {
1611                    self.w.extend(b"__fastcall ");
1612                }
1613                CallingConv::_Regcall => {
1614                    self.w.extend(b"__regcall ");
1615                }
1616            };
1617        }
1618    }
1619
1620    // Write the "first half" of a given type.
1621    fn write_pre(&mut self, t: &Type) {
1622        let storage_class = match t {
1623            Type::None => return,
1624            Type::MemberFunction(func_class, calling_conv, _, _, ref inner) => {
1625                if func_class.contains(FuncClass::THUNK) {
1626                    self.w.extend(b"[thunk]: ")
1627                }
1628                if !self.flags.contains(DemangleFlags::NO_ACCESS_SPECIFIERS) {
1629                    if func_class.contains(FuncClass::PRIVATE) {
1630                        self.w.extend(b"private: ")
1631                    }
1632                    if func_class.contains(FuncClass::PROTECTED) {
1633                        self.w.extend(b"protected: ")
1634                    }
1635                    if func_class.contains(FuncClass::PUBLIC) {
1636                        self.w.extend(b"public: ")
1637                    }
1638                }
1639                if !self.flags.contains(DemangleFlags::NO_MEMBER_TYPE) {
1640                    if func_class.contains(FuncClass::STATIC) {
1641                        self.w.extend(b"static ")
1642                    }
1643                    if func_class.contains(FuncClass::VIRTUAL) {
1644                        self.w.extend(b"virtual ");
1645                    }
1646                }
1647                self.write_pre(inner);
1648                self.write_calling_conv(calling_conv);
1649                return;
1650            }
1651            Type::MemberFunctionPointer(ref symbol, _, calling_conv, _, _, ref inner) => {
1652                self.write_pre(inner);
1653                self.write_space();
1654                self.w.push(b'(');
1655                self.write_calling_conv(calling_conv);
1656                self.write_space();
1657                self.write_space();
1658                self.write_name(symbol, None);
1659                self.w.extend(b"::*");
1660                return;
1661            }
1662            Type::NonMemberFunction(calling_conv, _, _, ref inner) => {
1663                self.write_pre(inner);
1664                self.write_calling_conv(calling_conv);
1665                return;
1666            }
1667            Type::VCallThunk(_, calling_conv) => {
1668                self.w.extend(b"[thunk]: ");
1669                self.write_calling_conv(calling_conv);
1670                return;
1671            }
1672            Type::CXXVBTable(_, sc) => sc,
1673            Type::CXXVFTable(_, sc) => sc,
1674            Type::TemplateParameterWithIndex(n) => {
1675                self.w.extend(b"`template-parameter");
1676                self.w.extend(itoa::Buffer::new().format(*n).as_bytes());
1677                self.w.push(b'\'');
1678                return;
1679            }
1680            Type::ThreadSafeStaticGuard(num) => {
1681                self.w.extend(b"TSS");
1682                self.w.extend(itoa::Buffer::new().format(*num).as_bytes());
1683                return;
1684            }
1685            Type::Constant(n) => {
1686                self.w.extend(itoa::Buffer::new().format(*n).as_bytes());
1687                return;
1688            }
1689            Type::ConstantString(_) => {
1690                // We have no idea what the original encoding of the string is,
1691                // and undname doesn't even try to display anything.
1692                //self.w.extend(s);
1693                return;
1694            }
1695            Type::VarArgs => {
1696                self.w.extend(b"...");
1697                return;
1698            }
1699            Type::Ptr(ref inner, storage_class)
1700            | Type::Ref(ref inner, storage_class)
1701            | Type::RValueRef(ref inner, storage_class) => {
1702                // "[]" and "()" (for function parameters) take precedence over "*",
1703                // so "int *x(int)" means "x is a function returning int *". We need
1704                // parentheses to supercede the default precedence. (e.g. we want to
1705                // emit something like "int (*x)(int)".)
1706                match *inner.as_ref() {
1707                    Type::MemberFunction(_, calling_conv, _, _, ref inner)
1708                    | Type::NonMemberFunction(calling_conv, _, _, ref inner) => {
1709                        self.write_pre(inner);
1710                        self.write_space();
1711                        self.w.push(b'(');
1712                        self.write_calling_conv(&calling_conv);
1713                    }
1714                    Type::Array(_, _, _) => {
1715                        self.write_pre(inner);
1716                        self.write_space();
1717                        self.w.push(b'(');
1718                    }
1719                    _ => {
1720                        self.write_pre(inner);
1721                    }
1722                }
1723
1724                match t {
1725                    Type::Ptr(_, _) => {
1726                        if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1727                            self.write_space();
1728                        } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1729                            self.write_space_ptr();
1730                        }
1731                        self.w.push(b'*')
1732                    }
1733                    Type::Ref(_, _) => {
1734                        if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1735                            self.write_space();
1736                        } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1737                            self.write_space_ptr();
1738                        }
1739                        self.w.push(b'&')
1740                    }
1741                    Type::RValueRef(_, _) => {
1742                        if !self.flags.contains(DemangleFlags::HUG_TYPE) {
1743                            self.write_space();
1744                        } else if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1745                            self.write_space_ptr();
1746                        }
1747                        self.w.extend(b"&&")
1748                    }
1749                    _ => {}
1750                }
1751
1752                storage_class
1753            }
1754            Type::Array(_len, ref inner, storage_class) => {
1755                self.write_pre(inner);
1756                storage_class
1757            }
1758            Type::Var(ref inner, kind, sc) => {
1759                match kind {
1760                    VarStorageKind::PrivateStatic => self.w.extend(b"private: static "),
1761                    VarStorageKind::ProtectedStatic => self.w.extend(b"protected: static "),
1762                    VarStorageKind::PublicStatic => self.w.extend(b"public: static "),
1763                    VarStorageKind::Global | VarStorageKind::FunctionLocalStatic => {}
1764                }
1765                self.write_pre(inner);
1766                sc
1767            }
1768            Type::Alias(ref names, sc) => {
1769                self.write_name(names, None);
1770                sc
1771            }
1772            Type::Struct(ref names, sc) => {
1773                self.write_class(names, "struct");
1774                sc
1775            }
1776            Type::Union(ref names, sc) => {
1777                self.write_class(names, "union");
1778                sc
1779            }
1780            Type::Class(ref names, sc) => {
1781                self.write_class(names, "class");
1782                sc
1783            }
1784            Type::Enum(ref names, sc) => {
1785                self.write_class(names, "enum");
1786                sc
1787            }
1788            Type::Void(sc) => {
1789                self.w.extend(b"void");
1790                sc
1791            }
1792            Type::Bool(sc) => {
1793                self.w.extend(b"bool");
1794                sc
1795            }
1796            Type::Char(sc) => {
1797                self.w.extend(b"char");
1798                sc
1799            }
1800            Type::Schar(sc) => {
1801                self.w.extend(b"signed char");
1802                sc
1803            }
1804            Type::Uchar(sc) => {
1805                self.w.extend(b"unsigned char");
1806                sc
1807            }
1808            Type::Short(sc) => {
1809                self.w.extend(b"short");
1810                sc
1811            }
1812            Type::Ushort(sc) => {
1813                self.w.extend(b"unsigned short");
1814                sc
1815            }
1816            Type::Int(sc) => {
1817                self.w.extend(b"int");
1818                sc
1819            }
1820            Type::Uint(sc) => {
1821                self.w.extend(b"unsigned int");
1822                sc
1823            }
1824            Type::Long(sc) => {
1825                self.w.extend(b"long");
1826                sc
1827            }
1828            Type::Ulong(sc) => {
1829                self.w.extend(b"unsigned long");
1830                sc
1831            }
1832            Type::Int64(sc) => {
1833                if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1834                    self.w.extend(b"__int64");
1835                } else {
1836                    self.w.extend(b"int64_t");
1837                }
1838                sc
1839            }
1840            Type::Uint64(sc) => {
1841                if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1842                    self.w.extend(b"unsigned __int64");
1843                } else {
1844                    self.w.extend(b"uint64_t");
1845                }
1846                sc
1847            }
1848            Type::Int128(sc) => {
1849                if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1850                    self.w.extend(b"__int128");
1851                } else {
1852                    self.w.extend(b"int128_t");
1853                }
1854                sc
1855            }
1856            Type::Uint128(sc) => {
1857                if self.flags.contains(DemangleFlags::MS_TYPENAMES) {
1858                    self.w.extend(b"unsigned __int128");
1859                } else {
1860                    self.w.extend(b"uint128_t");
1861                }
1862                sc
1863            }
1864            Type::Wchar(sc) => {
1865                self.w.extend(b"wchar_t");
1866                sc
1867            }
1868            Type::Float(sc) => {
1869                self.w.extend(b"float");
1870                sc
1871            }
1872            Type::Double(sc) => {
1873                self.w.extend(b"double");
1874                sc
1875            }
1876            Type::Ldouble(sc) => {
1877                self.w.extend(b"long double");
1878                sc
1879            }
1880            Type::Char8(sc) => {
1881                self.w.extend(b"char8_t");
1882                sc
1883            }
1884            Type::Char16(sc) => {
1885                self.w.extend(b"char16_t");
1886                sc
1887            }
1888            Type::Char32(sc) => {
1889                self.w.extend(b"char32_t");
1890                sc
1891            }
1892            Type::Nullptr => {
1893                self.w.extend(b"std::nullptr_t");
1894                return;
1895            }
1896            Type::EmptyParameterPack => return,
1897            Type::RTTIType => return,
1898        };
1899
1900        if storage_class.contains(StorageClass::CONST) {
1901            if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1902                self.write_space_ptr();
1903            } else {
1904                self.write_space();
1905            }
1906            self.w.extend(b"const");
1907        }
1908        if storage_class.contains(StorageClass::VOLATILE) {
1909            if self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
1910                self.write_space_ptr();
1911            } else {
1912                self.write_space();
1913            }
1914            self.w.extend(b"volatile");
1915        }
1916    }
1917
1918    fn write_memfn_qualifiers(&mut self, sc: StorageClass) {
1919        let with_ptr64 = self.flags.contains(DemangleFlags::WITH_PTR64);
1920        if self.flags.contains(DemangleFlags::NO_THISTYPE) {
1921            // TODO: should probably check for NO_CV_THISTYPE and NO_MS_THISTYPE
1922            // separately but I don't know what exactly those affect.
1923            return;
1924        }
1925        let mut write_one_qual = |flag, s: &[u8]| {
1926            if sc.contains(flag) {
1927                self.write_space();
1928                self.w.extend(s);
1929            }
1930        };
1931
1932        write_one_qual(StorageClass::CONST, b"const");
1933        write_one_qual(StorageClass::VOLATILE, b"volatile");
1934        if with_ptr64 {
1935            write_one_qual(StorageClass::PTR64, b"__ptr64");
1936        }
1937        // __restrict is different than `restrict`, keep the underscores!
1938        write_one_qual(StorageClass::RESTRICT, b"__restrict");
1939        // TODO: undname prints ref-qualifiers tightly to previous qualifiers.
1940        write_one_qual(StorageClass::LVALUE_QUAL, b"&");
1941        write_one_qual(StorageClass::RVALUE_QUAL, b"&&");
1942    }
1943
1944    // Write the "second half" of a given type.
1945    fn write_post(&mut self, t: &Type) {
1946        match *t {
1947            Type::MemberFunction(_, _, ref params, sc, ref return_type)
1948            | Type::NonMemberFunction(_, ref params, sc, ref return_type) => {
1949                self.w.push(b'(');
1950                self.write_types(&params.types);
1951                self.w.push(b')');
1952
1953                self.write_memfn_qualifiers(sc);
1954                self.write_post(return_type);
1955            }
1956            Type::MemberFunctionPointer(_, _, _, ref params, sc, ref return_type) => {
1957                self.w.extend(b")(");
1958                self.write_types(&params.types);
1959                self.w.push(b')');
1960
1961                self.write_post(return_type);
1962
1963                if sc.contains(StorageClass::CONST) {
1964                    self.write_space();
1965                    self.w.extend(b"const");
1966                }
1967            }
1968            Type::CXXVBTable(ref names, _sc) => {
1969                self.write_scope(names);
1970                self.w.extend(b"\'}}"); // the rest of the "operator"
1971            }
1972            Type::Ptr(ref inner, _sc) | Type::Ref(ref inner, _sc) => {
1973                match *inner.as_ref() {
1974                    Type::MemberFunction(_, _, _, _, _)
1975                    | Type::NonMemberFunction(_, _, _, _)
1976                    | Type::Array(_, _, _) => {
1977                        self.w.push(b')');
1978                    }
1979                    _ => {}
1980                }
1981                self.write_post(inner);
1982            }
1983            Type::Array(len, ref inner, _sc) => {
1984                self.w.push(b'[');
1985                self.w.extend(itoa::Buffer::new().format(len).as_bytes());
1986                self.w.push(b']');
1987                self.write_post(inner);
1988            }
1989            Type::Var(ref inner, _kind, _sc) => {
1990                self.write_post(inner);
1991            }
1992            Type::CXXVFTable(ref names, _) => {
1993                if !names.names.is_empty() {
1994                    self.w.extend(b"{for `");
1995                    self.write_scope(names);
1996                    self.w.extend(b"'}");
1997                }
1998            }
1999            Type::VCallThunk(offset, _) => {
2000                self.w.push(b'{');
2001                self.w.extend(itoa::Buffer::new().format(offset).as_bytes());
2002                self.w.push(b',');
2003                if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2004                    self.w.push(b' ');
2005                }
2006                self.w.extend(b"{flat}}");
2007            }
2008            _ => {}
2009        }
2010    }
2011
2012    // Write a function or template parameter list.
2013    fn write_types(&mut self, types: &[Type]) {
2014        for (idx, param) in types
2015            .iter()
2016            .filter(|x| **x != Type::EmptyParameterPack)
2017            .enumerate()
2018        {
2019            if idx > 0 {
2020                self.w.push(b',');
2021                if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2022                    self.w.push(b' ');
2023                }
2024            }
2025            self.write_pre(param);
2026            self.write_post(param);
2027        }
2028    }
2029
2030    fn write_class(&mut self, names: &Symbol, s: &str) {
2031        if !self.flags.contains(DemangleFlags::NO_CLASS_TYPE) {
2032            self.w.extend(s.as_bytes());
2033            self.w.push(b' ');
2034        }
2035        self.write_name(names, None);
2036    }
2037
2038    fn write_space_pre(&mut self) {
2039        if let Some(&c) = self.w.last() {
2040            if char::from(c).is_ascii_alphabetic() || c == b'&' || c == b'>' || c == b')' {
2041                self.w.push(b' ');
2042            }
2043        }
2044    }
2045
2046    fn write_space_ptr(&mut self) {
2047        if let Some(&c) = self.w.last() {
2048            if char::from(c).is_ascii_alphabetic() || c == b'>' || c == b')' {
2049                self.w.push(b' ');
2050            }
2051        }
2052    }
2053
2054    fn write_space(&mut self) {
2055        if let Some(&c) = self.w.last() {
2056            if char::from(c).is_ascii_alphabetic()
2057                || c == b'*'
2058                || c == b'&'
2059                || c == b'>'
2060                || c == b')'
2061            {
2062                self.w.push(b' ');
2063            }
2064        }
2065    }
2066
2067    fn write_operator_name(&mut self, op: &Operator) {
2068        let s = match *op {
2069            Operator::Ctor => "ctor",
2070            Operator::Dtor => "dtor",
2071            Operator::New => "operator new",
2072            Operator::Delete => "operator delete",
2073            Operator::Equal => "operator=",
2074            Operator::RShift => "operator>>",
2075            Operator::LShift => "operator<<",
2076            Operator::Bang => "operator!",
2077            Operator::EqualEqual => "operator==",
2078            Operator::BangEqual => "operator!=",
2079            Operator::Subscript => "operator[]",
2080
2081            // this is special cased for most situations unless demangling
2082            // produced something really wacky
2083            Operator::Conversion => "operatorcast",
2084            Operator::Arrow => "operator->",
2085            Operator::Star => "operator*",
2086            Operator::PlusPlus => "operator++",
2087            Operator::MinusMinus => "operator--",
2088            Operator::Minus => "operator-",
2089            Operator::Plus => "operator+",
2090            Operator::Amp => "operator&",
2091            Operator::ArrowStar => "operator->*",
2092            Operator::Slash => "operator/",
2093            Operator::Percent => "operator%",
2094            Operator::Less => "operator<",
2095            Operator::LessEqual => "operator<=",
2096            Operator::Greater => "operator>",
2097            Operator::GreaterEqual => "operator>=",
2098            Operator::Comma => "operator,",
2099            Operator::Call => "operator()",
2100            Operator::Tilde => "operator~",
2101            Operator::Caret => "operator^",
2102            Operator::Pipe => "operator|",
2103            Operator::AmpAmp => "operator&&",
2104            Operator::PipePipe => "operator||",
2105            Operator::StarEqual => "operator*=",
2106            Operator::PlusEqual => "operator+=",
2107            Operator::MinusEqual => "operator-=",
2108            Operator::SlashEqual => "operator/=",
2109            Operator::PercentEqual => "operator%=",
2110            Operator::GreaterGreaterEqual => "operator>>=",
2111            Operator::LessLessEqual => "operator<<=",
2112            Operator::AmpEqual => "operator&=",
2113            Operator::PipeEqual => "operator|=",
2114            Operator::CaretEqual => "operator^=",
2115
2116            Operator::VFTable => "`vftable'",
2117            Operator::VBTable => "`vbtable'",
2118            Operator::VCall => "`vcall'",
2119            Operator::Typeof => "`typeof'",
2120            Operator::LocalStaticGuard(scope) => {
2121                self.w.extend(b"`local static guard'");
2122                if let Some(scope) = scope {
2123                    self.w.push(b'{');
2124                    self.w.extend(itoa::Buffer::new().format(scope).as_bytes());
2125                    self.w.push(b'}');
2126                }
2127                return;
2128            }
2129            Operator::String => "`string'",
2130            Operator::VBaseDtor => "`vbase destructor'",
2131            Operator::VectorDeletingDtor => "`vector deleting destructor'",
2132            Operator::DefaultCtorClosure => "`default constructor closure'",
2133            Operator::ScalarDeletingDtor => "`scalar deleting destructor'",
2134            Operator::VectorCtorIterator => "`vector constructor iterator'",
2135            Operator::VectorDtorIterator => "`vector destructor iterator'",
2136            Operator::VectorVBaseCtorIterator => "`vector vbase constructor iterator'",
2137            Operator::VirtualDisplacementMap => "`virtual displacement map'",
2138            Operator::EHVectorCtorIterator => "`eh vector constructor iterator'",
2139            Operator::EHVectorDtorIterator => "`eh vector destructor iterator'",
2140            Operator::EHVectorVBaseCtorIterator => "`eh vector vbase constructor iterator'",
2141            Operator::CopyCtorClosure => "`copy constructor closure'",
2142
2143            Operator::LocalVFTable => "`local vftable'",
2144            Operator::LocalVFTableCtorClosure => "`local vftable constructor closure'",
2145            Operator::ArrayNew => "operator new[]",
2146            Operator::ArrayDelete => "operator delete[]",
2147            Operator::PlacementDeleteClosure => "`placement delete closure'",
2148            Operator::PlacementArrayDeleteClosure => "`placement delete[] closure'",
2149
2150            Operator::CoroutineAwait => " co_await",
2151            Operator::LiteralOperatorName => "operator \"\"",
2152
2153            Operator::RTTITypeDescriptor(_, ref inner) => {
2154                self.write_pre(inner);
2155                // XXX(mitsuhiko): llvm uses a space here instead of `::`.  No
2156                // idea why, seems inconsistent
2157                self.w.extend(b"::`RTTI Type Descriptor'");
2158                return;
2159            }
2160            Operator::RTTIBaseClassDescriptor(nv_offset, vbptr_offset, vbtable_offset, flags) => {
2161                let sp = if self.flags.contains(DemangleFlags::SPACE_AFTER_COMMA) {
2162                    " "
2163                } else {
2164                    ""
2165                };
2166                self.w.extend(
2167                    format!(
2168                        "`RTTI Base Class Descriptor at ({},{}{},{}{},{}{})'",
2169                        nv_offset, sp, vbptr_offset, sp, vbtable_offset, sp, flags
2170                    )
2171                    .as_bytes(),
2172                );
2173                return;
2174            }
2175            Operator::RTTIBaseClassArray => "`RTTI Base Class Array'",
2176            Operator::RTTIClassHierarchyDescriptor => "`RTTI Class Hierarchy Descriptor'",
2177            Operator::RTTIClassCompleteObjectLocator => "`RTTI Complete Object Locator'",
2178
2179            Operator::DynamicInitializer => "`dynamic initializer'",
2180            Operator::DynamicAtexitDtor => "`dynamic atexit destructor'",
2181            Operator::LocalStaticThreadGuard(scope) => {
2182                self.w.extend(b"`local static thread guard'");
2183                if let Some(scope) = scope {
2184                    self.w.push(b'{');
2185                    self.w.extend(itoa::Buffer::new().format(scope).as_bytes());
2186                    self.w.push(b'}');
2187                }
2188                return;
2189            }
2190        };
2191        self.w.extend(s.as_bytes());
2192    }
2193
2194    fn write_one_name(&mut self, name: &Name) {
2195        match *name {
2196            Name::Md5(name) => {
2197                self.w.extend(b"??@");
2198                self.w.extend(name);
2199                self.w.push(b'@');
2200            }
2201            Name::Operator(ref op) => {
2202                self.write_space();
2203                self.write_operator_name(op);
2204            }
2205            Name::NonTemplate(name) => {
2206                self.w.extend(name);
2207            }
2208            Name::AsInterface(name) => {
2209                self.w.push(b'[');
2210                self.w.extend(name);
2211                self.w.push(b']');
2212            }
2213            Name::Template(ref name, ref params) => {
2214                self.write_one_name(name);
2215                self.write_tmpl_params(params);
2216            }
2217            Name::Discriminator(val) => {
2218                self.w.push(b'`');
2219                self.w.extend(itoa::Buffer::new().format(val).as_bytes());
2220                self.w.push(b'\'');
2221            }
2222            Name::ParsedName(ref val) => {
2223                self.w.push(b'`');
2224                self.serialize(val);
2225                self.w.push(b'\'');
2226            }
2227            Name::AnonymousNamespace(_) => {
2228                self.w.extend(b"`anonymous namespace'");
2229            }
2230        }
2231    }
2232
2233    fn write_scope(&mut self, names: &NameSequence) {
2234        // Print out namespaces or outer class names.
2235        let mut i = names.names.iter().rev();
2236        if let Some(name) = i.next() {
2237            self.write_one_name(name);
2238        }
2239        for name in i {
2240            self.w.extend(b"::");
2241            self.write_one_name(name);
2242        }
2243    }
2244
2245    // Write a name read by read_name().
2246    fn write_name(&mut self, names: &Symbol, ty: Option<&Type<'_>>) {
2247        if !self.flags.contains(DemangleFlags::SPACE_BEFORE_POINTER) {
2248            self.write_space_pre();
2249        } else {
2250            self.write_space_ptr();
2251        }
2252
2253        let mut was_literal_op = false;
2254        if let Name::Operator(Operator::LiteralOperatorName) = names.name {
2255            self.write_space();
2256            self.write_operator_name(&Operator::LiteralOperatorName);
2257            was_literal_op = true;
2258        }
2259
2260        self.write_scope(&names.scope);
2261
2262        if !names.scope.names.is_empty() && !was_literal_op {
2263            self.w.extend(b"::");
2264        }
2265
2266        match names.name {
2267            Name::Md5(name) => {
2268                self.w.extend(b"??@");
2269                self.w.extend(name);
2270                self.w.push(b'@');
2271            }
2272            Name::Operator(ref op) => {
2273                match *op {
2274                    Operator::Ctor => {
2275                        if let Some(prev) = names.scope.names.first() {
2276                            self.write_one_name(prev);
2277                        } else {
2278                            self.w.extend(b"[invalid]");
2279                        }
2280                    }
2281                    Operator::Dtor => {
2282                        if let Some(prev) = names.scope.names.first() {
2283                            self.w.push(b'~');
2284                            self.write_one_name(prev);
2285                        } else {
2286                            self.w.extend(b"[invalid]");
2287                        }
2288                    }
2289                    Operator::VBTable => {
2290                        self.w.extend(b"`vbtable'{for `");
2291                        // The rest will be written by write_post of the
2292                        // symbol type.
2293                    }
2294                    Operator::Conversion => {
2295                        if let Some(Type::MemberFunction(_, _, _, _, ref rv)) = ty {
2296                            self.w.extend(b"operator ");
2297                            self.write_pre(rv);
2298                            self.write_post(rv);
2299                        } else {
2300                            self.write_space();
2301                            self.write_operator_name(op);
2302                        }
2303                    }
2304                    Operator::LiteralOperatorName => {}
2305                    _ => {
2306                        self.write_space();
2307                        // Print out an overloaded operator.
2308                        self.write_operator_name(op);
2309                    }
2310                }
2311            }
2312            Name::NonTemplate(name) => {
2313                self.w.extend(name);
2314            }
2315            Name::AsInterface(name) => {
2316                self.w.push(b'[');
2317                self.w.extend(name);
2318                self.w.push(b']');
2319            }
2320            Name::Template(ref name, ref params) => {
2321                self.write_one_name(name);
2322                self.write_tmpl_params(params);
2323            }
2324            Name::Discriminator(val) => {
2325                self.w.push(b'`');
2326                self.w.extend(itoa::Buffer::new().format(val).as_bytes());
2327                self.w.push(b'\'');
2328            }
2329            Name::ParsedName(ref val) => {
2330                self.serialize(val);
2331            }
2332            Name::AnonymousNamespace(_) => {
2333                // this should never happen as they are handled elsewhere
2334                debug_assert!(false, "not supposed to be here");
2335            }
2336        }
2337    }
2338
2339    fn write_tmpl_params(&mut self, params: &Params<'_>) {
2340        self.w.push(b'<');
2341        if !params.types.is_empty() {
2342            self.write_types(&params.types);
2343            if let Some(&b'>') = self.w.last() {
2344                self.w.push(b' ');
2345            }
2346        }
2347        self.w.push(b'>');
2348    }
2349}
2350
2351// grammar from MicrosoftMangle.cpp:
2352
2353// <mangled-name> ::= ? <name> <type-encoding>
2354// <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
2355// <unqualified-name> ::= <operator-name>
2356//                    ::= <ctor-dtor-name>
2357//                    ::= <source-name>
2358//                    ::= <template-name>
2359// <operator-name> ::= ???
2360//                 ::= ?B # cast, the target type is encoded as the return type.
2361// <source-name> ::= <identifier> @
2362//
2363// mangleNestedName: calls into mangle, which is responsible for <mangled-name>, and into mangleUnqualifiedName
2364// <postfix> ::= <unqualified-name> [<postfix>]
2365//           ::= <substitution> [<postfix>]
2366//
2367// <template-name> ::= <unscoped-template-name> <template-args>
2368//                 ::= <substitution>
2369// <unscoped-template-name> ::= ?$ <unqualified-name>
2370// <type-encoding> ::= <function-class> <function-type>
2371//                 ::= <storage-class> <variable-type>
2372// <function-class>  ::= <member-function> E? # E designates a 64-bit 'this'
2373//                                            # pointer. in 64-bit mode *all*
2374//                                            # 'this' pointers are 64-bit.
2375//                   ::= <global-function>
2376// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
2377//                     <return-type> <argument-list> <throw-spec>
2378// <member-function> ::= A # private: near
2379//                   ::= B # private: far
2380//                   ::= C # private: static near
2381//                   ::= D # private: static far
2382//                   ::= E # private: near
2383//                   ::= F # private: far
2384//                   ::= I # near
2385//                   ::= J # far
2386//                   ::= K # static near
2387//                   ::= L # static far
2388//                   ::= M # near
2389//                   ::= N # far
2390//                   ::= Q # near
2391//                   ::= R # far
2392//                   ::= S # static near
2393//                   ::= T # static far
2394//                   ::= U # near
2395//                   ::= V # far
2396// <global-function> ::= Y # global near
2397//                   ::= Z # global far
2398// <storage-class> ::= 0  # private static member
2399//                 ::= 1  # protected static member
2400//                 ::= 2  # public static member
2401//                 ::= 3  # global
2402//                 ::= 4  # static local