1#![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 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 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 const DECODE_32_BIT = 0x0800;
156 const COMPLETE = 0x0000;
158 const NAME_ONLY = 0x1000;
160 const NO_ACCESS_SPECIFIERS = 0x0080;
162 const NO_CV_THISTYPE = 0x0040;
170 const NO_FUNCTION_RETURNS = 0x0004;
172 const NO_MEMBER_TYPE = 0x0200;
176 const NO_MS_KEYWORDS = 0x0002;
178 const NO_MS_THISTYPE = 0x0020;
180 const MS_TYPENAMES = 0x0400;
182 const NO_THISTYPE = Self::NO_MS_THISTYPE.bits() | Self::NO_CV_THISTYPE.bits();
188 const NO_CLASS_TYPE = 0x10_0000;
193 const SPACE_AFTER_COMMA = 0x20_0000;
195 const HUG_TYPE = 0x40_0000;
197 const SPACE_BEFORE_POINTER = 0x80_0000;
199 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#[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#[derive(Clone, Copy, Debug, PartialEq)]
242pub enum VarStorageKind {
243 PrivateStatic,
244 ProtectedStatic,
245 PublicStatic,
246 Global,
247 FunctionLocalStatic,
248}
249
250#[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, 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#[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 ), 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
467struct ParserState<'a> {
471 remaining: &'a [u8],
474
475 input: &'a str,
477
478 offset: usize,
480
481 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 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 let mut symbol = self.read_name(true)?;
548
549 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 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 Type::None
597 }
598 b'Y' => {
599 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 let char_bytes = match self.get()? {
614 b'0' => 1, b'1' => 2, _ => {
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 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 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()?; 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 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 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 fn memorize_name(&mut self, n: &Name<'a>) {
850 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 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 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)?; 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 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 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 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 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 } 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 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 b'G' => read_thunk(FuncClass::PRIVATE | FuncClass::VIRTUAL)?,
1166 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 b'O' => read_thunk(FuncClass::PROTECTED | FuncClass::VIRTUAL)?,
1176 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 b'W' => read_thunk(FuncClass::PUBLIC | FuncClass::VIRTUAL)?,
1186 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 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 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 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 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 fn read_params(&mut self) -> Result<Params<'a>> {
1474 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 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 if len - self.remaining.len() > 1 {
1500 self.memorize_type(¶m_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 } else {
1510 self.expect(b"@")?;
1511 }
1512 Ok(Params { types: params })
1513 }
1514
1515 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
1555struct 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 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 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 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 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 write_one_qual(StorageClass::RESTRICT, b"__restrict");
1939 write_one_qual(StorageClass::LVALUE_QUAL, b"&");
1941 write_one_qual(StorageClass::RVALUE_QUAL, b"&&");
1942 }
1943
1944 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(¶ms.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(¶ms.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"\'}}"); }
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 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 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 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 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 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 }
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 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 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(¶ms.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