1use super::{DemangleNodeType, DemangleOptions, DemangleWrite, ParseOptions};
4use crate::error::{self, Result};
5use crate::index_str::IndexStr;
6use crate::subs::{Substitutable, SubstitutionTable};
7use alloc::boxed::Box;
8use alloc::string::String;
9use alloc::vec::Vec;
10use core::cell::Cell;
11#[cfg(feature = "logging")]
12use core::cell::RefCell;
13use core::fmt::{self, Write};
14use core::hash::{Hash, Hasher};
15use core::mem;
16use core::ops;
17use core::ptr;
18use core::str;
19
20struct AutoLogParse;
21
22#[cfg(feature = "logging")]
23thread_local! {
24 static LOG_DEPTH: RefCell<usize> = RefCell::new(0);
25}
26
27impl AutoLogParse {
28 #[cfg(feature = "logging")]
29 fn new(production: &'static str, input: IndexStr<'_>) -> AutoLogParse {
30 LOG_DEPTH.with(|depth| {
31 if *depth.borrow() == 0 {
32 println!();
33 }
34
35 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
36 log!(
37 "{}({} \"{}\" {}",
38 indent,
39 production,
40 String::from_utf8_lossy(input.as_ref()),
41 input.len(),
42 );
43 *depth.borrow_mut() += 1;
44 });
45 AutoLogParse
46 }
47
48 #[cfg(not(feature = "logging"))]
49 #[inline(always)]
50 fn new(_: &'static str, _: IndexStr) -> AutoLogParse {
51 AutoLogParse
52 }
53}
54
55#[cfg(feature = "logging")]
56impl Drop for AutoLogParse {
57 fn drop(&mut self) {
58 LOG_DEPTH.with(|depth| {
59 *depth.borrow_mut() -= 1;
60 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
61 log!("{})", indent);
62 });
63 }
64}
65
66macro_rules! try_begin_parse {
74 ( $production:expr , $ctx:expr , $input:expr ) => {
75 let _log = AutoLogParse::new($production, $input);
76 let _auto_check_recursion = AutoParseRecursion::new($ctx)?;
77 };
78}
79
80struct AutoLogDemangle;
81
82impl AutoLogDemangle {
83 #[cfg(feature = "logging")]
84 fn new<P, W>(
85 production: &P,
86 ctx: &DemangleContext<W>,
87 scope: Option<ArgScopeStack>,
88 is_inner: bool,
89 ) -> AutoLogDemangle
90 where
91 P: ?Sized + fmt::Debug,
92 W: DemangleWrite,
93 {
94 LOG_DEPTH.with(|depth| {
95 if *depth.borrow() == 0 {
96 println!();
97 }
98
99 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
100 log!("{}(", indent);
101 log!(
102 "{} {}{:?}",
103 indent,
104 if is_inner { "as_inner: " } else { "" },
105 production
106 );
107 log!("{} inner = {:?}", indent, ctx.inner);
108 log!("{} scope = {:?}", indent, scope);
109
110 *depth.borrow_mut() += 1;
111 });
112 AutoLogDemangle
113 }
114
115 #[cfg(not(feature = "logging"))]
116 #[inline(always)]
117 fn new<P, W>(
118 _: &P,
119 _: &DemangleContext<W>,
120 _: Option<ArgScopeStack>,
121 _: bool,
122 ) -> AutoLogDemangle
123 where
124 P: ?Sized + fmt::Debug,
125 W: DemangleWrite,
126 {
127 AutoLogDemangle
128 }
129}
130
131#[cfg(feature = "logging")]
132impl Drop for AutoLogDemangle {
133 fn drop(&mut self) {
134 LOG_DEPTH.with(|depth| {
135 *depth.borrow_mut() -= 1;
136 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
137 log!("{})", indent);
138 });
139 }
140}
141
142macro_rules! try_begin_demangle {
145 ( $production:expr, $ctx:expr, $scope:expr ) => {{
146 let _log = AutoLogDemangle::new($production, $ctx, $scope, false);
147 &mut AutoParseDemangle::new($ctx)?
148 }};
149}
150
151macro_rules! try_begin_demangle_as_inner {
154 ( $production:expr, $ctx:expr, $scope:expr ) => {{
155 let _log = AutoLogDemangle::new($production, $ctx, $scope, true);
156 &mut AutoParseDemangle::new($ctx)?
157 }};
158}
159
160#[derive(Debug, Default, Clone, Copy)]
161struct ParseContextState {
162 recursion_level: u32,
165 in_conversion: bool,
167}
168
169#[derive(Debug, Clone)]
171pub struct ParseContext {
172 max_recursion: u32,
175 state: Cell<ParseContextState>,
177}
178
179impl ParseContext {
180 pub fn new(options: ParseOptions) -> ParseContext {
182 ParseContext {
183 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(96),
184 state: Cell::new(ParseContextState::default()),
185 }
186 }
187
188 pub fn recursion_level(&self) -> u32 {
190 self.state.get().recursion_level
191 }
192
193 #[inline]
194 fn enter_recursion(&self) -> error::Result<()> {
195 let mut state = self.state.get();
196 let new_recursion_level = state.recursion_level + 1;
197
198 if new_recursion_level >= self.max_recursion {
199 log!("Hit too much recursion at level {}", self.max_recursion);
200 Err(error::Error::TooMuchRecursion)
201 } else {
202 state.recursion_level = new_recursion_level;
203 self.state.set(state);
204 Ok(())
205 }
206 }
207
208 #[inline]
209 fn exit_recursion(&self) {
210 let mut state = self.state.get();
211 debug_assert!(state.recursion_level >= 1);
212 state.recursion_level -= 1;
213 self.state.set(state);
214 }
215
216 #[inline]
217 fn in_conversion(&self) -> bool {
218 self.state.get().in_conversion
219 }
220
221 fn set_in_conversion(&self, in_conversion: bool) -> bool {
222 let mut state = self.state.get();
223 let previously_in_conversion = state.in_conversion;
224 state.in_conversion = in_conversion;
225 self.state.set(state);
226 previously_in_conversion
227 }
228}
229
230struct AutoParseRecursion<'a>(&'a ParseContext);
234
235impl<'a> AutoParseRecursion<'a> {
236 #[inline]
237 fn new(ctx: &'a ParseContext) -> error::Result<AutoParseRecursion<'a>> {
238 ctx.enter_recursion()?;
239 Ok(AutoParseRecursion(ctx))
240 }
241}
242
243impl<'a> Drop for AutoParseRecursion<'a> {
244 #[inline]
245 fn drop(&mut self) {
246 self.0.exit_recursion();
247 }
248}
249
250#[doc(hidden)]
261pub trait Parse: Sized {
262 fn parse<'a, 'b>(
265 ctx: &'a ParseContext,
266 subs: &'a mut SubstitutionTable,
267 input: IndexStr<'b>,
268 ) -> Result<(Self, IndexStr<'b>)>;
269}
270
271trait GetTemplateArgs {
278 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>;
280}
281
282#[derive(Debug)]
289pub(crate) enum LeafName<'a> {
290 SourceName(&'a SourceName),
291 WellKnownComponent(&'a WellKnownComponent),
292 Closure(&'a ClosureTypeName),
293 UnnamedType(&'a UnnamedTypeName),
294}
295
296impl<'subs, W> DemangleAsLeaf<'subs, W> for LeafName<'subs>
297where
298 W: 'subs + DemangleWrite,
299{
300 fn demangle_as_leaf<'me, 'ctx>(
301 &'me self,
302 ctx: &'ctx mut DemangleContext<'subs, W>,
303 ) -> fmt::Result {
304 match *self {
305 LeafName::SourceName(sn) => sn.demangle(ctx, None),
306 LeafName::Closure(c) => c.demangle(ctx, None),
307 LeafName::WellKnownComponent(wkc) => wkc.demangle_as_leaf(ctx),
308 LeafName::UnnamedType(utn) => utn.demangle_as_leaf(ctx),
309 }
310 }
311}
312
313pub(crate) trait GetLeafName<'a> {
316 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>;
317}
318
319pub(crate) trait IsCtorDtorConversion {
322 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool;
323}
324
325trait ArgScope<'me, 'ctx>: fmt::Debug {
340 fn leaf_name(&'me self) -> Result<LeafName<'ctx>>;
342
343 fn get_template_arg(&'me self, index: usize)
345 -> Result<(&'ctx TemplateArg, &'ctx TemplateArgs)>;
346
347 fn get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>;
349}
350
351#[derive(Copy, Clone, Debug)]
357pub struct ArgScopeStack<'prev, 'subs>
358where
359 'subs: 'prev,
360{
361 item: &'subs dyn ArgScope<'subs, 'subs>,
362 in_arg: Option<(usize, &'subs TemplateArgs)>,
363 prev: Option<&'prev ArgScopeStack<'prev, 'subs>>,
364}
365
366trait ArgScopeStackExt<'prev, 'subs>: Copy {
375 fn push(
378 &'prev self,
379 item: &'subs dyn ArgScope<'subs, 'subs>,
380 ) -> Option<ArgScopeStack<'prev, 'subs>>;
381}
382
383impl<'prev, 'subs> ArgScopeStackExt<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
384 fn push(
385 &'prev self,
386 item: &'subs dyn ArgScope<'subs, 'subs>,
387 ) -> Option<ArgScopeStack<'prev, 'subs>> {
388 log!("ArgScopeStack::push: {:?}", item);
389 Some(ArgScopeStack {
390 prev: self.as_ref(),
391 in_arg: None,
392 item: item,
393 })
394 }
395}
396
397impl<'prev, 'subs> ArgScope<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
399 fn leaf_name(&'prev self) -> Result<LeafName<'subs>> {
400 let mut scope = self.as_ref();
401 while let Some(s) = scope {
402 if let Ok(c) = s.item.leaf_name() {
403 return Ok(c);
404 }
405 scope = s.prev;
406 }
407 Err(error::Error::BadLeafNameReference)
408 }
409
410 fn get_template_arg(
411 &'prev self,
412 idx: usize,
413 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
414 let mut scope = self.as_ref();
415 while let Some(s) = scope {
416 if let Ok((arg, args)) = s.item.get_template_arg(idx) {
417 if let Some((in_idx, in_args)) = s.in_arg {
418 if args as *const TemplateArgs == in_args as *const TemplateArgs
419 && in_idx <= idx
420 {
421 return Err(error::Error::ForwardTemplateArgReference);
422 }
423 }
424 return Ok((arg, args));
425 }
426 scope = s.prev;
427 }
428
429 Err(error::Error::BadTemplateArgReference)
430 }
431
432 fn get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type> {
433 let mut scope = self.as_ref();
434 while let Some(s) = scope {
435 if let Ok(arg) = s.item.get_function_arg(idx) {
436 return Ok(arg);
437 }
438 scope = s.prev;
439 }
440
441 Err(error::Error::BadFunctionArgReference)
442 }
443}
444
445#[derive(Debug, Copy, Clone)]
446struct DemangleState {
447 pub recursion_level: u32,
449}
450
451struct AutoParseDemangle<'a, 'b, W: 'a + DemangleWrite>(&'b mut DemangleContext<'a, W>);
455
456impl<'a, 'b, W: 'a + DemangleWrite> AutoParseDemangle<'a, 'b, W> {
457 #[inline]
458 fn new(ctx: &'b mut DemangleContext<'a, W>) -> core::result::Result<Self, fmt::Error> {
459 ctx.enter_recursion()?;
460 Ok(AutoParseDemangle(ctx))
461 }
462}
463
464impl<'a, 'b, W: 'a + DemangleWrite> ops::Deref for AutoParseDemangle<'a, 'b, W> {
465 type Target = DemangleContext<'a, W>;
466
467 fn deref(&self) -> &Self::Target {
468 self.0
469 }
470}
471
472impl<'a, 'b, W: 'a + DemangleWrite> ops::DerefMut for AutoParseDemangle<'a, 'b, W> {
473 fn deref_mut(&mut self) -> &mut Self::Target {
474 self.0
475 }
476}
477
478impl<'a, 'b, W: 'a + DemangleWrite> Drop for AutoParseDemangle<'a, 'b, W> {
479 #[inline]
480 fn drop(&mut self) {
481 self.0.exit_recursion();
482 }
483}
484
485#[doc(hidden)]
487#[derive(Debug)]
488pub struct DemangleContext<'a, W>
489where
490 W: 'a + DemangleWrite,
491{
492 subs: &'a SubstitutionTable,
495
496 max_recursion: u32,
498
499 inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
515
516 input: &'a [u8],
518
519 source_name: Option<&'a str>,
522
523 out: &'a mut W,
525
526 bytes_written: usize,
529
530 last_char_written: Option<char>,
532
533 is_lambda_arg: bool,
536
537 is_template_prefix: bool,
539
540 is_template_prefix_in_nested_name: bool,
542
543 is_template_argument_pack: bool,
546
547 show_params: bool,
551
552 show_return_type: bool,
556
557 show_expression_literal_types: bool,
559
560 state: Cell<DemangleState>,
562}
563
564impl<'a, W> fmt::Write for DemangleContext<'a, W>
565where
566 W: 'a + DemangleWrite,
567{
568 fn write_str(&mut self, s: &str) -> fmt::Result {
569 if s.is_empty() {
570 return Ok(());
571 }
572
573 log!("DemangleContext::write: '{}'", s);
574
575 self.out.write_string(s).map(|_| {
576 self.last_char_written = s.chars().last();
577 self.bytes_written += s.len();
578 })
579 }
580}
581
582impl<'a, W> DemangleContext<'a, W>
583where
584 W: 'a + DemangleWrite,
585{
586 pub fn new(
588 subs: &'a SubstitutionTable,
589 input: &'a [u8],
590 options: DemangleOptions,
591 out: &'a mut W,
592 ) -> DemangleContext<'a, W> {
593 DemangleContext {
594 subs: subs,
595 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(128),
596 inner: vec![],
597 input: input,
598 source_name: None,
599 out: out,
600 bytes_written: 0,
601 last_char_written: None,
602 is_lambda_arg: false,
603 is_template_prefix: false,
604 is_template_prefix_in_nested_name: false,
605 is_template_argument_pack: false,
606 show_params: !options.no_params,
607 show_return_type: !options.no_return_type,
608 show_expression_literal_types: !options.hide_expression_literal_types,
609 state: Cell::new(DemangleState { recursion_level: 0 }),
610 }
611 }
612
613 pub fn recursion_level(&self) -> u32 {
615 self.state.get().recursion_level
616 }
617
618 #[inline]
619 fn enter_recursion(&self) -> fmt::Result {
620 let mut state = self.state.get();
621 let new_recursion_level = state.recursion_level + 1;
622
623 if new_recursion_level >= self.max_recursion {
624 log!("Hit too much recursion at level {}", self.max_recursion);
625 Err(Default::default())
626 } else {
627 state.recursion_level = new_recursion_level;
628 self.state.set(state);
629 Ok(())
630 }
631 }
632
633 #[inline]
634 fn exit_recursion(&self) {
635 let mut state = self.state.get();
636 debug_assert!(state.recursion_level >= 1);
637 state.recursion_level -= 1;
638 self.state.set(state);
639 }
640
641 #[inline]
642 fn ensure(&mut self, ch: char) -> fmt::Result {
643 if self.last_char_written == Some(ch) {
644 Ok(())
645 } else {
646 write!(self, "{}", ch)?;
647 Ok(())
648 }
649 }
650
651 #[inline]
652 fn ensure_space(&mut self) -> fmt::Result {
653 self.ensure(' ')
654 }
655
656 #[inline]
657 fn push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>) {
658 log!("DemangleContext::push_inner: {:?}", item);
659 self.inner.push(item);
660 }
661
662 #[inline]
663 fn pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>> {
664 let popped = self.inner.pop();
665 log!("DemangleContext::pop_inner: {:?}", popped);
666 popped
667 }
668
669 #[inline]
670 fn pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool {
671 let last = match self.inner.last() {
672 None => return false,
673 Some(last) => *last,
674 };
675
676 if ptr::eq(last, inner) {
677 self.inner.pop();
678 true
679 } else {
680 false
681 }
682 }
683
684 fn demangle_inner_prefixes<'prev>(
685 &mut self,
686 scope: Option<ArgScopeStack<'prev, 'a>>,
687 ) -> fmt::Result {
688 log!("DemangleContext::demangle_inner_prefixes");
689 let mut new_inner = vec![];
690 while let Some(inner) = self.pop_inner() {
691 if inner
692 .downcast_to_function_type()
693 .map_or(false, |f| !f.cv_qualifiers.is_empty())
694 {
695 log!(
696 "DemangleContext::demangle_inner_prefixes: not a prefix, saving: {:?}",
697 inner
698 );
699 new_inner.push(inner);
700 } else {
701 log!(
702 "DemangleContext::demangle_inner_prefixes: demangling prefix: {:?}",
703 inner
704 );
705 inner.demangle_as_inner(self, scope)?;
706 }
707 }
708 new_inner.reverse();
709 self.inner = new_inner;
710 Ok(())
711 }
712
713 fn demangle_inners<'prev>(&mut self, scope: Option<ArgScopeStack<'prev, 'a>>) -> fmt::Result {
714 while let Some(inner) = self.pop_inner() {
715 inner.demangle_as_inner(self, scope)?;
716 }
717 Ok(())
718 }
719
720 fn set_source_name(&mut self, start: usize, end: usize) {
721 let ident = &self.input[start..end];
722 self.source_name = str::from_utf8(ident).ok();
723 }
724
725 fn push_demangle_node(&mut self, t: DemangleNodeType) {
726 self.out.push_demangle_node(t);
727 }
728
729 fn pop_demangle_node(&mut self) {
732 self.out.pop_demangle_node();
733 }
734}
735
736#[doc(hidden)]
737#[derive(Debug)]
738pub struct AutoDemangleContextInnerBarrier<'ctx, 'a, W>
739where
740 W: 'a + DemangleWrite,
741 'a: 'ctx,
742{
743 ctx: &'ctx mut DemangleContext<'a, W>,
744 saved_inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
745}
746
747impl<'ctx, 'a, W> AutoDemangleContextInnerBarrier<'ctx, 'a, W>
748where
749 W: 'a + DemangleWrite,
750 'a: 'ctx,
751{
752 pub fn new(ctx: &'ctx mut DemangleContext<'a, W>) -> Self {
754 let mut saved_inner = vec![];
755 mem::swap(&mut saved_inner, &mut ctx.inner);
756 AutoDemangleContextInnerBarrier {
757 ctx: ctx,
758 saved_inner: saved_inner,
759 }
760 }
761}
762
763impl<'ctx, 'a, W> ops::Deref for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
764where
765 W: 'a + DemangleWrite,
766 'a: 'ctx,
767{
768 type Target = DemangleContext<'a, W>;
769
770 fn deref(&self) -> &Self::Target {
771 self.ctx
772 }
773}
774
775impl<'ctx, 'a, W> ops::DerefMut for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
776where
777 W: 'a + DemangleWrite,
778 'a: 'ctx,
779{
780 fn deref_mut(&mut self) -> &mut Self::Target {
781 self.ctx
782 }
783}
784
785impl<'ctx, 'a, W> Drop for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
786where
787 W: 'a + DemangleWrite,
788 'a: 'ctx,
789{
790 fn drop(&mut self) {
791 if !self.ctx.inner.is_empty() {
795 log!("Context inner was not emptied, did demangling fail?");
796 }
797 mem::swap(&mut self.saved_inner, &mut self.ctx.inner);
798 }
799}
800
801macro_rules! inner_barrier {
818 ( $ctx:ident ) => {
819 let mut _ctx = AutoDemangleContextInnerBarrier::new($ctx);
820 let $ctx = &mut _ctx;
821 };
822}
823
824#[doc(hidden)]
826pub trait Demangle<'subs, W>: fmt::Debug
827where
828 W: 'subs + DemangleWrite,
829{
830 fn demangle<'prev, 'ctx>(
832 &'subs self,
833 ctx: &'ctx mut DemangleContext<'subs, W>,
834 scope: Option<ArgScopeStack<'prev, 'subs>>,
835 ) -> fmt::Result;
836}
837
838#[doc(hidden)]
842pub trait DemangleAsInner<'subs, W>: Demangle<'subs, W>
843where
844 W: 'subs + DemangleWrite,
845{
846 fn demangle_as_inner<'prev, 'ctx>(
848 &'subs self,
849 ctx: &'ctx mut DemangleContext<'subs, W>,
850 scope: Option<ArgScopeStack<'prev, 'subs>>,
851 ) -> fmt::Result {
852 self.demangle(ctx, scope)
853 }
854
855 fn downcast_to_type(&self) -> Option<&Type> {
857 None
858 }
859
860 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
862 None
863 }
864
865 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
867 None
868 }
869
870 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
872 None
873 }
874
875 fn is_qualified(&self) -> bool {
876 false
877 }
878}
879
880pub(crate) trait DemangleAsLeaf<'subs, W>
886where
887 W: 'subs + DemangleWrite,
888{
889 fn demangle_as_leaf<'me, 'ctx>(
890 &'me self,
891 ctx: &'ctx mut DemangleContext<'subs, W>,
892 ) -> fmt::Result;
893}
894
895macro_rules! reference_newtype {
896 ( $newtype_name:ident , $oldtype:ty ) => {
897 #[derive(Debug)]
898 struct $newtype_name($oldtype);
899
900 impl $newtype_name {
901 #[allow(clippy::ptr_arg)]
902 #[allow(unsafe_code)]
903 fn new(types: &$oldtype) -> &$newtype_name {
904 unsafe {
905 &*(types as *const $oldtype as *const $newtype_name)
911 }
912 }
913 }
914
915 impl Drop for $newtype_name {
916 fn drop(&mut self) {
917 unreachable!(
918 "Dropping implies we dereferenced and took ownership, which \
919 is not safe for this newtype"
920 );
921 }
922 }
923
924 impl ops::Deref for $newtype_name {
925 type Target = $oldtype;
926
927 fn deref(&self) -> &Self::Target {
928 &self.0
929 }
930 }
931 };
932}
933
934reference_newtype!(FunctionArgList, Vec<TypeHandle>);
941
942reference_newtype!(FunctionArgListAndReturnType, Vec<TypeHandle>);
945
946reference_newtype!(FunctionArgSlice, [TypeHandle]);
949
950impl<'subs, W> Demangle<'subs, W> for FunctionArgSlice
952where
953 W: 'subs + DemangleWrite,
954{
955 fn demangle<'prev, 'ctx>(
956 &'subs self,
957 ctx: &'ctx mut DemangleContext<'subs, W>,
958 scope: Option<ArgScopeStack<'prev, 'subs>>,
959 ) -> fmt::Result {
960 let ctx = try_begin_demangle!(self, ctx, scope);
961
962 let mut saw_needs_paren = false;
963 let (needs_space, needs_paren) = ctx
964 .inner
965 .iter()
966 .rev()
967 .map(|inner| {
968 if inner.downcast_to_pointer_to_member().is_some() {
969 (true, true)
970 } else {
971 match inner.downcast_to_type() {
972 Some(&Type::Qualified(..))
973 | Some(&Type::Complex(_))
974 | Some(&Type::Imaginary(_))
975 | Some(&Type::PointerToMember(_)) => (true, true),
976 Some(&Type::PointerTo(_))
977 | Some(&Type::LvalueRef(_))
978 | Some(&Type::RvalueRef(_)) => (false, true),
979 _ => (false, false),
980 }
981 }
982 })
983 .take_while(|&(_, needs_paren)| {
984 if saw_needs_paren {
985 false
986 } else {
987 saw_needs_paren |= needs_paren;
988 true
989 }
990 })
991 .fold(
992 (false, false),
993 |(space, paren), (next_space, next_paren)| {
994 (space || next_space, paren || next_paren)
995 },
996 );
997
998 if needs_paren {
999 let needs_space = needs_space
1000 || match ctx.last_char_written {
1001 Some('(') | Some('*') => false,
1002 _ => true,
1003 };
1004
1005 if needs_space {
1006 ctx.ensure_space()?;
1007 }
1008
1009 write!(ctx, "(")?;
1010 }
1011
1012 ctx.demangle_inner_prefixes(scope)?;
1013
1014 if needs_paren {
1015 write!(ctx, ")")?;
1016 }
1017
1018 write!(ctx, "(")?;
1019
1020 if self.len() == 1 && self[0].is_void() {
1023 write!(ctx, ")")?;
1024 return Ok(());
1025 }
1026
1027 let mut need_comma = false;
1028 for arg in self.iter() {
1029 if need_comma {
1030 write!(ctx, ", ")?;
1031 }
1032 arg.demangle(ctx, scope)?;
1033 need_comma = true;
1034 }
1035
1036 write!(ctx, ")")?;
1037
1038 ctx.demangle_inners(scope)
1039 }
1040}
1041
1042impl<'subs, W> Demangle<'subs, W> for FunctionArgList
1043where
1044 W: 'subs + DemangleWrite,
1045{
1046 fn demangle<'prev, 'ctx>(
1047 &'subs self,
1048 ctx: &'ctx mut DemangleContext<'subs, W>,
1049 scope: Option<ArgScopeStack<'prev, 'subs>>,
1050 ) -> fmt::Result {
1051 FunctionArgSlice::new(&self.0[..]).demangle(ctx, scope)
1052 }
1053}
1054
1055impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgList where W: 'subs + DemangleWrite {}
1056
1057impl<'subs, W> Demangle<'subs, W> for FunctionArgListAndReturnType
1058where
1059 W: 'subs + DemangleWrite,
1060{
1061 fn demangle<'prev, 'ctx>(
1062 &'subs self,
1063 ctx: &'ctx mut DemangleContext<'subs, W>,
1064 scope: Option<ArgScopeStack<'prev, 'subs>>,
1065 ) -> fmt::Result {
1066 FunctionArgSlice::new(&self.0[1..]).demangle(ctx, scope)
1067 }
1068}
1069
1070impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgListAndReturnType where
1071 W: 'subs + DemangleWrite
1072{
1073}
1074
1075macro_rules! define_handle {
1086 (
1087 $(#[$attr:meta])*
1088 pub enum $typename:ident
1089 ) => {
1090 define_handle! {
1091 $(#[$attr])*
1092 pub enum $typename {}
1093 }
1094 };
1095
1096 (
1097 $(#[$attr:meta])*
1098 pub enum $typename:ident {
1099 $(
1100 $( #[$extra_attr:meta] )*
1101 extra $extra_variant:ident ( $extra_variant_ty:ty ),
1102 )*
1103 }
1104 ) => {
1105 $(#[$attr])*
1106 #[derive(Clone, Debug, PartialEq, Eq)]
1107 pub enum $typename {
1108 WellKnown(WellKnownComponent),
1110
1111 BackReference(usize),
1114
1115 $(
1116 $( #[$extra_attr] )*
1117 $extra_variant( $extra_variant_ty ),
1118 )*
1119 }
1120
1121 impl $typename {
1122 pub fn back_reference(&self) -> Option<usize> {
1124 match *self {
1125 $typename::BackReference(n) => Some(n),
1126 _ => None,
1127 }
1128 }
1129 }
1130
1131 impl<'subs, W> Demangle<'subs, W> for $typename
1132 where
1133 W: 'subs + DemangleWrite
1134 {
1135 #[inline]
1136 fn demangle<'prev, 'ctx>(&'subs self,
1137 ctx: &'ctx mut DemangleContext<'subs, W>,
1138 scope: Option<ArgScopeStack<'prev, 'subs>>)
1139 -> fmt::Result {
1140 match *self {
1141 $typename::WellKnown(ref comp) => comp.demangle(ctx, scope),
1142 $typename::BackReference(idx) => ctx.subs[idx].demangle(ctx, scope),
1143 $(
1144 $typename::$extra_variant(ref extra) => extra.demangle(ctx, scope),
1145 )*
1146 }
1147 }
1148 }
1149
1150 impl<'a> GetLeafName<'a> for $typename {
1151 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1152 match *self {
1153 $typename::WellKnown(ref wk) => wk.get_leaf_name(subs),
1154 $typename::BackReference(idx) => {
1155 subs.get(idx).and_then(|s| s.get_leaf_name(subs))
1156 }
1157 $(
1158 $typename::$extra_variant(ref e) => e.get_leaf_name(subs),
1159 )*
1160 }
1161 }
1162 }
1163 };
1164}
1165
1166#[derive(Clone, Debug, PartialEq, Eq)]
1170pub struct NonSubstitution(usize);
1171
1172impl<'subs, W> Demangle<'subs, W> for NonSubstitution
1173where
1174 W: 'subs + DemangleWrite,
1175{
1176 fn demangle<'prev, 'ctx>(
1177 &'subs self,
1178 ctx: &'ctx mut DemangleContext<'subs, W>,
1179 scope: Option<ArgScopeStack<'prev, 'subs>>,
1180 ) -> fmt::Result {
1181 ctx.subs.non_substitution(self.0).demangle(ctx, scope)
1182 }
1183}
1184
1185impl<'a> GetLeafName<'a> for NonSubstitution {
1186 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1187 subs.get_non_substitution(self.0)
1188 .and_then(|ns| ns.get_leaf_name(subs))
1189 }
1190}
1191
1192macro_rules! define_vocabulary {
1207 ( $(#[$attr:meta])* pub enum $typename:ident {
1208 $($variant:ident ( $mangled:expr, $printable:expr )),*
1209 } ) => {
1210
1211 $(#[$attr])*
1212 pub enum $typename {
1213 $(
1214 #[doc=$printable]
1215 $variant
1216 ),*
1217 }
1218
1219 impl Parse for $typename {
1220 fn parse<'a, 'b>(ctx: &'a ParseContext,
1221 _subs: &'a mut SubstitutionTable,
1222 input: IndexStr<'b>)
1223 -> Result<($typename, IndexStr<'b>)> {
1224 try_begin_parse!(stringify!($typename), ctx, input);
1225
1226 let mut found_prefix = false;
1227 $(
1228 if let Some((head, tail)) = input.try_split_at($mangled.len()) {
1229 if head.as_ref() == $mangled {
1230 return Ok(($typename::$variant, tail));
1231 }
1232 } else {
1233 found_prefix |= 0 < input.len() &&
1234 input.len() < $mangled.len() &&
1235 input.as_ref() == &$mangled[..input.len()];
1236 }
1237 )*
1238
1239 if input.is_empty() || found_prefix {
1240 Err(error::Error::UnexpectedEnd)
1241 } else {
1242 Err(error::Error::UnexpectedText)
1243 }
1244 }
1245 }
1246
1247 impl<'subs, W> Demangle<'subs, W> for $typename
1248 where
1249 W: 'subs + DemangleWrite,
1250 {
1251 fn demangle<'prev, 'ctx>(
1252 &'subs self,
1253 ctx: &'ctx mut DemangleContext<'subs, W>,
1254 scope: Option<ArgScopeStack<'prev, 'subs>>
1255 ) -> fmt::Result {
1256 let ctx = try_begin_demangle!(self, ctx, scope);
1257
1258 write!(ctx, "{}", match *self {
1259 $(
1260 $typename::$variant => $printable
1261 ),*
1262 })
1263 }
1264 }
1265
1266 impl $typename {
1267 #[allow(dead_code)]
1268 #[inline]
1269 fn starts_with(byte: u8) -> bool {
1270 $(
1271 if $mangled[0] == byte {
1272 return true;
1273 }
1274 )*
1275
1276 false
1277 }
1278 }
1279 };
1280 ( $(#[$attr:meta])* pub enum $typename:ident {
1281 $($variant:ident ( $mangled:expr, $printable:expr, $userdata:expr)),*
1282 }
1283
1284 impl $typename2:ident {
1285 fn $fn_name:ident(&self) -> $userdata_ty:ty;
1286 } ) => {
1287 define_vocabulary! {
1288 $(#[$attr])*
1289 pub enum $typename {
1290 $(
1291 $variant ( $mangled, $printable )
1292 ),*
1293 }
1294 }
1295
1296 impl $typename2 {
1297 fn $fn_name(&self) -> $userdata_ty {
1298 match *self {
1299 $(
1300 $typename2::$variant => $userdata,
1301 )*
1302 }
1303 }
1304 }
1305 };
1306}
1307
1308#[derive(Clone, Debug, PartialEq, Eq)]
1320pub enum MangledName {
1321 Encoding(Encoding, Vec<CloneSuffix>),
1323
1324 BlockInvoke(Encoding, Option<isize>),
1326
1327 Type(TypeHandle),
1330
1331 GlobalCtorDtor(GlobalCtorDtor),
1335}
1336
1337impl Parse for MangledName {
1338 fn parse<'a, 'b>(
1339 ctx: &'a ParseContext,
1340 subs: &'a mut SubstitutionTable,
1341 input: IndexStr<'b>,
1342 ) -> Result<(MangledName, IndexStr<'b>)> {
1343 try_begin_parse!("MangledName", ctx, input);
1344
1345 if let Ok(tail) = consume(b"_Z", input).or_else(|_| consume(b"__Z", input)) {
1346 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1347 let (clone_suffixes, tail) = zero_or_more(ctx, subs, tail)?;
1348 return Ok((MangledName::Encoding(encoding, clone_suffixes), tail));
1349 }
1350
1351 if let Ok(tail) = consume(b"___Z", input).or_else(|_| consume(b"____Z", input)) {
1352 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1353 let tail = consume(b"_block_invoke", tail)?;
1354
1355 let tail_opt = match consume(b"_", tail).or_else(|_| consume(b".", tail)) {
1356 Ok(tail) => Some(parse_number(10, false, tail)?),
1357 Err(_) => parse_number(10, false, tail).ok(),
1358 };
1359
1360 let (digits, tail) = match tail_opt {
1361 Some((digits, tail)) => (Some(digits), tail),
1362 None => (None, tail),
1363 };
1364
1365 return Ok((MangledName::BlockInvoke(encoding, digits), tail));
1366 }
1367
1368 if let Ok(tail) = consume(b"_GLOBAL_", input) {
1369 let (global_ctor_dtor, tail) = GlobalCtorDtor::parse(ctx, subs, tail)?;
1370 return Ok((MangledName::GlobalCtorDtor(global_ctor_dtor), tail));
1371 }
1372
1373 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
1376 Ok((MangledName::Type(ty), tail))
1377 }
1378}
1379
1380impl<'subs, W> Demangle<'subs, W> for MangledName
1381where
1382 W: 'subs + DemangleWrite,
1383{
1384 fn demangle<'prev, 'ctx>(
1385 &'subs self,
1386 ctx: &'ctx mut DemangleContext<'subs, W>,
1387 scope: Option<ArgScopeStack<'prev, 'subs>>,
1388 ) -> fmt::Result {
1389 let ctx = try_begin_demangle!(self, ctx, scope);
1390
1391 match *self {
1392 MangledName::Encoding(ref enc, ref cs) => {
1393 enc.demangle(ctx, scope)?;
1394 if !cs.is_empty() && ctx.show_params {
1395 for clone_suffix in cs {
1396 clone_suffix.demangle(ctx, scope)?;
1397 }
1398 }
1399 Ok(())
1400 }
1401 MangledName::BlockInvoke(ref enc, _) => {
1402 write!(ctx, "invocation function for block in ")?;
1403 enc.demangle(ctx, scope)?;
1404 Ok(())
1405 }
1406 MangledName::Type(ref ty) => ty.demangle(ctx, scope),
1407 MangledName::GlobalCtorDtor(ref gcd) => gcd.demangle(ctx, scope),
1408 }
1409 }
1410}
1411
1412#[derive(Clone, Debug, PartialEq, Eq)]
1420pub enum Encoding {
1421 Function(Name, BareFunctionType),
1423
1424 Data(Name),
1426
1427 Special(SpecialName),
1429}
1430
1431impl Parse for Encoding {
1432 fn parse<'a, 'b>(
1433 ctx: &'a ParseContext,
1434 subs: &'a mut SubstitutionTable,
1435 input: IndexStr<'b>,
1436 ) -> Result<(Encoding, IndexStr<'b>)> {
1437 try_begin_parse!("Encoding", ctx, input);
1438
1439 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
1440 if let Ok((ty, tail)) = BareFunctionType::parse(ctx, subs, tail) {
1441 return Ok((Encoding::Function(name, ty), tail));
1442 } else {
1443 return Ok((Encoding::Data(name), tail));
1444 }
1445 }
1446
1447 let (name, tail) = SpecialName::parse(ctx, subs, input)?;
1448 Ok((Encoding::Special(name), tail))
1449 }
1450}
1451
1452impl<'subs, W> Demangle<'subs, W> for Encoding
1453where
1454 W: 'subs + DemangleWrite,
1455{
1456 fn demangle<'prev, 'ctx>(
1457 &'subs self,
1458 ctx: &'ctx mut DemangleContext<'subs, W>,
1459 scope: Option<ArgScopeStack<'prev, 'subs>>,
1460 ) -> fmt::Result {
1461 let ctx = try_begin_demangle!(self, ctx, scope);
1462 inner_barrier!(ctx);
1463
1464 match *self {
1465 Encoding::Function(ref name, ref fun_ty) => {
1466 debug_assert!(!fun_ty.0.is_empty());
1469
1470 let scope = if let Some(leaf) = name.get_leaf_name(ctx.subs) {
1471 match leaf {
1472 LeafName::SourceName(leaf) => scope.push(leaf),
1473 LeafName::WellKnownComponent(leaf) => scope.push(leaf),
1474 LeafName::Closure(leaf) => scope.push(leaf),
1475 LeafName::UnnamedType(leaf) => scope.push(leaf),
1476 }
1477 } else {
1478 scope
1479 };
1480
1481 let scope = if let Some(template_args) = name.get_template_args(ctx.subs) {
1498 let scope = scope.push(template_args);
1499 if ctx.show_return_type && !name.is_ctor_dtor_conversion(ctx.subs) {
1500 fun_ty.0[0].demangle(ctx, scope)?;
1501 write!(ctx, " ")?;
1502 }
1503
1504 scope
1505 } else {
1506 scope
1507 };
1508
1509 if ctx.show_params {
1510 ctx.push_inner(self);
1511 name.demangle(ctx, scope)?;
1512 if ctx.pop_inner_if(self) {
1513 self.demangle_as_inner(ctx, scope)?;
1514 }
1515 } else {
1516 name.demangle(ctx, scope)?;
1517 }
1518
1519 Ok(())
1520 }
1521 Encoding::Data(ref name) => name.demangle(ctx, scope),
1522 Encoding::Special(ref name) => name.demangle(ctx, scope),
1523 }
1524 }
1525}
1526
1527impl<'subs, W> DemangleAsInner<'subs, W> for Encoding
1528where
1529 W: 'subs + DemangleWrite,
1530{
1531 fn demangle_as_inner<'prev, 'ctx>(
1532 &'subs self,
1533 ctx: &'ctx mut DemangleContext<'subs, W>,
1534 scope: Option<ArgScopeStack<'prev, 'subs>>,
1535 ) -> fmt::Result {
1536 if let Encoding::Function(ref name, ref fun_ty) = *self {
1537 let (scope, function_args) =
1538 if let Some(template_args) = name.get_template_args(ctx.subs) {
1539 let scope = scope.push(template_args);
1540 let function_args = FunctionArgListAndReturnType::new(&fun_ty.0);
1541 (scope, function_args as &dyn DemangleAsInner<W>)
1542 } else {
1543 let function_args = FunctionArgList::new(&fun_ty.0);
1544 (scope, function_args as &dyn DemangleAsInner<W>)
1545 };
1546 function_args.demangle_as_inner(ctx, scope)
1547 } else {
1548 unreachable!("we only push Encoding::Function onto the inner stack");
1549 }
1550 }
1551}
1552
1553#[derive(Clone, Debug, PartialEq, Eq)]
1556pub struct CloneSuffix(CloneTypeIdentifier, Vec<isize>);
1557
1558impl Parse for CloneSuffix {
1559 fn parse<'a, 'b>(
1560 ctx: &'a ParseContext,
1561 subs: &'a mut SubstitutionTable,
1562 input: IndexStr<'b>,
1563 ) -> Result<(CloneSuffix, IndexStr<'b>)> {
1564 try_begin_parse!("CloneSuffix", ctx, input);
1565
1566 let tail = consume(b".", input)?;
1567 let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?;
1568
1569 let mut numbers = Vec::with_capacity(1);
1570 while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) {
1571 numbers.push(n);
1572 tail = t;
1573 }
1574
1575 let clone_suffix = CloneSuffix(identifier, numbers);
1576 Ok((clone_suffix, tail))
1577 }
1578}
1579
1580impl<'subs, W> Demangle<'subs, W> for CloneSuffix
1581where
1582 W: 'subs + DemangleWrite,
1583{
1584 fn demangle<'prev, 'ctx>(
1585 &'subs self,
1586 ctx: &'ctx mut DemangleContext<'subs, W>,
1587 scope: Option<ArgScopeStack<'prev, 'subs>>,
1588 ) -> fmt::Result {
1589 let ctx = try_begin_demangle!(self, ctx, scope);
1590 write!(ctx, " [clone")?;
1591 self.0.demangle(ctx, scope)?;
1592 for nonnegative in &self.1 {
1593 write!(ctx, ".{}", nonnegative)?;
1594 }
1595 write!(ctx, "]")?;
1596 Ok(())
1597 }
1598}
1599
1600#[derive(Clone, Debug, PartialEq, Eq)]
1602pub enum GlobalCtorDtor {
1603 Ctor(Box<MangledName>),
1605 Dtor(Box<MangledName>),
1607}
1608
1609impl Parse for GlobalCtorDtor {
1610 fn parse<'a, 'b>(
1611 ctx: &'a ParseContext,
1612 subs: &'a mut SubstitutionTable,
1613 input: IndexStr<'b>,
1614 ) -> Result<(GlobalCtorDtor, IndexStr<'b>)> {
1615 try_begin_parse!("GlobalCtorDtor", ctx, input);
1616
1617 let tail = match input.next_or(error::Error::UnexpectedEnd)? {
1618 (b'_', t) | (b'.', t) | (b'$', t) => t,
1619 _ => return Err(error::Error::UnexpectedText),
1620 };
1621
1622 match tail.next_or(error::Error::UnexpectedEnd)? {
1623 (b'I', tail) => {
1624 let tail = consume(b"_", tail)?;
1625 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1626 Ok((GlobalCtorDtor::Ctor(Box::new(name)), tail))
1627 }
1628 (b'D', tail) => {
1629 let tail = consume(b"_", tail)?;
1630 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1631 Ok((GlobalCtorDtor::Dtor(Box::new(name)), tail))
1632 }
1633 _ => Err(error::Error::UnexpectedText),
1634 }
1635 }
1636}
1637
1638impl<'subs, W> Demangle<'subs, W> for GlobalCtorDtor
1639where
1640 W: 'subs + DemangleWrite,
1641{
1642 fn demangle<'prev, 'ctx>(
1643 &'subs self,
1644 ctx: &'ctx mut DemangleContext<'subs, W>,
1645 scope: Option<ArgScopeStack<'prev, 'subs>>,
1646 ) -> fmt::Result {
1647 let ctx = try_begin_demangle!(self, ctx, scope);
1648 inner_barrier!(ctx);
1649
1650 let saved_show_params = ctx.show_params;
1651 ctx.show_params = true;
1652 let ret = match *self {
1653 GlobalCtorDtor::Ctor(ref name) => {
1654 write!(ctx, "global constructors keyed to ")?;
1655 name.demangle(ctx, scope)
1656 }
1657 GlobalCtorDtor::Dtor(ref name) => {
1658 write!(ctx, "global destructors keyed to ")?;
1659 name.demangle(ctx, scope)
1660 }
1661 };
1662 ctx.show_params = saved_show_params;
1663 ret
1664 }
1665}
1666
1667#[derive(Clone, Debug, PartialEq, Eq)]
1676pub enum Name {
1677 Nested(NestedName),
1679
1680 Unscoped(UnscopedName),
1682
1683 UnscopedTemplate(UnscopedTemplateNameHandle, TemplateArgs),
1685
1686 Local(LocalName),
1688}
1689
1690impl Parse for Name {
1691 fn parse<'a, 'b>(
1692 ctx: &'a ParseContext,
1693 subs: &'a mut SubstitutionTable,
1694 input: IndexStr<'b>,
1695 ) -> Result<(Name, IndexStr<'b>)> {
1696 try_begin_parse!("Name", ctx, input);
1697
1698 if let Ok((name, tail)) = NestedName::parse(ctx, subs, input) {
1699 return Ok((Name::Nested(name), tail));
1700 }
1701
1702 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1703 if tail.peek() == Some(b'I') {
1704 let name = UnscopedTemplateName(name);
1705 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1706 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1707
1708 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1709 return Ok((Name::UnscopedTemplate(handle, args), tail));
1710 } else {
1711 return Ok((Name::Unscoped(name), tail));
1712 }
1713 }
1714
1715 if let Ok((name, tail)) = UnscopedTemplateNameHandle::parse(ctx, subs, input) {
1716 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1717 return Ok((Name::UnscopedTemplate(name, args), tail));
1718 }
1719
1720 let (name, tail) = LocalName::parse(ctx, subs, input)?;
1721 Ok((Name::Local(name), tail))
1722 }
1723}
1724
1725impl<'subs, W> Demangle<'subs, W> for Name
1726where
1727 W: 'subs + DemangleWrite,
1728{
1729 fn demangle<'prev, 'ctx>(
1730 &'subs self,
1731 ctx: &'ctx mut DemangleContext<'subs, W>,
1732 scope: Option<ArgScopeStack<'prev, 'subs>>,
1733 ) -> fmt::Result {
1734 let ctx = try_begin_demangle!(self, ctx, scope);
1735
1736 match *self {
1737 Name::Nested(ref nested) => nested.demangle(ctx, scope),
1738 Name::Unscoped(ref unscoped) => unscoped.demangle(ctx, scope),
1739 Name::UnscopedTemplate(ref template, ref args) => {
1740 template.demangle(ctx, scope.push(args))?;
1741 args.demangle(ctx, scope)
1742 }
1743 Name::Local(ref local) => local.demangle(ctx, scope),
1744 }
1745 }
1746}
1747
1748impl GetTemplateArgs for Name {
1749 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
1750 match *self {
1751 Name::UnscopedTemplate(_, ref args) => Some(args),
1752 Name::Nested(ref nested) => nested.get_template_args(subs),
1753 Name::Local(ref local) => local.get_template_args(subs),
1754 Name::Unscoped(_) => None,
1755 }
1756 }
1757}
1758
1759impl<'a> GetLeafName<'a> for Name {
1760 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1761 match *self {
1762 Name::UnscopedTemplate(ref templ, _) => templ.get_leaf_name(subs),
1763 Name::Nested(ref nested) => nested.get_leaf_name(subs),
1764 Name::Unscoped(ref unscoped) => unscoped.get_leaf_name(subs),
1765 Name::Local(ref local) => local.get_leaf_name(subs),
1766 }
1767 }
1768}
1769
1770impl IsCtorDtorConversion for Name {
1771 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1772 match *self {
1773 Name::Unscoped(ref unscoped) => unscoped.is_ctor_dtor_conversion(subs),
1774 Name::Nested(ref nested) => nested.is_ctor_dtor_conversion(subs),
1775 Name::Local(_) | Name::UnscopedTemplate(..) => false,
1776 }
1777 }
1778}
1779
1780#[derive(Clone, Debug, PartialEq, Eq)]
1787pub enum UnscopedName {
1788 Unqualified(UnqualifiedName),
1790
1791 Std(UnqualifiedName),
1793}
1794
1795impl Parse for UnscopedName {
1796 fn parse<'a, 'b>(
1797 ctx: &'a ParseContext,
1798 subs: &'a mut SubstitutionTable,
1799 input: IndexStr<'b>,
1800 ) -> Result<(UnscopedName, IndexStr<'b>)> {
1801 try_begin_parse!("UnscopedName", ctx, input);
1802
1803 if let Ok(tail) = consume(b"St", input) {
1804 let (name, tail) = UnqualifiedName::parse(ctx, subs, tail)?;
1805 return Ok((UnscopedName::Std(name), tail));
1806 }
1807
1808 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
1809 Ok((UnscopedName::Unqualified(name), tail))
1810 }
1811}
1812
1813impl<'subs, W> Demangle<'subs, W> for UnscopedName
1814where
1815 W: 'subs + DemangleWrite,
1816{
1817 fn demangle<'prev, 'ctx>(
1818 &'subs self,
1819 ctx: &'ctx mut DemangleContext<'subs, W>,
1820 scope: Option<ArgScopeStack<'prev, 'subs>>,
1821 ) -> fmt::Result {
1822 let ctx = try_begin_demangle!(self, ctx, scope);
1823
1824 match *self {
1825 UnscopedName::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
1826 UnscopedName::Std(ref std) => {
1827 write!(ctx, "std::")?;
1828 std.demangle(ctx, scope)
1829 }
1830 }
1831 }
1832}
1833
1834impl<'a> GetLeafName<'a> for UnscopedName {
1835 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1836 match *self {
1837 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1838 name.get_leaf_name(subs)
1839 }
1840 }
1841 }
1842}
1843
1844impl IsCtorDtorConversion for UnscopedName {
1845 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1846 match *self {
1847 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1848 name.is_ctor_dtor_conversion(subs)
1849 }
1850 }
1851 }
1852}
1853
1854#[derive(Clone, Debug, PartialEq, Eq)]
1861pub struct UnscopedTemplateName(UnscopedName);
1862
1863define_handle! {
1864 pub enum UnscopedTemplateNameHandle {
1866 extra NonSubstitution(NonSubstitution),
1869 }
1870}
1871
1872impl Parse for UnscopedTemplateNameHandle {
1873 fn parse<'a, 'b>(
1874 ctx: &'a ParseContext,
1875 subs: &'a mut SubstitutionTable,
1876 input: IndexStr<'b>,
1877 ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)> {
1878 try_begin_parse!("UnscopedTemplateNameHandle", ctx, input);
1879
1880 if let Ok((name, tail)) = UnscopedName::parse(ctx, subs, input) {
1881 let name = UnscopedTemplateName(name);
1882 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1883 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1884 return Ok((handle, tail));
1885 }
1886
1887 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
1888
1889 match sub {
1890 Substitution::WellKnown(component) => {
1891 Ok((UnscopedTemplateNameHandle::WellKnown(component), tail))
1892 }
1893 Substitution::BackReference(idx) => {
1894 Ok((UnscopedTemplateNameHandle::BackReference(idx), tail))
1897 }
1898 }
1899 }
1900}
1901
1902impl<'subs, W> Demangle<'subs, W> for UnscopedTemplateName
1903where
1904 W: 'subs + DemangleWrite,
1905{
1906 fn demangle<'prev, 'ctx>(
1907 &'subs self,
1908 ctx: &'ctx mut DemangleContext<'subs, W>,
1909 scope: Option<ArgScopeStack<'prev, 'subs>>,
1910 ) -> fmt::Result {
1911 let ctx = try_begin_demangle!(self, ctx, scope);
1912
1913 self.0.demangle(ctx, scope)
1914 }
1915}
1916
1917impl<'a> GetLeafName<'a> for UnscopedTemplateName {
1918 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1919 self.0.get_leaf_name(subs)
1920 }
1921}
1922
1923#[derive(Clone, Debug, PartialEq, Eq)]
1930pub enum NestedName {
1931 Unqualified(
1933 CvQualifiers,
1934 Option<RefQualifier>,
1935 PrefixHandle,
1936 UnqualifiedName,
1937 ),
1938
1939 Template(CvQualifiers, Option<RefQualifier>, PrefixHandle),
1941}
1942
1943impl Parse for NestedName {
1944 fn parse<'a, 'b>(
1945 ctx: &'a ParseContext,
1946 subs: &'a mut SubstitutionTable,
1947 input: IndexStr<'b>,
1948 ) -> Result<(NestedName, IndexStr<'b>)> {
1949 try_begin_parse!("NestedName", ctx, input);
1950
1951 let tail = consume(b"N", input)?;
1952
1953 let (cv_qualifiers, tail) = if let Ok((q, tail)) = CvQualifiers::parse(ctx, subs, tail) {
1954 (q, tail)
1955 } else {
1956 (Default::default(), tail)
1957 };
1958
1959 let (ref_qualifier, tail) = if let Ok((r, tail)) = RefQualifier::parse(ctx, subs, tail) {
1960 (Some(r), tail)
1961 } else {
1962 (None, tail)
1963 };
1964
1965 let (prefix, tail) = PrefixHandle::parse(ctx, subs, tail)?;
1966 let tail = consume(b"E", tail)?;
1967
1968 let substitutable = match prefix {
1969 PrefixHandle::BackReference(idx) => subs.get(idx),
1970 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => subs.get_non_substitution(idx),
1971 PrefixHandle::WellKnown(_) => None,
1972 };
1973
1974 match substitutable {
1975 Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))) => Ok((
1976 NestedName::Unqualified(cv_qualifiers, ref_qualifier, prefix.clone(), name.clone()),
1977 tail,
1978 )),
1979 Some(&Substitutable::Prefix(Prefix::Template(..))) => Ok((
1980 NestedName::Template(cv_qualifiers, ref_qualifier, prefix),
1981 tail,
1982 )),
1983 _ => Err(error::Error::UnexpectedText),
1984 }
1985 }
1986}
1987
1988impl NestedName {
1989 pub fn cv_qualifiers(&self) -> &CvQualifiers {
1991 match *self {
1992 NestedName::Unqualified(ref q, ..) | NestedName::Template(ref q, ..) => q,
1993 }
1994 }
1995
1996 pub fn ref_qualifier(&self) -> Option<&RefQualifier> {
1998 match *self {
1999 NestedName::Unqualified(_, Some(ref r), ..)
2000 | NestedName::Template(_, Some(ref r), ..) => Some(r),
2001 _ => None,
2002 }
2003 }
2004
2005 fn prefix(&self) -> &PrefixHandle {
2009 match *self {
2010 NestedName::Unqualified(_, _, ref p, _) | NestedName::Template(_, _, ref p) => p,
2011 }
2012 }
2013}
2014
2015impl<'subs, W> Demangle<'subs, W> for NestedName
2016where
2017 W: 'subs + DemangleWrite,
2018{
2019 fn demangle<'prev, 'ctx>(
2020 &'subs self,
2021 ctx: &'ctx mut DemangleContext<'subs, W>,
2022 scope: Option<ArgScopeStack<'prev, 'subs>>,
2023 ) -> fmt::Result {
2024 let ctx = try_begin_demangle!(self, ctx, scope);
2025
2026 match *self {
2027 NestedName::Unqualified(_, _, ref p, ref name) => {
2028 ctx.push_demangle_node(DemangleNodeType::NestedName);
2029 p.demangle(ctx, scope)?;
2030 if name.accepts_double_colon() {
2031 ctx.write_str("::")?;
2032 }
2033 name.demangle(ctx, scope)?;
2034 ctx.pop_demangle_node();
2035 }
2036 NestedName::Template(_, _, ref p) => {
2037 ctx.is_template_prefix_in_nested_name = true;
2038 p.demangle(ctx, scope)?;
2039 ctx.is_template_prefix_in_nested_name = false;
2040 }
2041 }
2042
2043 if let Some(inner) = ctx.pop_inner() {
2044 inner.demangle_as_inner(ctx, scope)?;
2045 }
2046
2047 if self.cv_qualifiers() != &CvQualifiers::default() && ctx.show_params {
2048 self.cv_qualifiers().demangle(ctx, scope)?;
2049 }
2050
2051 if let Some(ref refs) = self.ref_qualifier() {
2052 ctx.ensure_space()?;
2053 refs.demangle(ctx, scope)?;
2054 }
2055
2056 Ok(())
2057 }
2058}
2059
2060impl GetTemplateArgs for NestedName {
2061 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2062 match *self {
2063 NestedName::Template(_, _, ref prefix) => prefix.get_template_args(subs),
2064 _ => None,
2065 }
2066 }
2067}
2068
2069impl<'a> GetLeafName<'a> for NestedName {
2070 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2071 match *self {
2072 NestedName::Unqualified(_, _, ref prefix, ref name) => name
2073 .get_leaf_name(subs)
2074 .or_else(|| prefix.get_leaf_name(subs)),
2075 NestedName::Template(_, _, ref prefix) => prefix.get_leaf_name(subs),
2076 }
2077 }
2078}
2079
2080impl IsCtorDtorConversion for NestedName {
2081 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2082 self.prefix().is_ctor_dtor_conversion(subs)
2083 }
2084}
2085
2086#[derive(Clone, Debug, PartialEq, Eq)]
2103pub enum Prefix {
2104 Unqualified(UnqualifiedName),
2106
2107 Nested(PrefixHandle, UnqualifiedName),
2109
2110 Template(PrefixHandle, TemplateArgs),
2112
2113 TemplateParam(TemplateParam),
2115
2116 Decltype(Decltype),
2118
2119 DataMember(PrefixHandle, DataMemberPrefix),
2121}
2122
2123impl GetTemplateArgs for Prefix {
2124 fn get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2125 match *self {
2126 Prefix::Template(_, ref args) => Some(args),
2127 Prefix::Unqualified(_)
2128 | Prefix::Nested(_, _)
2129 | Prefix::TemplateParam(_)
2130 | Prefix::Decltype(_)
2131 | Prefix::DataMember(_, _) => None,
2132 }
2133 }
2134}
2135
2136define_handle! {
2137 pub enum PrefixHandle {
2139 extra NonSubstitution(NonSubstitution),
2143 }
2144}
2145
2146impl Parse for PrefixHandle {
2147 fn parse<'a, 'b>(
2148 ctx: &'a ParseContext,
2149 subs: &'a mut SubstitutionTable,
2150 input: IndexStr<'b>,
2151 ) -> Result<(PrefixHandle, IndexStr<'b>)> {
2152 try_begin_parse!("PrefixHandle", ctx, input);
2153
2154 #[inline]
2155 fn save(
2156 subs: &mut SubstitutionTable,
2157 prefix: Prefix,
2158 tail_tail: IndexStr<'_>,
2159 ) -> PrefixHandle {
2160 if let Some(b'E') = tail_tail.peek() {
2161 let idx = subs.insert_non_substitution(Substitutable::Prefix(prefix));
2167 PrefixHandle::NonSubstitution(NonSubstitution(idx))
2168 } else {
2169 let idx = subs.insert(Substitutable::Prefix(prefix));
2170 PrefixHandle::BackReference(idx)
2171 }
2172 }
2173
2174 let mut tail = input;
2175 let mut current = None;
2176
2177 loop {
2178 try_begin_parse!("PrefixHandle iteration", ctx, tail);
2179
2180 match tail.peek() {
2181 Some(b'E') | None => {
2182 if let Some(handle) = current {
2183 return Ok((handle, tail));
2184 } else {
2185 return Err(error::Error::UnexpectedEnd);
2186 }
2187 }
2188 Some(b'S') => {
2189 let (sub, tail_tail) = Substitution::parse(ctx, subs, tail)?;
2191 current = Some(match sub {
2192 Substitution::WellKnown(component) => PrefixHandle::WellKnown(component),
2193 Substitution::BackReference(idx) => {
2194 PrefixHandle::BackReference(idx)
2197 }
2198 });
2199 tail = tail_tail;
2200 }
2201 Some(b'T') => {
2202 let (param, tail_tail) = TemplateParam::parse(ctx, subs, tail)?;
2204 current = Some(save(subs, Prefix::TemplateParam(param), tail_tail));
2205 tail = tail_tail;
2206 }
2207 Some(b'D') => {
2208 if let Ok((decltype, tail_tail)) = Decltype::parse(ctx, subs, tail) {
2216 current = Some(save(subs, Prefix::Decltype(decltype), tail_tail));
2217 tail = tail_tail;
2218 } else {
2219 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2220 let prefix = match current {
2221 None => Prefix::Unqualified(name),
2222 Some(handle) => Prefix::Nested(handle, name),
2223 };
2224 current = Some(save(subs, prefix, tail_tail));
2225 tail = tail_tail;
2226 }
2227 }
2228 Some(b'I')
2229 if current.is_some() && current.as_ref().unwrap().is_template_prefix() =>
2230 {
2231 let (args, tail_tail) = TemplateArgs::parse(ctx, subs, tail)?;
2233 let prefix = Prefix::Template(current.unwrap(), args);
2234 current = Some(save(subs, prefix, tail_tail));
2235 tail = tail_tail;
2236 }
2237 Some(c) if current.is_some() && SourceName::starts_with(c) => {
2238 debug_assert!(SourceName::starts_with(c));
2246 debug_assert!(DataMemberPrefix::starts_with(c));
2247
2248 let (name, tail_tail) = SourceName::parse(ctx, subs, tail)?;
2249 if tail_tail.peek() == Some(b'M') {
2250 let prefix = Prefix::DataMember(current.unwrap(), DataMemberPrefix(name));
2251 current = Some(save(subs, prefix, tail_tail));
2252 tail = consume(b"M", tail_tail).unwrap();
2253 } else {
2254 let name = UnqualifiedName::Source(name);
2255 let prefix = match current {
2256 None => Prefix::Unqualified(name),
2257 Some(handle) => Prefix::Nested(handle, name),
2258 };
2259 current = Some(save(subs, prefix, tail_tail));
2260 tail = tail_tail;
2261 }
2262 }
2263 Some(c) if UnqualifiedName::starts_with(c, &tail) => {
2264 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2266 let prefix = match current {
2267 None => Prefix::Unqualified(name),
2268 Some(handle) => Prefix::Nested(handle, name),
2269 };
2270 current = Some(save(subs, prefix, tail_tail));
2271 tail = tail_tail;
2272 }
2273 Some(_) => {
2274 if let Some(handle) = current {
2275 return Ok((handle, tail));
2276 } else if tail.is_empty() {
2277 return Err(error::Error::UnexpectedEnd);
2278 } else {
2279 return Err(error::Error::UnexpectedText);
2280 }
2281 }
2282 }
2283 }
2284 }
2285}
2286
2287impl<'a> GetLeafName<'a> for Prefix {
2288 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2289 match *self {
2290 Prefix::Nested(ref prefix, ref name) => name
2291 .get_leaf_name(subs)
2292 .or_else(|| prefix.get_leaf_name(subs)),
2293 Prefix::Unqualified(ref name) => name.get_leaf_name(subs),
2294 Prefix::Template(ref prefix, _) => prefix.get_leaf_name(subs),
2295 Prefix::DataMember(_, ref name) => name.get_leaf_name(subs),
2296 Prefix::TemplateParam(_) | Prefix::Decltype(_) => None,
2297 }
2298 }
2299}
2300
2301impl GetTemplateArgs for PrefixHandle {
2302 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2305 match *self {
2306 PrefixHandle::BackReference(idx) => {
2307 if let Some(&Substitutable::Prefix(ref p)) = subs.get(idx) {
2308 p.get_template_args(subs)
2309 } else {
2310 None
2311 }
2312 }
2313 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2314 if let Some(&Substitutable::Prefix(ref p)) = subs.get_non_substitution(idx) {
2315 p.get_template_args(subs)
2316 } else {
2317 None
2318 }
2319 }
2320 _ => None,
2321 }
2322 }
2323}
2324
2325impl<'subs, W> Demangle<'subs, W> for Prefix
2326where
2327 W: 'subs + DemangleWrite,
2328{
2329 fn demangle<'prev, 'ctx>(
2330 &'subs self,
2331 ctx: &'ctx mut DemangleContext<'subs, W>,
2332 scope: Option<ArgScopeStack<'prev, 'subs>>,
2333 ) -> fmt::Result {
2334 let ctx = try_begin_demangle!(self, ctx, scope);
2335 if ctx.is_template_prefix {
2336 ctx.push_demangle_node(DemangleNodeType::TemplatePrefix);
2337 ctx.is_template_prefix = false;
2338 } else if ctx.is_template_prefix_in_nested_name {
2339 ctx.push_demangle_node(DemangleNodeType::NestedName);
2340 ctx.is_template_prefix_in_nested_name = false;
2341 } else {
2342 ctx.push_demangle_node(DemangleNodeType::Prefix);
2343 }
2344
2345 let ret = match *self {
2346 Prefix::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
2347 Prefix::Nested(ref prefix, ref unqualified) => {
2348 prefix.demangle(ctx, scope)?;
2349 if unqualified.accepts_double_colon() {
2350 write!(ctx, "::")?;
2351 }
2352 unqualified.demangle(ctx, scope)
2353 }
2354 Prefix::Template(ref prefix, ref args) => {
2355 ctx.is_template_prefix = true;
2356 prefix.demangle(ctx, scope)?;
2357 ctx.is_template_prefix = false;
2358 args.demangle(ctx, scope)
2359 }
2360 Prefix::TemplateParam(ref param) => param.demangle(ctx, scope),
2361 Prefix::Decltype(ref dt) => dt.demangle(ctx, scope),
2362 Prefix::DataMember(ref prefix, ref member) => {
2363 prefix.demangle(ctx, scope)?;
2364 write!(ctx, "::")?;
2365 member.demangle(ctx, scope)
2366 }
2367 };
2368 ctx.pop_demangle_node();
2369 ret
2370 }
2371}
2372
2373impl IsCtorDtorConversion for Prefix {
2374 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2375 match *self {
2376 Prefix::Unqualified(ref unqualified) | Prefix::Nested(_, ref unqualified) => {
2377 unqualified.is_ctor_dtor_conversion(subs)
2378 }
2379 Prefix::Template(ref prefix, _) => prefix.is_ctor_dtor_conversion(subs),
2380 _ => false,
2381 }
2382 }
2383}
2384
2385impl IsCtorDtorConversion for PrefixHandle {
2386 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2387 match *self {
2388 PrefixHandle::BackReference(idx) => {
2389 if let Some(sub) = subs.get(idx) {
2390 sub.is_ctor_dtor_conversion(subs)
2391 } else {
2392 false
2393 }
2394 }
2395 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2396 if let Some(sub) = subs.get_non_substitution(idx) {
2397 sub.is_ctor_dtor_conversion(subs)
2398 } else {
2399 false
2400 }
2401 }
2402 PrefixHandle::WellKnown(_) => false,
2403 }
2404 }
2405}
2406
2407impl PrefixHandle {
2408 fn is_template_prefix(&self) -> bool {
2411 match *self {
2412 PrefixHandle::BackReference(_) | PrefixHandle::WellKnown(_) => true,
2413 PrefixHandle::NonSubstitution(_) => false,
2414 }
2415 }
2416}
2417
2418#[derive(Clone, Debug, PartialEq, Eq)]
2434pub enum UnqualifiedName {
2435 Operator(OperatorName),
2437 CtorDtor(CtorDtorName),
2439 Source(SourceName),
2441 LocalSourceName(SourceName, Option<Discriminator>),
2443 UnnamedType(UnnamedTypeName),
2445 ABITag(TaggedName),
2447 ClosureType(ClosureTypeName),
2449}
2450
2451impl Parse for UnqualifiedName {
2452 fn parse<'a, 'b>(
2453 ctx: &'a ParseContext,
2454 subs: &'a mut SubstitutionTable,
2455 input: IndexStr<'b>,
2456 ) -> Result<(UnqualifiedName, IndexStr<'b>)> {
2457 try_begin_parse!("UnqualifiedName", ctx, input);
2458
2459 if let Ok((op, tail)) = OperatorName::parse(ctx, subs, input) {
2460 return Ok((UnqualifiedName::Operator(op), tail));
2461 }
2462
2463 if let Ok((ctor_dtor, tail)) = CtorDtorName::parse(ctx, subs, input) {
2464 return Ok((UnqualifiedName::CtorDtor(ctor_dtor), tail));
2465 }
2466
2467 if let Ok(tail) = consume(b"L", input) {
2468 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2469 let (discr, tail) = if let Ok((d, t)) = Discriminator::parse(ctx, subs, tail) {
2470 (Some(d), t)
2471 } else {
2472 (None, tail)
2473 };
2474 return Ok((UnqualifiedName::LocalSourceName(name, discr), tail));
2475 }
2476
2477 if let Ok((source, tail)) = SourceName::parse(ctx, subs, input) {
2478 return Ok((UnqualifiedName::Source(source), tail));
2479 }
2480
2481 if let Ok((tagged, tail)) = TaggedName::parse(ctx, subs, input) {
2482 return Ok((UnqualifiedName::ABITag(tagged), tail));
2483 }
2484
2485 if let Ok((closure, tail)) = ClosureTypeName::parse(ctx, subs, input) {
2486 return Ok((UnqualifiedName::ClosureType(closure), tail));
2487 }
2488
2489 UnnamedTypeName::parse(ctx, subs, input)
2490 .map(|(unnamed, tail)| (UnqualifiedName::UnnamedType(unnamed), tail))
2491 }
2492}
2493
2494impl<'subs, W> Demangle<'subs, W> for UnqualifiedName
2495where
2496 W: 'subs + DemangleWrite,
2497{
2498 fn demangle<'prev, 'ctx>(
2499 &'subs self,
2500 ctx: &'ctx mut DemangleContext<'subs, W>,
2501 scope: Option<ArgScopeStack<'prev, 'subs>>,
2502 ) -> fmt::Result {
2503 let ctx = try_begin_demangle!(self, ctx, scope);
2504
2505 ctx.push_demangle_node(DemangleNodeType::UnqualifiedName);
2506 let ret = match *self {
2507 UnqualifiedName::Operator(ref op_name) => {
2508 write!(ctx, "operator")?;
2509 op_name.demangle(ctx, scope)
2510 }
2511 UnqualifiedName::CtorDtor(ref ctor_dtor) => ctor_dtor.demangle(ctx, scope),
2512 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, ..) => {
2513 name.demangle(ctx, scope)
2514 }
2515 UnqualifiedName::UnnamedType(ref unnamed) => unnamed.demangle(ctx, scope),
2516 UnqualifiedName::ABITag(ref tagged) => tagged.demangle(ctx, scope),
2517 UnqualifiedName::ClosureType(ref closure) => closure.demangle(ctx, scope),
2518 };
2519 ctx.pop_demangle_node();
2520 ret
2521 }
2522}
2523
2524impl<'a> GetLeafName<'a> for UnqualifiedName {
2525 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2526 match *self {
2527 UnqualifiedName::ABITag(_)
2528 | UnqualifiedName::Operator(_)
2529 | UnqualifiedName::CtorDtor(_) => None,
2530 UnqualifiedName::UnnamedType(ref name) => Some(LeafName::UnnamedType(name)),
2531 UnqualifiedName::ClosureType(ref closure) => closure.get_leaf_name(subs),
2532 UnqualifiedName::Source(ref name) | UnqualifiedName::LocalSourceName(ref name, _) => {
2533 Some(LeafName::SourceName(name))
2534 }
2535 }
2536 }
2537}
2538
2539impl IsCtorDtorConversion for UnqualifiedName {
2540 fn is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool {
2541 match *self {
2542 UnqualifiedName::CtorDtor(_)
2543 | UnqualifiedName::Operator(OperatorName::Conversion(_)) => true,
2544 UnqualifiedName::Operator(_)
2545 | UnqualifiedName::Source(_)
2546 | UnqualifiedName::LocalSourceName(..)
2547 | UnqualifiedName::UnnamedType(_)
2548 | UnqualifiedName::ClosureType(_)
2549 | UnqualifiedName::ABITag(_) => false,
2550 }
2551 }
2552}
2553
2554impl UnqualifiedName {
2555 #[inline]
2556 fn starts_with(byte: u8, input: &IndexStr) -> bool {
2557 byte == b'L'
2558 || OperatorName::starts_with(byte)
2559 || CtorDtorName::starts_with(byte)
2560 || SourceName::starts_with(byte)
2561 || UnnamedTypeName::starts_with(byte)
2562 || TaggedName::starts_with(byte)
2563 || ClosureTypeName::starts_with(byte, input)
2564 }
2565
2566 fn accepts_double_colon(&self) -> bool {
2567 match *self {
2568 UnqualifiedName::Operator(_)
2569 | UnqualifiedName::CtorDtor(_)
2570 | UnqualifiedName::Source(_)
2571 | UnqualifiedName::LocalSourceName(..)
2572 | UnqualifiedName::UnnamedType(_)
2573 | UnqualifiedName::ClosureType(_) => true,
2574 UnqualifiedName::ABITag(_) => false,
2575 }
2576 }
2577}
2578
2579#[derive(Clone, Debug, PartialEq, Eq)]
2585pub struct SourceName(Identifier);
2586
2587impl Parse for SourceName {
2588 fn parse<'a, 'b>(
2589 ctx: &'a ParseContext,
2590 subs: &'a mut SubstitutionTable,
2591 input: IndexStr<'b>,
2592 ) -> Result<(SourceName, IndexStr<'b>)> {
2593 try_begin_parse!("SourceName", ctx, input);
2594
2595 let (source_name_len, input) = parse_number(10, false, input)?;
2596 debug_assert!(source_name_len >= 0);
2597 if source_name_len == 0 {
2598 return Err(error::Error::UnexpectedText);
2599 }
2600
2601 let (head, tail) = match input.try_split_at(source_name_len as _) {
2602 Some((head, tail)) => (head, tail),
2603 None => return Err(error::Error::UnexpectedEnd),
2604 };
2605
2606 let (identifier, empty) = Identifier::parse(ctx, subs, head)?;
2607 if !empty.is_empty() {
2608 return Err(error::Error::UnexpectedText);
2609 }
2610
2611 let source_name = SourceName(identifier);
2612 Ok((source_name, tail))
2613 }
2614}
2615
2616impl<'subs> ArgScope<'subs, 'subs> for SourceName {
2617 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
2618 Ok(LeafName::SourceName(self))
2619 }
2620
2621 fn get_template_arg(
2622 &'subs self,
2623 _: usize,
2624 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
2625 Err(error::Error::BadTemplateArgReference)
2626 }
2627
2628 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
2629 Err(error::Error::BadFunctionArgReference)
2630 }
2631}
2632
2633impl SourceName {
2634 #[inline]
2635 fn starts_with(byte: u8) -> bool {
2636 byte == b'0' || (b'0' <= byte && byte <= b'9')
2637 }
2638}
2639
2640impl<'subs, W> Demangle<'subs, W> for SourceName
2641where
2642 W: 'subs + DemangleWrite,
2643{
2644 #[inline]
2645 fn demangle<'prev, 'ctx>(
2646 &'subs self,
2647 ctx: &'ctx mut DemangleContext<'subs, W>,
2648 scope: Option<ArgScopeStack<'prev, 'subs>>,
2649 ) -> fmt::Result {
2650 let ctx = try_begin_demangle!(self, ctx, scope);
2651
2652 self.0.demangle(ctx, scope)
2653 }
2654}
2655
2656#[derive(Clone, Debug, PartialEq, Eq)]
2662pub struct TaggedName(SourceName);
2663
2664impl Parse for TaggedName {
2665 fn parse<'a, 'b>(
2666 ctx: &'a ParseContext,
2667 subs: &'a mut SubstitutionTable,
2668 input: IndexStr<'b>,
2669 ) -> Result<(TaggedName, IndexStr<'b>)> {
2670 try_begin_parse!("TaggedName", ctx, input);
2671
2672 let tail = consume(b"B", input)?;
2673 let (source_name, tail) = SourceName::parse(ctx, subs, tail)?;
2674 Ok((TaggedName(source_name), tail))
2675 }
2676}
2677
2678impl<'subs, W> Demangle<'subs, W> for TaggedName
2679where
2680 W: 'subs + DemangleWrite,
2681{
2682 fn demangle<'prev, 'ctx>(
2683 &'subs self,
2684 ctx: &'ctx mut DemangleContext<'subs, W>,
2685 scope: Option<ArgScopeStack<'prev, 'subs>>,
2686 ) -> fmt::Result {
2687 let ctx = try_begin_demangle!(self, ctx, scope);
2688
2689 write!(ctx, "[abi:")?;
2690 self.0.demangle(ctx, scope)?;
2691 write!(ctx, "]")
2692 }
2693}
2694
2695impl TaggedName {
2696 #[inline]
2697 fn starts_with(byte: u8) -> bool {
2698 byte == b'B'
2699 }
2700}
2701
2702#[derive(Clone, Debug, PartialEq, Eq)]
2715pub struct Identifier {
2716 start: usize,
2717 end: usize,
2718}
2719
2720impl Parse for Identifier {
2721 fn parse<'a, 'b>(
2722 ctx: &'a ParseContext,
2723 _subs: &'a mut SubstitutionTable,
2724 input: IndexStr<'b>,
2725 ) -> Result<(Identifier, IndexStr<'b>)> {
2726 try_begin_parse!("Identifier", ctx, input);
2727
2728 if input.is_empty() {
2729 return Err(error::Error::UnexpectedEnd);
2730 }
2731
2732 let end = input
2733 .as_ref()
2734 .iter()
2735 .map(|&c| c as char)
2736 .take_while(|&c| c == '$' || c == '_' || c == '.' || c.is_digit(36))
2737 .count();
2738
2739 if end == 0 {
2740 return Err(error::Error::UnexpectedText);
2741 }
2742
2743 let tail = input.range_from(end..);
2744
2745 let identifier = Identifier {
2746 start: input.index(),
2747 end: tail.index(),
2748 };
2749
2750 Ok((identifier, tail))
2751 }
2752}
2753
2754impl<'subs, W> Demangle<'subs, W> for Identifier
2755where
2756 W: 'subs + DemangleWrite,
2757{
2758 #[inline]
2759 fn demangle<'prev, 'ctx>(
2760 &'subs self,
2761 ctx: &'ctx mut DemangleContext<'subs, W>,
2762 scope: Option<ArgScopeStack<'prev, 'subs>>,
2763 ) -> fmt::Result {
2764 let ctx = try_begin_demangle!(self, ctx, scope);
2765
2766 let ident = &ctx.input[self.start..self.end];
2767
2768 let anon_namespace_prefix = b"_GLOBAL_";
2770 if ident.starts_with(anon_namespace_prefix)
2771 && ident.len() >= anon_namespace_prefix.len() + 2
2772 {
2773 let first = ident[anon_namespace_prefix.len()];
2774 let second = ident[anon_namespace_prefix.len() + 1];
2775
2776 match (first, second) {
2777 (b'.', b'N') | (b'_', b'N') | (b'$', b'N') => {
2778 write!(ctx, "(anonymous namespace)")?;
2779 return Ok(());
2780 }
2781 _ => {
2782 }
2784 }
2785 }
2786
2787 let source_name = String::from_utf8_lossy(ident);
2788 ctx.set_source_name(self.start, self.end);
2789 write!(ctx, "{}", source_name)?;
2790 Ok(())
2791 }
2792}
2793
2794#[derive(Clone, Debug, PartialEq, Eq)]
2800pub struct CloneTypeIdentifier {
2801 start: usize,
2802 end: usize,
2803}
2804
2805impl Parse for CloneTypeIdentifier {
2806 fn parse<'a, 'b>(
2807 ctx: &'a ParseContext,
2808 _subs: &'a mut SubstitutionTable,
2809 input: IndexStr<'b>,
2810 ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
2811 try_begin_parse!("CloneTypeIdentifier", ctx, input);
2812
2813 if input.is_empty() {
2814 return Err(error::Error::UnexpectedEnd);
2815 }
2816
2817 let end = input
2818 .as_ref()
2819 .iter()
2820 .map(|&c| c as char)
2821 .take_while(|&c| c == '$' || c == '_' || c.is_digit(36))
2822 .count();
2823
2824 if end == 0 {
2825 return Err(error::Error::UnexpectedText);
2826 }
2827
2828 let tail = input.range_from(end..);
2829
2830 let identifier = CloneTypeIdentifier {
2831 start: input.index(),
2832 end: tail.index(),
2833 };
2834
2835 Ok((identifier, tail))
2836 }
2837}
2838
2839impl<'subs, W> Demangle<'subs, W> for CloneTypeIdentifier
2840where
2841 W: 'subs + DemangleWrite,
2842{
2843 #[inline]
2844 fn demangle<'prev, 'ctx>(
2845 &'subs self,
2846 ctx: &'ctx mut DemangleContext<'subs, W>,
2847 scope: Option<ArgScopeStack<'prev, 'subs>>,
2848 ) -> fmt::Result {
2849 let ctx = try_begin_demangle!(self, ctx, scope);
2850
2851 let ident = &ctx.input[self.start..self.end];
2852
2853 let source_name = String::from_utf8_lossy(ident);
2854 ctx.set_source_name(self.start, self.end);
2855 write!(ctx, " .{}", source_name)?;
2856 Ok(())
2857 }
2858}
2859
2860type Number = isize;
2866
2867impl Parse for Number {
2868 fn parse<'a, 'b>(
2869 ctx: &'a ParseContext,
2870 _subs: &'a mut SubstitutionTable,
2871 input: IndexStr<'b>,
2872 ) -> Result<(isize, IndexStr<'b>)> {
2873 try_begin_parse!("Number", ctx, input);
2874 parse_number(10, true, input)
2875 }
2876}
2877
2878#[derive(Clone, Debug, PartialEq, Eq)]
2884pub struct SeqId(usize);
2885
2886impl Parse for SeqId {
2887 fn parse<'a, 'b>(
2888 ctx: &'a ParseContext,
2889 _subs: &'a mut SubstitutionTable,
2890 input: IndexStr<'b>,
2891 ) -> Result<(SeqId, IndexStr<'b>)> {
2892 try_begin_parse!("SeqId", ctx, input);
2893
2894 parse_number(36, false, input).map(|(num, tail)| (SeqId(num as _), tail))
2895 }
2896}
2897
2898#[derive(Clone, Debug, PartialEq, Eq)]
2907pub enum OperatorName {
2908 Simple(SimpleOperatorName),
2910
2911 Cast(TypeHandle),
2913
2914 Conversion(TypeHandle),
2916
2917 Literal(SourceName),
2919
2920 VendorExtension(u8, SourceName),
2922}
2923
2924impl OperatorName {
2925 fn starts_with(byte: u8) -> bool {
2926 byte == b'c' || byte == b'l' || byte == b'v' || SimpleOperatorName::starts_with(byte)
2927 }
2928
2929 fn arity(&self) -> u8 {
2930 match self {
2931 &OperatorName::Cast(_) | &OperatorName::Conversion(_) | &OperatorName::Literal(_) => 1,
2932 &OperatorName::Simple(ref s) => s.arity(),
2933 &OperatorName::VendorExtension(arity, _) => arity,
2934 }
2935 }
2936
2937 fn parse_from_expr<'a, 'b>(
2938 ctx: &'a ParseContext,
2939 subs: &'a mut SubstitutionTable,
2940 input: IndexStr<'b>,
2941 ) -> Result<(Expression, IndexStr<'b>)> {
2942 let (operator, tail) = OperatorName::parse_internal(ctx, subs, input, true)?;
2943
2944 let arity = operator.arity();
2945 if arity == 1 {
2946 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2947 let expr = Expression::Unary(operator, Box::new(first));
2948 Ok((expr, tail))
2949 } else if arity == 2 {
2950 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2951 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2952 let expr = Expression::Binary(operator, Box::new(first), Box::new(second));
2953 Ok((expr, tail))
2954 } else if arity == 3 {
2955 let (first, tail) = Expression::parse(ctx, subs, tail)?;
2956 let (second, tail) = Expression::parse(ctx, subs, tail)?;
2957 let (third, tail) = Expression::parse(ctx, subs, tail)?;
2958 let expr =
2959 Expression::Ternary(operator, Box::new(first), Box::new(second), Box::new(third));
2960 Ok((expr, tail))
2961 } else {
2962 Err(error::Error::UnexpectedText)
2963 }
2964 }
2965
2966 fn parse_internal<'a, 'b>(
2967 ctx: &'a ParseContext,
2968 subs: &'a mut SubstitutionTable,
2969 input: IndexStr<'b>,
2970 from_expr: bool,
2971 ) -> Result<(OperatorName, IndexStr<'b>)> {
2972 try_begin_parse!("OperatorName", ctx, input);
2973
2974 if let Ok((simple, tail)) = SimpleOperatorName::parse(ctx, subs, input) {
2975 return Ok((OperatorName::Simple(simple), tail));
2976 }
2977
2978 if let Ok(tail) = consume(b"cv", input) {
2979 let previously_in_conversion = ctx.set_in_conversion(!from_expr);
2982 let parse_result = TypeHandle::parse(ctx, subs, tail);
2983 ctx.set_in_conversion(previously_in_conversion);
2984 let (ty, tail) = parse_result?;
2985 if from_expr {
2986 return Ok((OperatorName::Cast(ty), tail));
2987 } else {
2988 return Ok((OperatorName::Conversion(ty), tail));
2989 }
2990 }
2991
2992 if let Ok(tail) = consume(b"li", input) {
2993 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2994 return Ok((OperatorName::Literal(name), tail));
2995 }
2996
2997 let tail = consume(b"v", input)?;
2998 let (arity, tail) = match tail.peek() {
2999 Some(c) if b'0' <= c && c <= b'9' => (c - b'0', tail.range_from(1..)),
3000 None => return Err(error::Error::UnexpectedEnd),
3001 _ => return Err(error::Error::UnexpectedText),
3002 };
3003 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3004 Ok((OperatorName::VendorExtension(arity, name), tail))
3005 }
3006}
3007
3008impl Parse for OperatorName {
3009 fn parse<'a, 'b>(
3010 ctx: &'a ParseContext,
3011 subs: &'a mut SubstitutionTable,
3012 input: IndexStr<'b>,
3013 ) -> Result<(OperatorName, IndexStr<'b>)> {
3014 OperatorName::parse_internal(ctx, subs, input, false)
3015 }
3016}
3017
3018impl<'subs, W> Demangle<'subs, W> for OperatorName
3019where
3020 W: 'subs + DemangleWrite,
3021{
3022 fn demangle<'prev, 'ctx>(
3023 &'subs self,
3024 ctx: &'ctx mut DemangleContext<'subs, W>,
3025 scope: Option<ArgScopeStack<'prev, 'subs>>,
3026 ) -> fmt::Result {
3027 let ctx = try_begin_demangle!(self, ctx, scope);
3028
3029 match *self {
3030 OperatorName::Simple(ref simple) => {
3031 match *simple {
3032 SimpleOperatorName::New
3033 | SimpleOperatorName::NewArray
3034 | SimpleOperatorName::Delete
3035 | SimpleOperatorName::DeleteArray => {
3036 ctx.ensure_space()?;
3037 }
3038 _ => {}
3039 }
3040 simple.demangle(ctx, scope)
3041 }
3042 OperatorName::Cast(ref ty) | OperatorName::Conversion(ref ty) => {
3043 ctx.ensure_space()?;
3044
3045 let scope = ty
3049 .get_template_args(ctx.subs)
3050 .map_or(scope, |args| scope.push(args));
3051
3052 ty.demangle(ctx, scope)?;
3053 Ok(())
3054 }
3055 OperatorName::Literal(ref name) => {
3056 name.demangle(ctx, scope)?;
3057 write!(ctx, "::operator \"\"")?;
3058 Ok(())
3059 }
3060 OperatorName::VendorExtension(arity, ref name) => {
3061 name.demangle(ctx, scope)?;
3063 write!(ctx, "::operator {}", arity)?;
3064 Ok(())
3065 }
3066 }
3067 }
3068}
3069
3070define_vocabulary! {
3071 #[derive(Clone, Debug, PartialEq, Eq)]
3073 pub enum SimpleOperatorName {
3074 New (b"nw", "new", 3),
3075 NewArray (b"na", "new[]", 3),
3076 Delete (b"dl", "delete", 1),
3077 DeleteArray (b"da", "delete[]", 1),
3078 UnaryPlus (b"ps", "+", 1),
3079 Neg (b"ng", "-", 1),
3080 AddressOf (b"ad", "&", 1),
3081 Deref (b"de", "*", 1),
3082 BitNot (b"co", "~", 1),
3083 Add (b"pl", "+", 2),
3084 Sub (b"mi", "-", 2),
3085 Mul (b"ml", "*", 2),
3086 Div (b"dv", "/", 2),
3087 Rem (b"rm", "%", 2),
3088 BitAnd (b"an", "&", 2),
3089 BitOr (b"or", "|", 2),
3090 BitXor (b"eo", "^", 2),
3091 Assign (b"aS", "=", 2),
3092 AddAssign (b"pL", "+=", 2),
3093 SubAssign (b"mI", "-=", 2),
3094 MulAssign (b"mL", "*=", 2),
3095 DivAssign (b"dV", "/=", 2),
3096 RemAssign (b"rM", "%=", 2),
3097 BitAndAssign (b"aN", "&=", 2),
3098 BitOrAssign (b"oR", "|=", 2),
3099 BitXorAssign (b"eO", "^=", 2),
3100 Shl (b"ls", "<<", 2),
3101 Shr (b"rs", ">>", 2),
3102 ShlAssign (b"lS", "<<=", 2),
3103 ShrAssign (b"rS", ">>=", 2),
3104 Eq (b"eq", "==", 2),
3105 Ne (b"ne", "!=", 2),
3106 Less (b"lt", "<", 2),
3107 Greater (b"gt", ">", 2),
3108 LessEq (b"le", "<=", 2),
3109 GreaterEq (b"ge", ">=", 2),
3110 Not (b"nt", "!", 1),
3111 LogicalAnd (b"aa", "&&", 2),
3112 LogicalOr (b"oo", "||", 2),
3113 PostInc (b"pp", "++", 1), PostDec (b"mm", "--", 1), Comma (b"cm", ",", 2),
3116 DerefMemberPtr (b"pm", "->*", 2),
3117 DerefMember (b"pt", "->", 2),
3118 Call (b"cl", "()", 2),
3119 Index (b"ix", "[]", 2),
3120 Question (b"qu", "?:", 3),
3121 Spaceship (b"ss", "<=>", 2)
3122 }
3123
3124 impl SimpleOperatorName {
3125 fn arity(&self) -> u8;
3127 }
3128}
3129
3130#[derive(Clone, Debug, PartialEq, Eq)]
3137pub enum CallOffset {
3138 NonVirtual(NvOffset),
3140 Virtual(VOffset),
3142}
3143
3144impl Parse for CallOffset {
3145 fn parse<'a, 'b>(
3146 ctx: &'a ParseContext,
3147 subs: &'a mut SubstitutionTable,
3148 input: IndexStr<'b>,
3149 ) -> Result<(CallOffset, IndexStr<'b>)> {
3150 try_begin_parse!("CallOffset", ctx, input);
3151
3152 if input.is_empty() {
3153 return Err(error::Error::UnexpectedEnd);
3154 }
3155
3156 if let Ok(tail) = consume(b"h", input) {
3157 let (offset, tail) = NvOffset::parse(ctx, subs, tail)?;
3158 let tail = consume(b"_", tail)?;
3159 return Ok((CallOffset::NonVirtual(offset), tail));
3160 }
3161
3162 if let Ok(tail) = consume(b"v", input) {
3163 let (offset, tail) = VOffset::parse(ctx, subs, tail)?;
3164 let tail = consume(b"_", tail)?;
3165 return Ok((CallOffset::Virtual(offset), tail));
3166 }
3167
3168 Err(error::Error::UnexpectedText)
3169 }
3170}
3171
3172impl<'subs, W> Demangle<'subs, W> for CallOffset
3173where
3174 W: 'subs + DemangleWrite,
3175{
3176 fn demangle<'prev, 'ctx>(
3177 &'subs self,
3178 ctx: &'ctx mut DemangleContext<'subs, W>,
3179 scope: Option<ArgScopeStack<'prev, 'subs>>,
3180 ) -> fmt::Result {
3181 let ctx = try_begin_demangle!(self, ctx, scope);
3182
3183 match *self {
3184 CallOffset::NonVirtual(NvOffset(offset)) => {
3185 write!(ctx, "{{offset({})}}", offset)?;
3186 }
3187 CallOffset::Virtual(VOffset(vbase, vcall)) => {
3188 write!(ctx, "{{virtual offset({}, {})}}", vbase, vcall)?;
3189 }
3190 }
3191 Ok(())
3192 }
3193}
3194
3195#[derive(Clone, Debug, PartialEq, Eq)]
3201pub struct NvOffset(isize);
3202
3203impl Parse for NvOffset {
3204 fn parse<'a, 'b>(
3205 ctx: &'a ParseContext,
3206 subs: &'a mut SubstitutionTable,
3207 input: IndexStr<'b>,
3208 ) -> Result<(NvOffset, IndexStr<'b>)> {
3209 try_begin_parse!("NvOffset", ctx, input);
3210
3211 Number::parse(ctx, subs, input).map(|(num, tail)| (NvOffset(num), tail))
3212 }
3213}
3214
3215#[derive(Clone, Debug, PartialEq, Eq)]
3221pub struct VOffset(isize, isize);
3222
3223impl Parse for VOffset {
3224 fn parse<'a, 'b>(
3225 ctx: &'a ParseContext,
3226 subs: &'a mut SubstitutionTable,
3227 input: IndexStr<'b>,
3228 ) -> Result<(VOffset, IndexStr<'b>)> {
3229 try_begin_parse!("VOffset", ctx, input);
3230
3231 let (offset, tail) = Number::parse(ctx, subs, input)?;
3232 let tail = consume(b"_", tail)?;
3233 let (virtual_offset, tail) = Number::parse(ctx, subs, tail)?;
3234 Ok((VOffset(offset, virtual_offset), tail))
3235 }
3236}
3237
3238#[derive(Clone, Debug, PartialEq, Eq)]
3261pub enum CtorDtorName {
3262 CompleteConstructor(Option<Box<Name>>),
3264 BaseConstructor(Option<Box<Name>>),
3266 CompleteAllocatingConstructor(Option<Box<Name>>),
3268 MaybeInChargeConstructor(Option<Box<Name>>),
3270 DeletingDestructor,
3272 CompleteDestructor,
3274 BaseDestructor,
3276 MaybeInChargeDestructor,
3278}
3279
3280impl CtorDtorName {
3281 fn inheriting_mut(&mut self) -> &mut Option<Box<Name>> {
3282 match self {
3283 CtorDtorName::CompleteConstructor(ref mut inheriting)
3284 | CtorDtorName::BaseConstructor(ref mut inheriting)
3285 | CtorDtorName::CompleteAllocatingConstructor(ref mut inheriting)
3286 | CtorDtorName::MaybeInChargeConstructor(ref mut inheriting) => inheriting,
3287 CtorDtorName::DeletingDestructor
3288 | CtorDtorName::CompleteDestructor
3289 | CtorDtorName::BaseDestructor
3290 | CtorDtorName::MaybeInChargeDestructor => unreachable!(),
3291 }
3292 }
3293}
3294
3295impl Parse for CtorDtorName {
3296 fn parse<'a, 'b>(
3297 ctx: &'a ParseContext,
3298 subs: &'a mut SubstitutionTable,
3299 input: IndexStr<'b>,
3300 ) -> Result<(CtorDtorName, IndexStr<'b>)> {
3301 try_begin_parse!(stringify!(CtorDtorName), ctx, input);
3302
3303 match input.peek() {
3304 Some(b'C') => {
3305 let mut tail = consume(b"C", input)?;
3306 let inheriting = match tail.peek() {
3307 Some(b'I') => {
3308 tail = consume(b"I", tail)?;
3309 true
3310 }
3311 _ => false,
3312 };
3313
3314 let mut ctor_type: CtorDtorName = match tail
3315 .try_split_at(1)
3316 .as_ref()
3317 .map(|&(ref h, t)| (h.as_ref(), t))
3318 {
3319 None => Err(error::Error::UnexpectedEnd),
3320 Some((b"1", t)) => {
3321 tail = t;
3322 Ok(CtorDtorName::CompleteConstructor(None))
3323 }
3324 Some((b"2", t)) => {
3325 tail = t;
3326 Ok(CtorDtorName::BaseConstructor(None))
3327 }
3328 Some((b"3", t)) => {
3329 tail = t;
3330 Ok(CtorDtorName::CompleteAllocatingConstructor(None))
3331 }
3332 Some((b"4", t)) => {
3333 tail = t;
3334 Ok(CtorDtorName::MaybeInChargeConstructor(None))
3335 }
3336 _ => Err(error::Error::UnexpectedText),
3337 }?;
3338
3339 if inheriting {
3340 let (ty, tail) = Name::parse(ctx, subs, tail)?;
3341 *ctor_type.inheriting_mut() = Some(Box::new(ty));
3342 Ok((ctor_type, tail))
3343 } else {
3344 Ok((ctor_type, tail))
3345 }
3346 }
3347 Some(b'D') => {
3348 match input
3349 .try_split_at(2)
3350 .as_ref()
3351 .map(|&(ref h, t)| (h.as_ref(), t))
3352 {
3353 Some((b"D0", tail)) => Ok((CtorDtorName::DeletingDestructor, tail)),
3354 Some((b"D1", tail)) => Ok((CtorDtorName::CompleteDestructor, tail)),
3355 Some((b"D2", tail)) => Ok((CtorDtorName::BaseDestructor, tail)),
3356 Some((b"D4", tail)) => Ok((CtorDtorName::MaybeInChargeDestructor, tail)),
3357 _ => Err(error::Error::UnexpectedText),
3358 }
3359 }
3360 None => Err(error::Error::UnexpectedEnd),
3361 _ => Err(error::Error::UnexpectedText),
3362 }
3363 }
3364}
3365
3366impl<'subs, W> Demangle<'subs, W> for CtorDtorName
3367where
3368 W: 'subs + DemangleWrite,
3369{
3370 fn demangle<'prev, 'ctx>(
3371 &'subs self,
3372 ctx: &'ctx mut DemangleContext<'subs, W>,
3373 scope: Option<ArgScopeStack<'prev, 'subs>>,
3374 ) -> fmt::Result {
3375 let ctx = try_begin_demangle!(self, ctx, scope);
3376
3377 let leaf = scope.leaf_name().map_err(|e| {
3378 log!("Error getting leaf name: {}", e);
3379 fmt::Error
3380 })?;
3381
3382 match *self {
3383 CtorDtorName::CompleteConstructor(ref inheriting)
3384 | CtorDtorName::BaseConstructor(ref inheriting)
3385 | CtorDtorName::CompleteAllocatingConstructor(ref inheriting)
3386 | CtorDtorName::MaybeInChargeConstructor(ref inheriting) => match inheriting {
3387 Some(ty) => ty
3388 .get_leaf_name(ctx.subs)
3389 .ok_or_else(|| {
3390 log!("Error getting leaf name: {:?}", ty);
3391 fmt::Error
3392 })?
3393 .demangle_as_leaf(ctx),
3394 None => leaf.demangle_as_leaf(ctx),
3395 },
3396 CtorDtorName::DeletingDestructor
3397 | CtorDtorName::CompleteDestructor
3398 | CtorDtorName::BaseDestructor
3399 | CtorDtorName::MaybeInChargeDestructor => {
3400 write!(ctx, "~")?;
3401 leaf.demangle_as_leaf(ctx)
3402 }
3403 }
3404 }
3405}
3406
3407impl CtorDtorName {
3408 #[inline]
3409 fn starts_with(byte: u8) -> bool {
3410 byte == b'C' || byte == b'D'
3411 }
3412}
3413
3414#[derive(Clone, Debug, PartialEq, Eq)]
3437#[allow(clippy::large_enum_variant)]
3438pub enum Type {
3439 Function(FunctionType),
3441
3442 ClassEnum(ClassEnumType),
3444
3445 Array(ArrayType),
3447
3448 Vector(VectorType),
3450
3451 PointerToMember(PointerToMemberType),
3453
3454 TemplateParam(TemplateParam),
3456
3457 TemplateTemplate(TemplateTemplateParamHandle, TemplateArgs),
3459
3460 Decltype(Decltype),
3462
3463 Qualified(CvQualifiers, TypeHandle),
3465
3466 PointerTo(TypeHandle),
3468
3469 LvalueRef(TypeHandle),
3471
3472 RvalueRef(TypeHandle),
3474
3475 Complex(TypeHandle),
3477
3478 Imaginary(TypeHandle),
3480
3481 VendorExtension(SourceName, Option<TemplateArgs>, TypeHandle),
3483
3484 PackExpansion(TypeHandle),
3486}
3487
3488define_handle! {
3489 pub enum TypeHandle {
3491 extra Builtin(BuiltinType),
3493
3494 extra QualifiedBuiltin(QualifiedBuiltin),
3496 }
3497}
3498
3499impl TypeHandle {
3500 fn is_void(&self) -> bool {
3501 match *self {
3502 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Void)) => true,
3503 _ => false,
3504 }
3505 }
3506}
3507
3508impl Parse for TypeHandle {
3509 fn parse<'a, 'b>(
3510 ctx: &'a ParseContext,
3511 subs: &'a mut SubstitutionTable,
3512 input: IndexStr<'b>,
3513 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3514 try_begin_parse!("TypeHandle", ctx, input);
3515
3516 fn insert_and_return_handle<'a, 'b>(
3519 ty: Type,
3520 subs: &'a mut SubstitutionTable,
3521 tail: IndexStr<'b>,
3522 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3523 let ty = Substitutable::Type(ty);
3524 let idx = subs.insert(ty);
3525 let handle = TypeHandle::BackReference(idx);
3526 Ok((handle, tail))
3527 }
3528
3529 if let Ok((builtin, tail)) = BuiltinType::parse(ctx, subs, input) {
3530 let handle = TypeHandle::Builtin(builtin);
3533 return Ok((handle, tail));
3534 }
3535
3536 if let Ok((ty, tail)) = ClassEnumType::parse(ctx, subs, input) {
3537 let ty = Type::ClassEnum(ty);
3538 return insert_and_return_handle(ty, subs, tail);
3539 }
3540
3541 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
3542 if tail.peek() != Some(b'I') {
3548 match sub {
3549 Substitution::WellKnown(component) => {
3550 return Ok((TypeHandle::WellKnown(component), tail));
3551 }
3552 Substitution::BackReference(idx) => {
3553 return Ok((TypeHandle::BackReference(idx), tail));
3556 }
3557 }
3558 }
3559 }
3560
3561 if let Ok((funty, tail)) = FunctionType::parse(ctx, subs, input) {
3562 let ty = Type::Function(funty);
3563 return insert_and_return_handle(ty, subs, tail);
3564 }
3565
3566 if let Ok((ty, tail)) = ArrayType::parse(ctx, subs, input) {
3567 let ty = Type::Array(ty);
3568 return insert_and_return_handle(ty, subs, tail);
3569 }
3570
3571 if let Ok((ty, tail)) = VectorType::parse(ctx, subs, input) {
3572 let ty = Type::Vector(ty);
3573 return insert_and_return_handle(ty, subs, tail);
3574 }
3575
3576 if let Ok((ty, tail)) = PointerToMemberType::parse(ctx, subs, input) {
3577 let ty = Type::PointerToMember(ty);
3578 return insert_and_return_handle(ty, subs, tail);
3579 }
3580
3581 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
3582 if tail.peek() != Some(b'I') {
3586 let ty = Type::TemplateParam(param);
3587 return insert_and_return_handle(ty, subs, tail);
3588 } else if ctx.in_conversion() {
3589 let mut tmp_subs = subs.clone();
3602 if let Ok((_, new_tail)) = TemplateArgs::parse(ctx, &mut tmp_subs, tail) {
3603 if new_tail.peek() != Some(b'I') {
3604 let ty = Type::TemplateParam(param);
3606 return insert_and_return_handle(ty, subs, tail);
3607 }
3608 }
3614 }
3615 }
3616
3617 if let Ok((ttp, tail)) = TemplateTemplateParamHandle::parse(ctx, subs, input) {
3618 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
3619 let ty = Type::TemplateTemplate(ttp, args);
3620 return insert_and_return_handle(ty, subs, tail);
3621 }
3622
3623 if let Ok((param, tail)) = Decltype::parse(ctx, subs, input) {
3624 let ty = Type::Decltype(param);
3625 return insert_and_return_handle(ty, subs, tail);
3626 }
3627
3628 if let Ok((qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
3629 if tail.len() < input.len() {
3633 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3634 let ty = Type::Qualified(qualifiers, ty);
3635 return insert_and_return_handle(ty, subs, tail);
3636 }
3637 }
3638
3639 if let Ok(tail) = consume(b"P", input) {
3640 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3641 let ty = Type::PointerTo(ty);
3642 return insert_and_return_handle(ty, subs, tail);
3643 }
3644
3645 if let Ok(tail) = consume(b"R", input) {
3646 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3647 let ty = Type::LvalueRef(ty);
3648 return insert_and_return_handle(ty, subs, tail);
3649 }
3650
3651 if let Ok(tail) = consume(b"O", input) {
3652 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3653 let ty = Type::RvalueRef(ty);
3654 return insert_and_return_handle(ty, subs, tail);
3655 }
3656
3657 if let Ok(tail) = consume(b"C", input) {
3658 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3659 let ty = Type::Complex(ty);
3660 return insert_and_return_handle(ty, subs, tail);
3661 }
3662
3663 if let Ok(tail) = consume(b"G", input) {
3664 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3665 let ty = Type::Imaginary(ty);
3666 return insert_and_return_handle(ty, subs, tail);
3667 }
3668
3669 if let Ok(tail) = consume(b"U", input) {
3670 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3671 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
3672 (Some(args), tail)
3673 } else {
3674 (None, tail)
3675 };
3676 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3677 let ty = Type::VendorExtension(name, args, ty);
3678 return insert_and_return_handle(ty, subs, tail);
3679 }
3680
3681 let tail = consume(b"Dp", input)?;
3682 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3683 let ty = Type::PackExpansion(ty);
3684 insert_and_return_handle(ty, subs, tail)
3685 }
3686}
3687
3688impl GetTemplateArgs for TypeHandle {
3689 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3690 subs.get_type(self)
3691 .and_then(|ty| ty.get_template_args(subs))
3692 }
3693}
3694
3695impl<'subs, W> Demangle<'subs, W> for Type
3696where
3697 W: 'subs + DemangleWrite,
3698{
3699 fn demangle<'prev, 'ctx>(
3700 &'subs self,
3701 ctx: &'ctx mut DemangleContext<'subs, W>,
3702 scope: Option<ArgScopeStack<'prev, 'subs>>,
3703 ) -> fmt::Result {
3704 let ctx = try_begin_demangle!(self, ctx, scope);
3705
3706 match *self {
3707 Type::Function(ref func_ty) => func_ty.demangle(ctx, scope),
3708 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.demangle(ctx, scope),
3709 Type::Array(ref array_ty) => array_ty.demangle(ctx, scope),
3710 Type::Vector(ref vector_ty) => vector_ty.demangle(ctx, scope),
3711 Type::PointerToMember(ref ptm) => ptm.demangle(ctx, scope),
3712 Type::TemplateParam(ref param) => param.demangle(ctx, scope),
3713 Type::TemplateTemplate(ref tt_param, ref args) => {
3714 tt_param.demangle(ctx, scope)?;
3715 args.demangle(ctx, scope)
3716 }
3717 Type::Decltype(ref dt) => dt.demangle(ctx, scope),
3718 Type::Qualified(_, ref ty) => {
3719 ctx.push_inner(self);
3720 ty.demangle(ctx, scope)?;
3721 if ctx.pop_inner_if(self) {
3722 self.demangle_as_inner(ctx, scope)?;
3723 }
3724 Ok(())
3725 }
3726 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3727 ctx.push_inner(self);
3728 ty.demangle(ctx, scope)?;
3729 if ctx.pop_inner_if(self) {
3730 self.demangle_as_inner(ctx, scope)?;
3731 }
3732 Ok(())
3733 }
3734 Type::Complex(ref ty) => {
3735 ty.demangle(ctx, scope)?;
3736 write!(ctx, " complex")?;
3737 Ok(())
3738 }
3739 Type::Imaginary(ref ty) => {
3740 ty.demangle(ctx, scope)?;
3741 write!(ctx, " imaginary")?;
3742 Ok(())
3743 }
3744 Type::VendorExtension(ref name, ref template_args, ref ty) => {
3745 ty.demangle(ctx, scope)?;
3746 write!(ctx, " ")?;
3747 name.demangle(ctx, scope)?;
3748 if let Some(ref args) = *template_args {
3749 args.demangle(ctx, scope)?;
3750 }
3751 Ok(())
3752 }
3753 Type::PackExpansion(ref ty) => {
3754 ty.demangle(ctx, scope)?;
3755 if !ctx.is_template_argument_pack {
3756 write!(ctx, "...")?;
3757 }
3758 Ok(())
3759 }
3760 }
3761 }
3762}
3763
3764impl<'subs, W> DemangleAsInner<'subs, W> for Type
3765where
3766 W: 'subs + DemangleWrite,
3767{
3768 fn demangle_as_inner<'prev, 'ctx>(
3769 &'subs self,
3770 ctx: &'ctx mut DemangleContext<'subs, W>,
3771 scope: Option<ArgScopeStack<'prev, 'subs>>,
3772 ) -> fmt::Result {
3773 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
3774
3775 match *self {
3776 Type::Qualified(ref quals, _) => quals.demangle_as_inner(ctx, scope),
3777 Type::PointerTo(_) => write!(ctx, "*"),
3778 Type::RvalueRef(_) => {
3779 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3780 match v {
3781 Type::RvalueRef(_) => {
3784 ctx.inner.pop().unwrap();
3785 }
3786 Type::LvalueRef(_) => return Ok(()),
3790 _ => break,
3791 }
3792 }
3793 write!(ctx, "&&")
3794 }
3795 Type::LvalueRef(_) => {
3796 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3797 match v {
3798 Type::RvalueRef(_) => {
3802 ctx.inner.pop().unwrap();
3803 }
3804 Type::LvalueRef(_) => return Ok(()),
3808 _ => break,
3809 }
3810 }
3811 write!(ctx, "&")
3812 }
3813 ref otherwise => {
3814 unreachable!(
3815 "We shouldn't ever put any other types on the inner stack: {:?}",
3816 otherwise
3817 );
3818 }
3819 }
3820 }
3821
3822 fn downcast_to_type(&self) -> Option<&Type> {
3823 Some(self)
3824 }
3825
3826 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
3827 if let Type::Function(ref f) = *self {
3828 Some(f)
3829 } else {
3830 None
3831 }
3832 }
3833
3834 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
3835 if let Type::Array(ref arr) = *self {
3836 Some(arr)
3837 } else {
3838 None
3839 }
3840 }
3841
3842 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
3843 if let Type::PointerToMember(ref ptm) = *self {
3844 Some(ptm)
3845 } else {
3846 None
3847 }
3848 }
3849
3850 fn is_qualified(&self) -> bool {
3851 match *self {
3852 Type::Qualified(..) => true,
3853 _ => false,
3854 }
3855 }
3856}
3857
3858impl GetTemplateArgs for Type {
3859 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3860 match *self {
3864 Type::VendorExtension(_, Some(ref args), _) | Type::TemplateTemplate(_, ref args) => {
3865 Some(args)
3866 }
3867 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3868 ty.get_template_args(subs)
3869 }
3870 _ => None,
3871 }
3872 }
3873}
3874
3875impl<'a> GetLeafName<'a> for Type {
3876 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
3877 match *self {
3878 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.get_leaf_name(subs),
3879 _ => None,
3880 }
3881 }
3882}
3883
3884#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
3890pub struct CvQualifiers {
3891 pub restrict: bool,
3893 pub volatile: bool,
3895 pub const_: bool,
3897}
3898
3899impl CvQualifiers {
3900 #[inline]
3901 fn is_empty(&self) -> bool {
3902 !self.restrict && !self.volatile && !self.const_
3903 }
3904}
3905
3906impl Parse for CvQualifiers {
3907 fn parse<'a, 'b>(
3908 ctx: &'a ParseContext,
3909 _subs: &'a mut SubstitutionTable,
3910 input: IndexStr<'b>,
3911 ) -> Result<(CvQualifiers, IndexStr<'b>)> {
3912 try_begin_parse!("CvQualifiers", ctx, input);
3913
3914 let (restrict, tail) = if let Ok(tail) = consume(b"r", input) {
3915 (true, tail)
3916 } else {
3917 (false, input)
3918 };
3919
3920 let (volatile, tail) = if let Ok(tail) = consume(b"V", tail) {
3921 (true, tail)
3922 } else {
3923 (false, tail)
3924 };
3925
3926 let (const_, tail) = if let Ok(tail) = consume(b"K", tail) {
3927 (true, tail)
3928 } else {
3929 (false, tail)
3930 };
3931
3932 let qualifiers = CvQualifiers {
3933 restrict: restrict,
3934 volatile: volatile,
3935 const_: const_,
3936 };
3937
3938 Ok((qualifiers, tail))
3939 }
3940}
3941
3942impl<'subs, W> Demangle<'subs, W> for CvQualifiers
3943where
3944 W: 'subs + DemangleWrite,
3945{
3946 fn demangle<'prev, 'ctx>(
3947 &'subs self,
3948 ctx: &'ctx mut DemangleContext<'subs, W>,
3949 scope: Option<ArgScopeStack<'prev, 'subs>>,
3950 ) -> fmt::Result {
3951 let ctx = try_begin_demangle!(self, ctx, scope);
3952
3953 if self.const_ {
3954 ctx.ensure_space()?;
3955 write!(ctx, "const")?;
3956 }
3957
3958 if self.volatile {
3959 ctx.ensure_space()?;
3960 write!(ctx, "volatile")?;
3961 }
3962
3963 if self.restrict {
3964 ctx.ensure_space()?;
3965 write!(ctx, "restrict")?;
3966 }
3967
3968 Ok(())
3969 }
3970}
3971
3972impl<'subs, W> DemangleAsInner<'subs, W> for CvQualifiers where W: 'subs + DemangleWrite {}
3973
3974define_vocabulary! {
3975 #[derive(Clone, Debug, PartialEq, Eq)]
3982 pub enum RefQualifier {
3983 LValueRef(b"R", "&"),
3984 RValueRef(b"O", "&&")
3985 }
3986}
3987
3988define_vocabulary! {
3989 #[derive(Clone, Debug, PartialEq, Eq)]
4025 pub enum StandardBuiltinType {
4026 Void (b"v", "void"),
4027 Wchar (b"w", "wchar_t"),
4028 Bool (b"b", "bool"),
4029 Char (b"c", "char"),
4030 SignedChar (b"a", "signed char"),
4031 UnsignedChar (b"h", "unsigned char"),
4032 Short (b"s", "short"),
4033 UnsignedShort (b"t", "unsigned short"),
4034 Int (b"i", "int"),
4035 UnsignedInt (b"j", "unsigned int"),
4036 Long (b"l", "long"),
4037 UnsignedLong (b"m", "unsigned long"),
4038 LongLong (b"x", "long long"),
4039 UnsignedLongLong (b"y", "unsigned long long"),
4040 Int128 (b"n", "__int128"),
4041 Uint128 (b"o", "unsigned __int128"),
4042 Float (b"f", "float"),
4043 Double (b"d", "double"),
4044 LongDouble (b"e", "long double"),
4045 Float128 (b"g", "__float128"),
4046 Ellipsis (b"z", "..."),
4047 DecimalFloat64 (b"Dd", "decimal64"),
4048 DecimalFloat128 (b"De", "decimal128"),
4049 DecimalFloat32 (b"Df", "decimal32"),
4050 DecimalFloat16 (b"Dh", "half"),
4051 Char32 (b"Di", "char32_t"),
4052 Char16 (b"Ds", "char16_t"),
4053 Char8 (b"Du", "char8_t"),
4054 Auto (b"Da", "auto"),
4055 Decltype (b"Dc", "decltype(auto)"),
4056 Nullptr (b"Dn", "std::nullptr_t")
4057 }
4058}
4059
4060#[derive(Clone, Debug, PartialEq, Eq)]
4062pub enum BuiltinType {
4063 Standard(StandardBuiltinType),
4065
4066 Extension(SourceName),
4072}
4073
4074impl Parse for BuiltinType {
4075 fn parse<'a, 'b>(
4076 ctx: &'a ParseContext,
4077 subs: &'a mut SubstitutionTable,
4078 input: IndexStr<'b>,
4079 ) -> Result<(BuiltinType, IndexStr<'b>)> {
4080 try_begin_parse!("BuiltinType", ctx, input);
4081
4082 if let Ok((ty, tail)) = StandardBuiltinType::parse(ctx, subs, input) {
4083 return Ok((BuiltinType::Standard(ty), tail));
4084 }
4085
4086 let tail = consume(b"u", input)?;
4087 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4088 Ok((BuiltinType::Extension(name), tail))
4089 }
4090}
4091
4092impl<'subs, W> Demangle<'subs, W> for BuiltinType
4093where
4094 W: 'subs + DemangleWrite,
4095{
4096 fn demangle<'prev, 'ctx>(
4097 &'subs self,
4098 ctx: &'ctx mut DemangleContext<'subs, W>,
4099 scope: Option<ArgScopeStack<'prev, 'subs>>,
4100 ) -> fmt::Result {
4101 let ctx = try_begin_demangle!(self, ctx, scope);
4102
4103 match *self {
4104 BuiltinType::Standard(ref ty) => ty.demangle(ctx, scope),
4105 BuiltinType::Extension(ref name) => name.demangle(ctx, scope),
4106 }
4107 }
4108}
4109
4110impl<'a> GetLeafName<'a> for BuiltinType {
4111 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4112 None
4113 }
4114}
4115
4116#[derive(Clone, Debug, PartialEq, Eq)]
4121pub struct QualifiedBuiltin(CvQualifiers, BuiltinType);
4122
4123impl<'subs, W> Demangle<'subs, W> for QualifiedBuiltin
4124where
4125 W: 'subs + DemangleWrite,
4126{
4127 fn demangle<'prev, 'ctx>(
4128 &'subs self,
4129 ctx: &'ctx mut DemangleContext<'subs, W>,
4130 scope: Option<ArgScopeStack<'prev, 'subs>>,
4131 ) -> fmt::Result {
4132 let ctx = try_begin_demangle!(self, ctx, scope);
4133
4134 ctx.push_inner(&self.0);
4135 self.1.demangle(ctx, scope)?;
4136 if ctx.pop_inner_if(&self.0) {
4137 self.0.demangle_as_inner(ctx, scope)?;
4138 }
4139 Ok(())
4140 }
4141}
4142
4143impl<'a> GetLeafName<'a> for QualifiedBuiltin {
4144 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4145 None
4146 }
4147}
4148
4149#[derive(Clone, Debug, PartialEq, Eq)]
4155pub enum ExceptionSpec {
4156 NoExcept,
4158 Computed(Expression),
4160 }
4163
4164impl Parse for ExceptionSpec {
4165 fn parse<'a, 'b>(
4166 ctx: &'a ParseContext,
4167 subs: &'a mut SubstitutionTable,
4168 input: IndexStr<'b>,
4169 ) -> Result<(ExceptionSpec, IndexStr<'b>)> {
4170 try_begin_parse!("ExceptionSpec", ctx, input);
4171
4172 if let Ok(tail) = consume(b"Do", input) {
4173 return Ok((ExceptionSpec::NoExcept, tail));
4174 }
4175
4176 let tail = consume(b"DO", input)?;
4177 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4178 let tail = consume(b"E", tail)?;
4179 Ok((ExceptionSpec::Computed(expr), tail))
4180 }
4181}
4182
4183impl<'subs, W> Demangle<'subs, W> for ExceptionSpec
4184where
4185 W: 'subs + DemangleWrite,
4186{
4187 fn demangle<'prev, 'ctx>(
4188 &'subs self,
4189 ctx: &'ctx mut DemangleContext<'subs, W>,
4190 scope: Option<ArgScopeStack<'prev, 'subs>>,
4191 ) -> fmt::Result {
4192 let ctx = try_begin_demangle!(self, ctx, scope);
4193
4194 match *self {
4195 ExceptionSpec::NoExcept => write!(ctx, "noexcept"),
4196 ExceptionSpec::Computed(ref expr) => {
4197 write!(ctx, "noexcept(")?;
4198 expr.demangle(ctx, scope)?;
4199 write!(ctx, ")")
4200 }
4201 }
4202 }
4203}
4204
4205#[derive(Clone, Debug, PartialEq, Eq)]
4211pub struct FunctionType {
4212 cv_qualifiers: CvQualifiers,
4213 exception_spec: Option<ExceptionSpec>,
4214 transaction_safe: bool,
4215 extern_c: bool,
4216 bare: BareFunctionType,
4217 ref_qualifier: Option<RefQualifier>,
4218}
4219
4220impl Parse for FunctionType {
4221 fn parse<'a, 'b>(
4222 ctx: &'a ParseContext,
4223 subs: &'a mut SubstitutionTable,
4224 input: IndexStr<'b>,
4225 ) -> Result<(FunctionType, IndexStr<'b>)> {
4226 try_begin_parse!("FunctionType", ctx, input);
4227
4228 let (cv_qualifiers, tail) =
4229 if let Ok((cv_qualifiers, tail)) = CvQualifiers::parse(ctx, subs, input) {
4230 (cv_qualifiers, tail)
4231 } else {
4232 (Default::default(), input)
4233 };
4234
4235 let (exception_spec, tail) =
4236 if let Ok((exception_spec, tail)) = ExceptionSpec::parse(ctx, subs, tail) {
4237 (Some(exception_spec), tail)
4238 } else {
4239 (None, tail)
4240 };
4241
4242 let (transaction_safe, tail) = if let Ok(tail) = consume(b"Dx", tail) {
4243 (true, tail)
4244 } else {
4245 (false, tail)
4246 };
4247
4248 let tail = consume(b"F", tail)?;
4249
4250 let (extern_c, tail) = if let Ok(tail) = consume(b"Y", tail) {
4251 (true, tail)
4252 } else {
4253 (false, tail)
4254 };
4255
4256 let (bare, tail) = BareFunctionType::parse(ctx, subs, tail)?;
4257
4258 let (ref_qualifier, tail) =
4259 if let Ok((ref_qualifier, tail)) = RefQualifier::parse(ctx, subs, tail) {
4260 (Some(ref_qualifier), tail)
4261 } else {
4262 (None, tail)
4263 };
4264
4265 let tail = consume(b"E", tail)?;
4266
4267 let func_ty = FunctionType {
4268 cv_qualifiers: cv_qualifiers,
4269 exception_spec: exception_spec,
4270 transaction_safe: transaction_safe,
4271 extern_c: extern_c,
4272 bare: bare,
4273 ref_qualifier: ref_qualifier,
4274 };
4275 Ok((func_ty, tail))
4276 }
4277}
4278
4279impl<'subs, W> Demangle<'subs, W> for FunctionType
4280where
4281 W: 'subs + DemangleWrite,
4282{
4283 fn demangle<'prev, 'ctx>(
4284 &'subs self,
4285 ctx: &'ctx mut DemangleContext<'subs, W>,
4286 scope: Option<ArgScopeStack<'prev, 'subs>>,
4287 ) -> fmt::Result {
4288 let ctx = try_begin_demangle!(self, ctx, scope);
4289
4290 ctx.push_inner(self);
4291 self.bare.demangle(ctx, scope)?;
4292 if ctx.pop_inner_if(self) {
4293 self.demangle_as_inner(ctx, scope)?;
4294 }
4295 if let Some(ref es) = self.exception_spec {
4296 ctx.ensure_space()?;
4298 es.demangle(ctx, scope)?;
4299 }
4300 Ok(())
4301 }
4302}
4303
4304impl<'subs, W> DemangleAsInner<'subs, W> for FunctionType
4305where
4306 W: 'subs + DemangleWrite,
4307{
4308 fn demangle_as_inner<'prev, 'ctx>(
4309 &'subs self,
4310 ctx: &'ctx mut DemangleContext<'subs, W>,
4311 scope: Option<ArgScopeStack<'prev, 'subs>>,
4312 ) -> fmt::Result {
4313 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4314
4315 if !self.cv_qualifiers.is_empty() {
4316 self.cv_qualifiers.demangle(ctx, scope)?;
4317 }
4318
4319 if let Some(ref rq) = self.ref_qualifier {
4320 ctx.ensure_space()?;
4322 rq.demangle(ctx, scope)?;
4323 }
4324
4325 Ok(())
4326 }
4327
4328 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
4329 Some(self)
4330 }
4331}
4332
4333#[derive(Clone, Debug, PartialEq, Eq)]
4340pub struct BareFunctionType(Vec<TypeHandle>);
4341
4342impl BareFunctionType {
4343 fn ret(&self) -> &TypeHandle {
4344 &self.0[0]
4345 }
4346
4347 fn args(&self) -> &FunctionArgListAndReturnType {
4348 FunctionArgListAndReturnType::new(&self.0)
4349 }
4350}
4351
4352impl Parse for BareFunctionType {
4353 fn parse<'a, 'b>(
4354 ctx: &'a ParseContext,
4355 subs: &'a mut SubstitutionTable,
4356 input: IndexStr<'b>,
4357 ) -> Result<(BareFunctionType, IndexStr<'b>)> {
4358 try_begin_parse!("BareFunctionType", ctx, input);
4359
4360 let (types, tail) = one_or_more::<TypeHandle>(ctx, subs, input)?;
4361 Ok((BareFunctionType(types), tail))
4362 }
4363}
4364
4365impl<'subs, W> Demangle<'subs, W> for BareFunctionType
4366where
4367 W: 'subs + DemangleWrite,
4368{
4369 fn demangle<'prev, 'ctx>(
4370 &'subs self,
4371 ctx: &'ctx mut DemangleContext<'subs, W>,
4372 scope: Option<ArgScopeStack<'prev, 'subs>>,
4373 ) -> fmt::Result {
4374 let ctx = try_begin_demangle!(self, ctx, scope);
4375
4376 ctx.push_inner(self);
4377
4378 self.ret().demangle(ctx, scope)?;
4379
4380 if ctx.pop_inner_if(self) {
4381 ctx.ensure_space()?;
4382 self.demangle_as_inner(ctx, scope)?;
4383 }
4384
4385 Ok(())
4386 }
4387}
4388
4389impl<'subs, W> DemangleAsInner<'subs, W> for BareFunctionType
4390where
4391 W: 'subs + DemangleWrite,
4392{
4393 fn demangle_as_inner<'prev, 'ctx>(
4394 &'subs self,
4395 ctx: &'ctx mut DemangleContext<'subs, W>,
4396 scope: Option<ArgScopeStack<'prev, 'subs>>,
4397 ) -> fmt::Result {
4398 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4399 self.args().demangle_as_inner(ctx, scope)?;
4400 Ok(())
4401 }
4402}
4403
4404#[derive(Clone, Debug, PartialEq, Eq)]
4411pub enum Decltype {
4412 IdExpression(Expression),
4414
4415 Expression(Expression),
4417}
4418
4419impl Parse for Decltype {
4420 fn parse<'a, 'b>(
4421 ctx: &'a ParseContext,
4422 subs: &'a mut SubstitutionTable,
4423 input: IndexStr<'b>,
4424 ) -> Result<(Decltype, IndexStr<'b>)> {
4425 try_begin_parse!("Decltype", ctx, input);
4426
4427 let tail = consume(b"D", input)?;
4428
4429 if let Ok(tail) = consume(b"t", tail) {
4430 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4431 let tail = consume(b"E", tail)?;
4432 return Ok((Decltype::IdExpression(expr), tail));
4433 }
4434
4435 let tail = consume(b"T", tail)?;
4436 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4437 let tail = consume(b"E", tail)?;
4438 Ok((Decltype::Expression(expr), tail))
4439 }
4440}
4441
4442impl<'subs, W> Demangle<'subs, W> for Decltype
4443where
4444 W: 'subs + DemangleWrite,
4445{
4446 fn demangle<'prev, 'ctx>(
4447 &'subs self,
4448 ctx: &'ctx mut DemangleContext<'subs, W>,
4449 scope: Option<ArgScopeStack<'prev, 'subs>>,
4450 ) -> fmt::Result {
4451 let ctx = try_begin_demangle!(self, ctx, scope);
4452
4453 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4454 let ret = match *self {
4455 Decltype::Expression(ref expr) | Decltype::IdExpression(ref expr) => {
4456 write!(ctx, "decltype (")?;
4457 expr.demangle(ctx, scope)?;
4458 write!(ctx, ")")?;
4459 Ok(())
4460 }
4461 };
4462 ctx.pop_demangle_node();
4463 ret
4464 }
4465}
4466
4467#[derive(Clone, Debug, PartialEq, Eq)]
4476pub enum ClassEnumType {
4477 Named(Name),
4480
4481 ElaboratedStruct(Name),
4483
4484 ElaboratedUnion(Name),
4486
4487 ElaboratedEnum(Name),
4489}
4490
4491impl Parse for ClassEnumType {
4492 fn parse<'a, 'b>(
4493 ctx: &'a ParseContext,
4494 subs: &'a mut SubstitutionTable,
4495 input: IndexStr<'b>,
4496 ) -> Result<(ClassEnumType, IndexStr<'b>)> {
4497 try_begin_parse!("ClassEnumType", ctx, input);
4498
4499 if let Ok((name, tail)) = Name::parse(ctx, subs, input) {
4500 return Ok((ClassEnumType::Named(name), tail));
4501 }
4502
4503 let tail = consume(b"T", input)?;
4504
4505 if let Ok(tail) = consume(b"s", tail) {
4506 let (name, tail) = Name::parse(ctx, subs, tail)?;
4507 return Ok((ClassEnumType::ElaboratedStruct(name), tail));
4508 }
4509
4510 if let Ok(tail) = consume(b"u", tail) {
4511 let (name, tail) = Name::parse(ctx, subs, tail)?;
4512 return Ok((ClassEnumType::ElaboratedUnion(name), tail));
4513 }
4514
4515 let tail = consume(b"e", tail)?;
4516 let (name, tail) = Name::parse(ctx, subs, tail)?;
4517 Ok((ClassEnumType::ElaboratedEnum(name), tail))
4518 }
4519}
4520
4521impl<'subs, W> Demangle<'subs, W> for ClassEnumType
4522where
4523 W: 'subs + DemangleWrite,
4524{
4525 fn demangle<'prev, 'ctx>(
4526 &'subs self,
4527 ctx: &'ctx mut DemangleContext<'subs, W>,
4528 scope: Option<ArgScopeStack<'prev, 'subs>>,
4529 ) -> fmt::Result {
4530 let ctx = try_begin_demangle!(self, ctx, scope);
4531
4532 match *self {
4533 ClassEnumType::Named(ref name) => name.demangle(ctx, scope),
4534 ClassEnumType::ElaboratedStruct(ref name) => {
4535 write!(ctx, "class ")?;
4536 name.demangle(ctx, scope)
4537 }
4538 ClassEnumType::ElaboratedUnion(ref name) => {
4539 write!(ctx, "union ")?;
4540 name.demangle(ctx, scope)
4541 }
4542 ClassEnumType::ElaboratedEnum(ref name) => {
4543 write!(ctx, "enum ")?;
4544 name.demangle(ctx, scope)
4545 }
4546 }
4547 }
4548}
4549
4550impl<'a> GetLeafName<'a> for ClassEnumType {
4551 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4552 match *self {
4553 ClassEnumType::Named(ref name)
4554 | ClassEnumType::ElaboratedStruct(ref name)
4555 | ClassEnumType::ElaboratedUnion(ref name)
4556 | ClassEnumType::ElaboratedEnum(ref name) => name.get_leaf_name(subs),
4557 }
4558 }
4559}
4560
4561#[derive(Clone, Debug, PartialEq, Eq)]
4570pub struct UnnamedTypeName(Option<usize>);
4571
4572impl Parse for UnnamedTypeName {
4573 fn parse<'a, 'b>(
4574 ctx: &'a ParseContext,
4575 _subs: &'a mut SubstitutionTable,
4576 input: IndexStr<'b>,
4577 ) -> Result<(UnnamedTypeName, IndexStr<'b>)> {
4578 try_begin_parse!("UnnamedTypeName", ctx, input);
4579
4580 let input = consume(b"Ut", input)?;
4581 let (number, input) = match parse_number(10, false, input) {
4582 Ok((number, input)) => (Some(number as _), input),
4583 Err(_) => (None, input),
4584 };
4585 let input = consume(b"_", input)?;
4586 Ok((UnnamedTypeName(number), input))
4587 }
4588}
4589
4590impl UnnamedTypeName {
4591 #[inline]
4592 fn starts_with(byte: u8) -> bool {
4593 byte == b'U'
4594 }
4595}
4596
4597impl<'subs, W> Demangle<'subs, W> for UnnamedTypeName
4598where
4599 W: 'subs + DemangleWrite,
4600{
4601 fn demangle<'prev, 'ctx>(
4602 &'subs self,
4603 ctx: &'ctx mut DemangleContext<'subs, W>,
4604 scope: Option<ArgScopeStack<'prev, 'subs>>,
4605 ) -> fmt::Result {
4606 let ctx = try_begin_demangle!(self, ctx, scope);
4607
4608 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4609 Ok(())
4610 }
4611}
4612
4613impl<'subs, W> DemangleAsLeaf<'subs, W> for UnnamedTypeName
4614where
4615 W: 'subs + DemangleWrite,
4616{
4617 fn demangle_as_leaf<'me, 'ctx>(
4618 &'me self,
4619 ctx: &'ctx mut DemangleContext<'subs, W>,
4620 ) -> fmt::Result {
4621 let ctx = try_begin_demangle!(self, ctx, None);
4622 if let Some(source_name) = ctx.source_name {
4623 write!(ctx, "{}", source_name)?;
4624 } else {
4625 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4626 }
4627 Ok(())
4628 }
4629}
4630
4631impl<'subs> ArgScope<'subs, 'subs> for UnnamedTypeName {
4632 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
4633 Ok(LeafName::UnnamedType(self))
4634 }
4635
4636 fn get_template_arg(
4637 &'subs self,
4638 _: usize,
4639 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
4640 Err(error::Error::BadTemplateArgReference)
4641 }
4642
4643 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
4644 Err(error::Error::BadFunctionArgReference)
4645 }
4646}
4647
4648#[derive(Clone, Debug, PartialEq, Eq)]
4655pub enum ArrayType {
4656 DimensionNumber(usize, TypeHandle),
4658
4659 DimensionExpression(Expression, TypeHandle),
4661
4662 NoDimension(TypeHandle),
4664}
4665
4666impl Parse for ArrayType {
4667 fn parse<'a, 'b>(
4668 ctx: &'a ParseContext,
4669 subs: &'a mut SubstitutionTable,
4670 input: IndexStr<'b>,
4671 ) -> Result<(ArrayType, IndexStr<'b>)> {
4672 try_begin_parse!("ArrayType", ctx, input);
4673
4674 let tail = consume(b"A", input)?;
4675
4676 if let Ok((num, tail)) = parse_number(10, false, tail) {
4677 debug_assert!(num >= 0);
4678 let tail = consume(b"_", tail)?;
4679 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4680 return Ok((ArrayType::DimensionNumber(num as _, ty), tail));
4681 }
4682
4683 if let Ok((expr, tail)) = Expression::parse(ctx, subs, tail) {
4684 let tail = consume(b"_", tail)?;
4685 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4686 return Ok((ArrayType::DimensionExpression(expr, ty), tail));
4687 }
4688
4689 let tail = consume(b"_", tail)?;
4690 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4691 Ok((ArrayType::NoDimension(ty), tail))
4692 }
4693}
4694
4695impl<'subs, W> Demangle<'subs, W> for ArrayType
4696where
4697 W: 'subs + DemangleWrite,
4698{
4699 fn demangle<'prev, 'ctx>(
4700 &'subs self,
4701 ctx: &'ctx mut DemangleContext<'subs, W>,
4702 scope: Option<ArgScopeStack<'prev, 'subs>>,
4703 ) -> fmt::Result {
4704 let ctx = try_begin_demangle!(self, ctx, scope);
4705
4706 ctx.push_inner(self);
4707
4708 match *self {
4709 ArrayType::DimensionNumber(_, ref ty)
4710 | ArrayType::DimensionExpression(_, ref ty)
4711 | ArrayType::NoDimension(ref ty) => {
4712 ty.demangle(ctx, scope)?;
4713 }
4714 }
4715
4716 if ctx.pop_inner_if(self) {
4717 self.demangle_as_inner(ctx, scope)?;
4718 }
4719
4720 Ok(())
4721 }
4722}
4723
4724impl<'subs, W> DemangleAsInner<'subs, W> for ArrayType
4725where
4726 W: 'subs + DemangleWrite,
4727{
4728 fn demangle_as_inner<'prev, 'ctx>(
4729 &'subs self,
4730 ctx: &'ctx mut DemangleContext<'subs, W>,
4731 scope: Option<ArgScopeStack<'prev, 'subs>>,
4732 ) -> fmt::Result {
4733 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4734
4735 let mut needs_space = true;
4737
4738 while let Some(inner) = ctx.pop_inner() {
4739 let inner_is_array = match inner.downcast_to_type() {
4743 Some(&Type::Qualified(_, ref ty)) => ctx.subs.get_type(ty).map_or(false, |ty| {
4744 DemangleAsInner::<W>::downcast_to_array_type(ty).is_some()
4745 }),
4746 _ => {
4747 if inner.downcast_to_array_type().is_some() {
4748 needs_space = false;
4749 true
4750 } else {
4751 false
4752 }
4753 }
4754 };
4755
4756 if inner_is_array {
4757 inner.demangle_as_inner(ctx, scope)?;
4758 } else {
4759 ctx.ensure_space()?;
4760
4761 if inner.is_qualified() {
4763 inner.demangle_as_inner(ctx, scope)?;
4764 ctx.ensure_space()?;
4765 write!(ctx, "(")?;
4766 } else {
4767 write!(ctx, "(")?;
4768 inner.demangle_as_inner(ctx, scope)?;
4769 }
4770
4771 ctx.demangle_inners(scope)?;
4772 write!(ctx, ")")?;
4773 }
4774 }
4775
4776 if needs_space {
4777 ctx.ensure_space()?;
4778 }
4779
4780 match *self {
4781 ArrayType::DimensionNumber(n, _) => {
4782 write!(ctx, "[{}]", n)?;
4783 }
4784 ArrayType::DimensionExpression(ref expr, _) => {
4785 write!(ctx, "[")?;
4786 expr.demangle(ctx, scope)?;
4787 write!(ctx, "]")?;
4788 }
4789 ArrayType::NoDimension(_) => {
4790 write!(ctx, "[]")?;
4791 }
4792 }
4793
4794 Ok(())
4795 }
4796
4797 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
4798 Some(self)
4799 }
4800}
4801
4802#[derive(Clone, Debug, PartialEq, Eq)]
4809pub enum VectorType {
4810 DimensionNumber(usize, TypeHandle),
4812
4813 DimensionExpression(Expression, TypeHandle),
4815}
4816
4817impl Parse for VectorType {
4818 fn parse<'a, 'b>(
4819 ctx: &'a ParseContext,
4820 subs: &'a mut SubstitutionTable,
4821 input: IndexStr<'b>,
4822 ) -> Result<(VectorType, IndexStr<'b>)> {
4823 try_begin_parse!("VectorType", ctx, input);
4824
4825 let tail = consume(b"Dv", input)?;
4826
4827 if let Ok((num, tail)) = parse_number(10, false, tail) {
4828 debug_assert!(num >= 0);
4829 let tail = consume(b"_", tail)?;
4830 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4831 return Ok((VectorType::DimensionNumber(num as _, ty), tail));
4832 }
4833
4834 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4835 let tail = consume(b"_", tail)?;
4836 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4837 Ok((VectorType::DimensionExpression(expr, ty), tail))
4838 }
4839}
4840
4841impl<'subs, W> Demangle<'subs, W> for VectorType
4842where
4843 W: 'subs + DemangleWrite,
4844{
4845 fn demangle<'prev, 'ctx>(
4846 &'subs self,
4847 ctx: &'ctx mut DemangleContext<'subs, W>,
4848 scope: Option<ArgScopeStack<'prev, 'subs>>,
4849 ) -> fmt::Result {
4850 let ctx = try_begin_demangle!(self, ctx, scope);
4851
4852 ctx.push_inner(self);
4853
4854 match *self {
4855 VectorType::DimensionNumber(_, ref ty) | VectorType::DimensionExpression(_, ref ty) => {
4856 ty.demangle(ctx, scope)?;
4857 }
4858 }
4859
4860 if ctx.pop_inner_if(self) {
4861 self.demangle_as_inner(ctx, scope)?;
4862 }
4863
4864 Ok(())
4865 }
4866}
4867
4868impl<'subs, W> DemangleAsInner<'subs, W> for VectorType
4869where
4870 W: 'subs + DemangleWrite,
4871{
4872 fn demangle_as_inner<'prev, 'ctx>(
4873 &'subs self,
4874 ctx: &'ctx mut DemangleContext<'subs, W>,
4875 scope: Option<ArgScopeStack<'prev, 'subs>>,
4876 ) -> fmt::Result {
4877 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4878
4879 match *self {
4880 VectorType::DimensionNumber(n, _) => {
4881 write!(ctx, " __vector({})", n)?;
4882 }
4883 VectorType::DimensionExpression(ref expr, _) => {
4884 write!(ctx, " __vector(")?;
4885 expr.demangle(ctx, scope)?;
4886 write!(ctx, ")")?;
4887 }
4888 }
4889
4890 Ok(())
4891 }
4892}
4893
4894#[derive(Clone, Debug, PartialEq, Eq)]
4900pub struct PointerToMemberType(TypeHandle, TypeHandle);
4901
4902impl Parse for PointerToMemberType {
4903 fn parse<'a, 'b>(
4904 ctx: &'a ParseContext,
4905 subs: &'a mut SubstitutionTable,
4906 input: IndexStr<'b>,
4907 ) -> Result<(PointerToMemberType, IndexStr<'b>)> {
4908 try_begin_parse!("PointerToMemberType", ctx, input);
4909
4910 let tail = consume(b"M", input)?;
4911 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
4912 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
4913 Ok((PointerToMemberType(ty1, ty2), tail))
4914 }
4915}
4916
4917impl<'subs, W> Demangle<'subs, W> for PointerToMemberType
4918where
4919 W: 'subs + DemangleWrite,
4920{
4921 fn demangle<'prev, 'ctx>(
4922 &'subs self,
4923 ctx: &'ctx mut DemangleContext<'subs, W>,
4924 scope: Option<ArgScopeStack<'prev, 'subs>>,
4925 ) -> fmt::Result {
4926 let ctx = try_begin_demangle!(self, ctx, scope);
4927
4928 ctx.push_inner(self);
4929 self.1.demangle(ctx, scope)?;
4930 if ctx.pop_inner_if(self) {
4931 self.demangle_as_inner(ctx, scope)?;
4932 }
4933 Ok(())
4934 }
4935}
4936
4937impl<'subs, W> DemangleAsInner<'subs, W> for PointerToMemberType
4938where
4939 W: 'subs + DemangleWrite,
4940{
4941 fn demangle_as_inner<'prev, 'ctx>(
4942 &'subs self,
4943 ctx: &'ctx mut DemangleContext<'subs, W>,
4944 scope: Option<ArgScopeStack<'prev, 'subs>>,
4945 ) -> fmt::Result {
4946 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4947
4948 if ctx.last_char_written != Some('(') {
4949 ctx.ensure_space()?;
4950 }
4951
4952 self.0.demangle(ctx, scope)?;
4953 write!(ctx, "::*")?;
4954 Ok(())
4955 }
4956
4957 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
4958 Some(self)
4959 }
4960}
4961
4962#[derive(Clone, Debug, PartialEq, Eq)]
4969pub struct TemplateParam(usize);
4970
4971impl Parse for TemplateParam {
4972 fn parse<'a, 'b>(
4973 ctx: &'a ParseContext,
4974 _subs: &'a mut SubstitutionTable,
4975 input: IndexStr<'b>,
4976 ) -> Result<(TemplateParam, IndexStr<'b>)> {
4977 try_begin_parse!("TemplateParam", ctx, input);
4978
4979 let input = consume(b"T", input)?;
4980 let (number, input) = match parse_number(10, false, input) {
4981 Ok((number, input)) => ((number + 1) as _, input),
4982 Err(_) => (0, input),
4983 };
4984 let input = consume(b"_", input)?;
4985 Ok((TemplateParam(number), input))
4986 }
4987}
4988
4989impl<'subs, W> Demangle<'subs, W> for TemplateParam
4990where
4991 W: 'subs + DemangleWrite,
4992{
4993 fn demangle<'prev, 'ctx>(
4994 &'subs self,
4995 ctx: &'ctx mut DemangleContext<'subs, W>,
4996 scope: Option<ArgScopeStack<'prev, 'subs>>,
4997 ) -> fmt::Result {
4998 let ctx = try_begin_demangle!(self, ctx, scope);
4999
5000 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
5001 let ret = if ctx.is_lambda_arg {
5002 write!(ctx, "auto:{}", self.0 + 1)
5004 } else {
5005 let arg = self.resolve(scope)?;
5006 arg.demangle(ctx, scope)
5007 };
5008 ctx.pop_demangle_node();
5009 ret
5010 }
5011}
5012
5013impl TemplateParam {
5014 fn resolve<'subs, 'prev>(
5015 &'subs self,
5016 scope: Option<ArgScopeStack<'prev, 'subs>>,
5017 ) -> ::core::result::Result<&'subs TemplateArg, fmt::Error> {
5018 scope
5019 .get_template_arg(self.0)
5020 .map_err(|e| {
5021 log!("Error obtaining template argument: {}", e);
5022 fmt::Error
5023 })
5024 .map(|v| v.0)
5025 }
5026}
5027
5028impl<'a> Hash for &'a TemplateParam {
5029 fn hash<H>(&self, state: &mut H)
5030 where
5031 H: Hasher,
5032 {
5033 let self_ref: &TemplateParam = *self;
5034 let self_ptr = self_ref as *const TemplateParam;
5035 self_ptr.hash(state);
5036 }
5037}
5038
5039#[derive(Clone, Debug, PartialEq, Eq)]
5046pub struct TemplateTemplateParam(TemplateParam);
5047
5048define_handle! {
5049 pub enum TemplateTemplateParamHandle
5051}
5052
5053impl Parse for TemplateTemplateParamHandle {
5054 fn parse<'a, 'b>(
5055 ctx: &'a ParseContext,
5056 subs: &'a mut SubstitutionTable,
5057 input: IndexStr<'b>,
5058 ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)> {
5059 try_begin_parse!("TemplateTemplateParamHandle", ctx, input);
5060
5061 if let Ok((sub, tail)) = Substitution::parse(ctx, subs, input) {
5062 match sub {
5063 Substitution::WellKnown(component) => {
5064 return Ok((TemplateTemplateParamHandle::WellKnown(component), tail));
5065 }
5066 Substitution::BackReference(idx) => {
5067 return Ok((TemplateTemplateParamHandle::BackReference(idx), tail));
5071 }
5072 }
5073 }
5074
5075 let (param, tail) = TemplateParam::parse(ctx, subs, input)?;
5076 let ttp = TemplateTemplateParam(param);
5077 let ttp = Substitutable::TemplateTemplateParam(ttp);
5078 let idx = subs.insert(ttp);
5079 let handle = TemplateTemplateParamHandle::BackReference(idx);
5080 Ok((handle, tail))
5081 }
5082}
5083
5084impl<'subs, W> Demangle<'subs, W> for TemplateTemplateParam
5085where
5086 W: 'subs + DemangleWrite,
5087{
5088 #[inline]
5089 fn demangle<'prev, 'ctx>(
5090 &'subs self,
5091 ctx: &'ctx mut DemangleContext<'subs, W>,
5092 scope: Option<ArgScopeStack<'prev, 'subs>>,
5093 ) -> fmt::Result {
5094 let ctx = try_begin_demangle!(self, ctx, scope);
5095
5096 self.0.demangle(ctx, scope)
5097 }
5098}
5099
5100#[derive(Clone, Debug, PartialEq, Eq)]
5113pub struct FunctionParam(usize, CvQualifiers, Option<usize>);
5114
5115impl Parse for FunctionParam {
5116 fn parse<'a, 'b>(
5117 ctx: &'a ParseContext,
5118 subs: &'a mut SubstitutionTable,
5119 input: IndexStr<'b>,
5120 ) -> Result<(FunctionParam, IndexStr<'b>)> {
5121 try_begin_parse!("FunctionParam", ctx, input);
5122
5123 let tail = consume(b"f", input)?;
5124 if tail.is_empty() {
5125 return Err(error::Error::UnexpectedEnd);
5126 }
5127
5128 let (scope, tail) = if let Ok(tail) = consume(b"L", tail) {
5129 parse_number(10, false, tail)?
5130 } else {
5131 (0, tail)
5132 };
5133
5134 let tail = consume(b"p", tail)?;
5135
5136 let (qualifiers, tail) = CvQualifiers::parse(ctx, subs, tail)?;
5137
5138 let (param, tail) = if tail.peek() == Some(b'T') {
5139 (None, consume(b"T", tail)?)
5140 } else if let Ok((num, tail)) = parse_number(10, false, tail) {
5141 (Some(num as usize + 1), consume(b"_", tail)?)
5142 } else {
5143 (Some(0), consume(b"_", tail)?)
5144 };
5145
5146 Ok((FunctionParam(scope as _, qualifiers, param), tail))
5147 }
5148}
5149
5150impl<'subs, W> Demangle<'subs, W> for FunctionParam
5151where
5152 W: 'subs + DemangleWrite,
5153{
5154 fn demangle<'prev, 'ctx>(
5155 &'subs self,
5156 ctx: &'ctx mut DemangleContext<'subs, W>,
5157 scope: Option<ArgScopeStack<'prev, 'subs>>,
5158 ) -> fmt::Result {
5159 let ctx = try_begin_demangle!(self, ctx, scope);
5160
5161 match self.2 {
5162 None => write!(ctx, "this"),
5163 Some(i) => write!(ctx, "{{parm#{}}}", i + 1),
5164 }
5165 }
5166}
5167
5168#[derive(Clone, Debug, PartialEq, Eq)]
5174pub struct TemplateArgs(Vec<TemplateArg>);
5175
5176impl Parse for TemplateArgs {
5177 fn parse<'a, 'b>(
5178 ctx: &'a ParseContext,
5179 subs: &'a mut SubstitutionTable,
5180 input: IndexStr<'b>,
5181 ) -> Result<(TemplateArgs, IndexStr<'b>)> {
5182 try_begin_parse!("TemplateArgs", ctx, input);
5183
5184 let tail = consume(b"I", input)?;
5185
5186 let (args, tail) = one_or_more::<TemplateArg>(ctx, subs, tail)?;
5187 let tail = consume(b"E", tail)?;
5188 Ok((TemplateArgs(args), tail))
5189 }
5190}
5191
5192impl<'subs, W> Demangle<'subs, W> for TemplateArgs
5193where
5194 W: 'subs + DemangleWrite,
5195{
5196 fn demangle<'prev, 'ctx>(
5197 &'subs self,
5198 ctx: &'ctx mut DemangleContext<'subs, W>,
5199 mut scope: Option<ArgScopeStack<'prev, 'subs>>,
5200 ) -> fmt::Result {
5201 let ctx = try_begin_demangle!(self, ctx, scope);
5202 inner_barrier!(ctx);
5203
5204 if ctx.last_char_written == Some('<') {
5205 write!(ctx, " ")?;
5206 }
5207 write!(ctx, "<")?;
5208 ctx.push_demangle_node(DemangleNodeType::TemplateArgs);
5209 let mut need_comma = false;
5210 for arg_index in 0..self.0.len() {
5211 if need_comma {
5212 write!(ctx, ", ")?;
5213 }
5214 if let Some(ref mut scope) = scope {
5215 scope.in_arg = Some((arg_index, self));
5216 }
5217 self.0[arg_index].demangle(ctx, scope)?;
5218 need_comma = true;
5219 }
5220
5221 if ctx.last_char_written == Some('>') {
5224 write!(ctx, " ")?;
5225 }
5226 ctx.pop_demangle_node();
5227 write!(ctx, ">")?;
5228 Ok(())
5229 }
5230}
5231
5232impl<'subs> ArgScope<'subs, 'subs> for TemplateArgs {
5233 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
5234 Err(error::Error::BadLeafNameReference)
5235 }
5236
5237 fn get_template_arg(
5238 &'subs self,
5239 idx: usize,
5240 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
5241 self.0
5242 .get(idx)
5243 .ok_or(error::Error::BadTemplateArgReference)
5244 .map(|v| (v, self))
5245 }
5246
5247 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
5248 Err(error::Error::BadFunctionArgReference)
5249 }
5250}
5251
5252#[derive(Clone, Debug, PartialEq, Eq)]
5261pub enum TemplateArg {
5262 Type(TypeHandle),
5264
5265 Expression(Expression),
5267
5268 SimpleExpression(ExprPrimary),
5270
5271 ArgPack(Vec<TemplateArg>),
5273}
5274
5275impl Parse for TemplateArg {
5276 fn parse<'a, 'b>(
5277 ctx: &'a ParseContext,
5278 subs: &'a mut SubstitutionTable,
5279 input: IndexStr<'b>,
5280 ) -> Result<(TemplateArg, IndexStr<'b>)> {
5281 try_begin_parse!("TemplateArg", ctx, input);
5282
5283 if let Ok(tail) = consume(b"X", input) {
5284 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5285 let tail = consume(b"E", tail)?;
5286 return Ok((TemplateArg::Expression(expr), tail));
5287 }
5288
5289 if let Ok((expr, tail)) = ExprPrimary::parse(ctx, subs, input) {
5290 return Ok((TemplateArg::SimpleExpression(expr), tail));
5291 }
5292
5293 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, input) {
5294 return Ok((TemplateArg::Type(ty), tail));
5295 }
5296
5297 let tail = if input.peek() == Some(b'J') {
5298 consume(b"J", input)?
5299 } else {
5300 consume(b"I", input)?
5301 };
5302
5303 let (args, tail) = if tail.peek() == Some(b'E') {
5304 (vec![], tail)
5305 } else {
5306 zero_or_more::<TemplateArg>(ctx, subs, tail)?
5307 };
5308 let tail = consume(b"E", tail)?;
5309 Ok((TemplateArg::ArgPack(args), tail))
5310 }
5311}
5312
5313impl<'subs, W> Demangle<'subs, W> for TemplateArg
5314where
5315 W: 'subs + DemangleWrite,
5316{
5317 fn demangle<'prev, 'ctx>(
5318 &'subs self,
5319 ctx: &'ctx mut DemangleContext<'subs, W>,
5320 scope: Option<ArgScopeStack<'prev, 'subs>>,
5321 ) -> fmt::Result {
5322 let ctx = try_begin_demangle!(self, ctx, scope);
5323
5324 match *self {
5325 TemplateArg::Type(ref ty) => ty.demangle(ctx, scope),
5326 TemplateArg::Expression(ref expr) => expr.demangle(ctx, scope),
5327 TemplateArg::SimpleExpression(ref expr) => expr.demangle(ctx, scope),
5328 TemplateArg::ArgPack(ref args) => {
5329 ctx.is_template_argument_pack = true;
5330 let mut need_comma = false;
5331 for arg in &args[..] {
5332 if need_comma {
5333 write!(ctx, ", ")?;
5334 }
5335 arg.demangle(ctx, scope)?;
5336 need_comma = true;
5337 }
5338 Ok(())
5339 }
5340 }
5341 }
5342}
5343
5344#[derive(Clone, Debug, PartialEq, Eq)]
5350pub struct MemberName(Name);
5351
5352impl Parse for MemberName {
5353 fn parse<'a, 'b>(
5354 ctx: &'a ParseContext,
5355 subs: &'a mut SubstitutionTable,
5356 input: IndexStr<'b>,
5357 ) -> Result<(MemberName, IndexStr<'b>)> {
5358 try_begin_parse!("MemberName", ctx, input);
5359
5360 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
5361 let name = UnscopedName::Unqualified(name);
5362 if let Ok((template, tail)) = TemplateArgs::parse(ctx, subs, tail) {
5363 let name = UnscopedTemplateName(name);
5364 let idx = subs.insert_non_substitution(Substitutable::UnscopedTemplateName(name));
5366 let handle = UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(idx));
5367 Ok((MemberName(Name::UnscopedTemplate(handle, template)), tail))
5368 } else {
5369 Ok((MemberName(Name::Unscoped(name)), tail))
5370 }
5371 }
5372}
5373
5374impl<'subs, W> Demangle<'subs, W> for MemberName
5375where
5376 W: 'subs + DemangleWrite,
5377{
5378 fn demangle<'prev, 'ctx>(
5379 &'subs self,
5380 ctx: &'ctx mut DemangleContext<'subs, W>,
5381 scope: Option<ArgScopeStack<'prev, 'subs>>,
5382 ) -> fmt::Result {
5383 let ctx = try_begin_demangle!(self, ctx, scope);
5384
5385 let needs_parens = self.0.get_template_args(ctx.subs).is_some();
5386 if needs_parens {
5387 write!(ctx, "(")?;
5388 }
5389
5390 self.0.demangle(ctx, scope)?;
5391
5392 if needs_parens {
5393 write!(ctx, ")")?;
5394 }
5395
5396 Ok(())
5397 }
5398}
5399
5400#[derive(Clone, Debug, PartialEq, Eq)]
5448pub enum Expression {
5449 Unary(OperatorName, Box<Expression>),
5451
5452 Binary(OperatorName, Box<Expression>, Box<Expression>),
5454
5455 Ternary(
5457 OperatorName,
5458 Box<Expression>,
5459 Box<Expression>,
5460 Box<Expression>,
5461 ),
5462
5463 PrefixInc(Box<Expression>),
5465
5466 PrefixDec(Box<Expression>),
5468
5469 Call(Box<Expression>, Vec<Expression>),
5471
5472 ConversionOne(TypeHandle, Box<Expression>),
5474
5475 ConversionMany(TypeHandle, Vec<Expression>),
5477
5478 ConversionBraced(TypeHandle, Vec<Expression>),
5480
5481 BracedInitList(Box<Expression>),
5483
5484 New(Vec<Expression>, TypeHandle, Option<Initializer>),
5486
5487 GlobalNew(Vec<Expression>, TypeHandle, Option<Initializer>),
5489
5490 NewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5492
5493 GlobalNewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5495
5496 Delete(Box<Expression>),
5498
5499 GlobalDelete(Box<Expression>),
5501
5502 DeleteArray(Box<Expression>),
5504
5505 GlobalDeleteArray(Box<Expression>),
5507
5508 DynamicCast(TypeHandle, Box<Expression>),
5510
5511 StaticCast(TypeHandle, Box<Expression>),
5513
5514 ConstCast(TypeHandle, Box<Expression>),
5516
5517 ReinterpretCast(TypeHandle, Box<Expression>),
5519
5520 TypeidType(TypeHandle),
5522
5523 TypeidExpr(Box<Expression>),
5525
5526 SizeofType(TypeHandle),
5528
5529 SizeofExpr(Box<Expression>),
5531
5532 AlignofType(TypeHandle),
5534
5535 AlignofExpr(Box<Expression>),
5537
5538 Noexcept(Box<Expression>),
5540
5541 Subobject(SubobjectExpr),
5543
5544 TemplateParam(TemplateParam),
5546
5547 FunctionParam(FunctionParam),
5549
5550 Member(Box<Expression>, MemberName),
5552
5553 DerefMember(Box<Expression>, MemberName),
5555
5556 PointerToMember(Box<Expression>, Box<Expression>),
5558
5559 SizeofTemplatePack(TemplateParam),
5561
5562 SizeofFunctionPack(FunctionParam),
5564
5565 SizeofCapturedTemplatePack(Vec<TemplateArg>),
5568
5569 PackExpansion(Box<Expression>),
5571
5572 Throw(Box<Expression>),
5574
5575 Rethrow,
5577
5578 UnresolvedName(UnresolvedName),
5581
5582 Primary(ExprPrimary),
5584}
5585
5586impl Parse for Expression {
5587 fn parse<'a, 'b>(
5588 ctx: &'a ParseContext,
5589 subs: &'a mut SubstitutionTable,
5590 input: IndexStr<'b>,
5591 ) -> Result<(Expression, IndexStr<'b>)> {
5592 try_begin_parse!("Expression", ctx, input);
5593
5594 if let Ok(tail) = consume(b"pp_", input) {
5595 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5596 let expr = Expression::PrefixInc(Box::new(expr));
5597 return Ok((expr, tail));
5598 }
5599
5600 if let Ok(tail) = consume(b"mm_", input) {
5601 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5602 let expr = Expression::PrefixDec(Box::new(expr));
5603 return Ok((expr, tail));
5604 }
5605
5606 if let Some((head, tail)) = input.try_split_at(2) {
5607 match head.as_ref() {
5608 b"cl" => {
5609 let (func, tail) = Expression::parse(ctx, subs, tail)?;
5610 let (args, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5611 let tail = consume(b"E", tail)?;
5612 let expr = Expression::Call(Box::new(func), args);
5613 return Ok((expr, tail));
5614 }
5615 b"cv" => {
5616 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5617 if let Ok(tail) = consume(b"_", tail) {
5618 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5619 let tail = consume(b"E", tail)?;
5620 let expr = Expression::ConversionMany(ty, exprs);
5621 return Ok((expr, tail));
5622 } else {
5623 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5624 let expr = Expression::ConversionOne(ty, Box::new(expr));
5625 return Ok((expr, tail));
5626 }
5627 }
5628 b"tl" => {
5629 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5630 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5631 let expr = Expression::ConversionBraced(ty, exprs);
5632 let tail = consume(b"E", tail)?;
5633 return Ok((expr, tail));
5634 }
5635 b"il" => {
5636 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5637 let tail = consume(b"E", tail)?;
5638 let expr = Expression::BracedInitList(Box::new(expr));
5639 return Ok((expr, tail));
5640 }
5641 b"dc" => {
5642 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5643 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5644 let expr = Expression::DynamicCast(ty, Box::new(expr));
5645 return Ok((expr, tail));
5646 }
5647 b"sc" => {
5648 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5649 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5650 let expr = Expression::StaticCast(ty, Box::new(expr));
5651 return Ok((expr, tail));
5652 }
5653 b"cc" => {
5654 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5655 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5656 let expr = Expression::ConstCast(ty, Box::new(expr));
5657 return Ok((expr, tail));
5658 }
5659 b"rc" => {
5660 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5661 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5662 let expr = Expression::ReinterpretCast(ty, Box::new(expr));
5663 return Ok((expr, tail));
5664 }
5665 b"ti" => {
5666 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5667 let expr = Expression::TypeidType(ty);
5668 return Ok((expr, tail));
5669 }
5670 b"te" => {
5671 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5672 let expr = Expression::TypeidExpr(Box::new(expr));
5673 return Ok((expr, tail));
5674 }
5675 b"st" => {
5676 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5677 let expr = Expression::SizeofType(ty);
5678 return Ok((expr, tail));
5679 }
5680 b"sz" => {
5681 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5682 let expr = Expression::SizeofExpr(Box::new(expr));
5683 return Ok((expr, tail));
5684 }
5685 b"at" => {
5686 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5687 let expr = Expression::AlignofType(ty);
5688 return Ok((expr, tail));
5689 }
5690 b"az" => {
5691 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5692 let expr = Expression::AlignofExpr(Box::new(expr));
5693 return Ok((expr, tail));
5694 }
5695 b"nx" => {
5696 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5697 let expr = Expression::Noexcept(Box::new(expr));
5698 return Ok((expr, tail));
5699 }
5700 b"so" => {
5701 let (expr, tail) = SubobjectExpr::parse(ctx, subs, tail)?;
5702 let expr = Expression::Subobject(expr);
5703 return Ok((expr, tail));
5704 }
5705 b"dt" => {
5706 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5707 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5708 let expr = Expression::Member(Box::new(expr), name);
5709 return Ok((expr, tail));
5710 }
5711 b"pt" => {
5712 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5713 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
5714 let expr = Expression::DerefMember(Box::new(expr), name);
5715 return Ok((expr, tail));
5716 }
5717 b"ds" => {
5718 let (first, tail) = Expression::parse(ctx, subs, tail)?;
5719 let (second, tail) = Expression::parse(ctx, subs, tail)?;
5720 let expr = Expression::PointerToMember(Box::new(first), Box::new(second));
5721 return Ok((expr, tail));
5722 }
5723 b"sZ" => {
5724 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, tail) {
5725 let expr = Expression::SizeofTemplatePack(param);
5726 return Ok((expr, tail));
5727 }
5728
5729 let (param, tail) = FunctionParam::parse(ctx, subs, tail)?;
5730 let expr = Expression::SizeofFunctionPack(param);
5731 return Ok((expr, tail));
5732 }
5733 b"sP" => {
5734 let (args, tail) = zero_or_more::<TemplateArg>(ctx, subs, tail)?;
5735 let expr = Expression::SizeofCapturedTemplatePack(args);
5736 let tail = consume(b"E", tail)?;
5737 return Ok((expr, tail));
5738 }
5739 b"sp" => {
5740 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5741 let expr = Expression::PackExpansion(Box::new(expr));
5742 return Ok((expr, tail));
5743 }
5744 b"tw" => {
5745 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5746 let expr = Expression::Throw(Box::new(expr));
5747 return Ok((expr, tail));
5748 }
5749 b"tr" => {
5750 let expr = Expression::Rethrow;
5751 return Ok((expr, tail));
5752 }
5753 b"gs" => {
5754 if let Ok((expr, tail)) = can_be_global(true, ctx, subs, tail) {
5755 return Ok((expr, tail));
5756 }
5757 }
5758 _ => {}
5759 }
5760 }
5761
5762 if let Ok((expr, tail)) = can_be_global(false, ctx, subs, input) {
5763 return Ok((expr, tail));
5764 }
5765
5766 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
5767 let expr = Expression::TemplateParam(param);
5768 return Ok((expr, tail));
5769 }
5770
5771 if let Ok((param, tail)) = FunctionParam::parse(ctx, subs, input) {
5772 let expr = Expression::FunctionParam(param);
5773 return Ok((expr, tail));
5774 }
5775
5776 if let Ok((name, tail)) = UnresolvedName::parse(ctx, subs, input) {
5777 let expr = Expression::UnresolvedName(name);
5778 return Ok((expr, tail));
5779 }
5780
5781 if let Ok((prim, tail)) = ExprPrimary::parse(ctx, subs, input) {
5782 let expr = Expression::Primary(prim);
5783 return Ok((expr, tail));
5784 }
5785
5786 let (expr, tail) = OperatorName::parse_from_expr(ctx, subs, input)?;
5791 return Ok((expr, tail));
5792
5793 fn can_be_global<'a, 'b>(
5798 is_global: bool,
5799 ctx: &'a ParseContext,
5800 subs: &'a mut SubstitutionTable,
5801 input: IndexStr<'b>,
5802 ) -> Result<(Expression, IndexStr<'b>)> {
5803 match input.try_split_at(2) {
5804 None => Err(error::Error::UnexpectedEnd),
5805 Some((head, tail)) => match head.as_ref() {
5806 b"nw" => {
5807 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5808 let tail = consume(b"_", tail)?;
5809 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5810 if let Ok(tail) = consume(b"E", tail) {
5811 let expr = if is_global {
5812 Expression::GlobalNew(exprs, ty, None)
5813 } else {
5814 Expression::New(exprs, ty, None)
5815 };
5816 Ok((expr, tail))
5817 } else {
5818 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5819 let expr = if is_global {
5820 Expression::GlobalNew(exprs, ty, Some(init))
5821 } else {
5822 Expression::New(exprs, ty, Some(init))
5823 };
5824 Ok((expr, tail))
5825 }
5826 }
5827 b"na" => {
5828 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5829 let tail = consume(b"_", tail)?;
5830 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5831 if let Ok(tail) = consume(b"E", tail) {
5832 let expr = if is_global {
5833 Expression::GlobalNewArray(exprs, ty, None)
5834 } else {
5835 Expression::NewArray(exprs, ty, None)
5836 };
5837 Ok((expr, tail))
5838 } else {
5839 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
5840 let expr = if is_global {
5841 Expression::GlobalNewArray(exprs, ty, Some(init))
5842 } else {
5843 Expression::NewArray(exprs, ty, Some(init))
5844 };
5845 Ok((expr, tail))
5846 }
5847 }
5848 b"dl" => {
5849 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5850 let expr = if is_global {
5851 Expression::GlobalDelete(Box::new(expr))
5852 } else {
5853 Expression::Delete(Box::new(expr))
5854 };
5855 Ok((expr, tail))
5856 }
5857 b"da" => {
5858 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5859 let expr = if is_global {
5860 Expression::GlobalDeleteArray(Box::new(expr))
5861 } else {
5862 Expression::DeleteArray(Box::new(expr))
5863 };
5864 Ok((expr, tail))
5865 }
5866 _ => Err(error::Error::UnexpectedText),
5867 },
5868 }
5869 }
5870 }
5871}
5872
5873impl<'subs, W> Demangle<'subs, W> for Expression
5874where
5875 W: 'subs + DemangleWrite,
5876{
5877 fn demangle<'prev, 'ctx>(
5878 &'subs self,
5879 ctx: &'ctx mut DemangleContext<'subs, W>,
5880 scope: Option<ArgScopeStack<'prev, 'subs>>,
5881 ) -> fmt::Result {
5882 let ctx = try_begin_demangle!(self, ctx, scope);
5883
5884 match *self {
5885 Expression::Unary(OperatorName::Simple(ref op), ref expr)
5886 if *op == SimpleOperatorName::PostInc || *op == SimpleOperatorName::PostDec =>
5887 {
5888 expr.demangle_as_subexpr(ctx, scope)?;
5889 op.demangle(ctx, scope)
5890 }
5891 Expression::Unary(ref op, ref expr) => {
5892 op.demangle(ctx, scope)?;
5893 expr.demangle_as_subexpr(ctx, scope)
5894 }
5895 Expression::Binary(
5898 OperatorName::Simple(SimpleOperatorName::Greater),
5899 ref lhs,
5900 ref rhs,
5901 ) => {
5902 write!(ctx, "((")?;
5903 lhs.demangle(ctx, scope)?;
5904 write!(ctx, ")>(")?;
5905 rhs.demangle(ctx, scope)?;
5906 write!(ctx, "))")
5907 }
5908 Expression::Binary(ref op, ref lhs, ref rhs) => {
5909 lhs.demangle_as_subexpr(ctx, scope)?;
5910 op.demangle(ctx, scope)?;
5911 rhs.demangle_as_subexpr(ctx, scope)
5912 }
5913 Expression::Ternary(
5914 OperatorName::Simple(SimpleOperatorName::Question),
5915 ref condition,
5916 ref consequent,
5917 ref alternative,
5918 ) => {
5919 condition.demangle_as_subexpr(ctx, scope)?;
5920 write!(ctx, "?")?;
5921 consequent.demangle_as_subexpr(ctx, scope)?;
5922 write!(ctx, " : ")?;
5923 alternative.demangle_as_subexpr(ctx, scope)
5924 }
5925 Expression::Ternary(ref op, ref e1, ref e2, ref e3) => {
5926 op.demangle(ctx, scope)?;
5931 write!(ctx, "(")?;
5932 e1.demangle(ctx, scope)?;
5933 write!(ctx, ", ")?;
5934 e2.demangle(ctx, scope)?;
5935 write!(ctx, ", ")?;
5936 e3.demangle(ctx, scope)?;
5937 write!(ctx, ")")?;
5938 Ok(())
5939 }
5940 Expression::PrefixInc(ref expr) => {
5941 write!(ctx, "++")?;
5942 expr.demangle(ctx, scope)
5943 }
5944 Expression::PrefixDec(ref expr) => {
5945 write!(ctx, "--")?;
5946 expr.demangle(ctx, scope)
5947 }
5948 Expression::Call(ref functor_expr, ref args) => {
5949 functor_expr.demangle_as_subexpr(ctx, scope)?;
5950 write!(ctx, "(")?;
5951 let mut need_comma = false;
5952 for arg in args {
5953 if need_comma {
5954 write!(ctx, ", ")?;
5955 }
5956 arg.demangle(ctx, scope)?;
5957 need_comma = true;
5958 }
5959 write!(ctx, ")")?;
5960 Ok(())
5961 }
5962 Expression::ConversionOne(ref ty, ref expr) => {
5963 write!(ctx, "(")?;
5964 ty.demangle(ctx, scope)?;
5965 write!(ctx, ")(")?;
5966 expr.demangle(ctx, scope)?;
5967 write!(ctx, ")")?;
5968 Ok(())
5969 }
5970 Expression::ConversionMany(ref ty, ref exprs) => {
5971 ty.demangle(ctx, scope)?;
5972 write!(ctx, "(")?;
5973 let mut need_comma = false;
5974 for expr in exprs {
5975 if need_comma {
5976 write!(ctx, ", ")?;
5977 }
5978 expr.demangle(ctx, scope)?;
5979 need_comma = true;
5980 }
5981 write!(ctx, ")")?;
5982 Ok(())
5983 }
5984 Expression::ConversionBraced(ref ty, ref exprs) => {
5985 ty.demangle(ctx, scope)?;
5986 write!(ctx, "{{")?;
5987 let mut need_comma = false;
5988 for expr in exprs {
5989 if need_comma {
5990 write!(ctx, ", ")?;
5991 }
5992 expr.demangle(ctx, scope)?;
5993 need_comma = true;
5994 }
5995 write!(ctx, "}}")?;
5996 Ok(())
5997 }
5998 Expression::BracedInitList(ref expr) => {
5999 write!(ctx, "{{")?;
6000 expr.demangle(ctx, scope)?;
6001 write!(ctx, "}}")?;
6002 Ok(())
6003 }
6004 Expression::New(ref exprs, ref ty, ref init) => {
6006 write!(ctx, "new (")?;
6007 let mut need_comma = false;
6008 for expr in exprs {
6009 if need_comma {
6010 write!(ctx, ", ")?;
6011 }
6012 expr.demangle(ctx, scope)?;
6013 need_comma = true;
6014 }
6015 write!(ctx, ") ")?;
6016 ty.demangle(ctx, scope)?;
6017 if let Some(ref init) = *init {
6018 init.demangle(ctx, scope)?;
6019 }
6020 Ok(())
6021 }
6022 Expression::GlobalNew(ref exprs, ref ty, ref init) => {
6023 write!(ctx, "::new (")?;
6024 let mut need_comma = false;
6025 for expr in exprs {
6026 if need_comma {
6027 write!(ctx, ", ")?;
6028 }
6029 expr.demangle(ctx, scope)?;
6030 need_comma = true;
6031 }
6032 write!(ctx, ") ")?;
6033 ty.demangle(ctx, scope)?;
6034 if let Some(ref init) = *init {
6035 init.demangle(ctx, scope)?;
6036 }
6037 Ok(())
6038 }
6039 Expression::NewArray(ref exprs, ref ty, ref init) => {
6040 write!(ctx, "new[] (")?;
6041 let mut need_comma = false;
6042 for expr in exprs {
6043 if need_comma {
6044 write!(ctx, ", ")?;
6045 }
6046 expr.demangle(ctx, scope)?;
6047 need_comma = true;
6048 }
6049 write!(ctx, ") ")?;
6050 ty.demangle(ctx, scope)?;
6051 if let Some(ref init) = *init {
6052 init.demangle(ctx, scope)?;
6053 }
6054 Ok(())
6055 }
6056 Expression::GlobalNewArray(ref exprs, ref ty, ref init) => {
6057 write!(ctx, "::new[] (")?;
6058 let mut need_comma = false;
6059 for expr in exprs {
6060 if need_comma {
6061 write!(ctx, ", ")?;
6062 }
6063 expr.demangle(ctx, scope)?;
6064 need_comma = true;
6065 }
6066 write!(ctx, ") ")?;
6067 ty.demangle(ctx, scope)?;
6068 if let Some(ref init) = *init {
6069 init.demangle(ctx, scope)?;
6070 }
6071 Ok(())
6072 }
6073 Expression::Delete(ref expr) => {
6074 write!(ctx, "delete ")?;
6075 expr.demangle(ctx, scope)
6076 }
6077 Expression::GlobalDelete(ref expr) => {
6078 write!(ctx, "::delete ")?;
6079 expr.demangle(ctx, scope)
6080 }
6081 Expression::DeleteArray(ref expr) => {
6082 write!(ctx, "delete[] ")?;
6083 expr.demangle(ctx, scope)
6084 }
6085 Expression::GlobalDeleteArray(ref expr) => {
6086 write!(ctx, "::delete[] ")?;
6087 expr.demangle(ctx, scope)
6088 }
6089 Expression::DynamicCast(ref ty, ref expr) => {
6091 write!(ctx, "dynamic_cast<")?;
6092 ty.demangle(ctx, scope)?;
6093 write!(ctx, ">(")?;
6094 expr.demangle(ctx, scope)?;
6095 write!(ctx, ")")?;
6096 Ok(())
6097 }
6098 Expression::StaticCast(ref ty, ref expr) => {
6099 write!(ctx, "static_cast<")?;
6100 ty.demangle(ctx, scope)?;
6101 write!(ctx, ">(")?;
6102 expr.demangle(ctx, scope)?;
6103 write!(ctx, ")")?;
6104 Ok(())
6105 }
6106 Expression::ConstCast(ref ty, ref expr) => {
6107 write!(ctx, "const_cast<")?;
6108 ty.demangle(ctx, scope)?;
6109 write!(ctx, ">(")?;
6110 expr.demangle(ctx, scope)?;
6111 write!(ctx, ")")?;
6112 Ok(())
6113 }
6114 Expression::ReinterpretCast(ref ty, ref expr) => {
6115 write!(ctx, "reinterpret_cast<")?;
6116 ty.demangle(ctx, scope)?;
6117 write!(ctx, ">(")?;
6118 expr.demangle(ctx, scope)?;
6119 write!(ctx, ")")?;
6120 Ok(())
6121 }
6122 Expression::TypeidType(ref ty) => {
6123 write!(ctx, "typeid (")?;
6124 ty.demangle(ctx, scope)?;
6125 write!(ctx, ")")?;
6126 Ok(())
6127 }
6128 Expression::TypeidExpr(ref expr) => {
6129 write!(ctx, "typeid (")?;
6130 expr.demangle(ctx, scope)?;
6131 write!(ctx, ")")?;
6132 Ok(())
6133 }
6134 Expression::SizeofType(ref ty) => {
6135 write!(ctx, "sizeof (")?;
6136 ty.demangle(ctx, scope)?;
6137 write!(ctx, ")")?;
6138 Ok(())
6139 }
6140 Expression::SizeofExpr(ref expr) => {
6141 write!(ctx, "sizeof (")?;
6142 expr.demangle(ctx, scope)?;
6143 write!(ctx, ")")?;
6144 Ok(())
6145 }
6146 Expression::AlignofType(ref ty) => {
6147 write!(ctx, "alignof (")?;
6148 ty.demangle(ctx, scope)?;
6149 write!(ctx, ")")?;
6150 Ok(())
6151 }
6152 Expression::AlignofExpr(ref expr) => {
6153 write!(ctx, "alignof (")?;
6154 expr.demangle(ctx, scope)?;
6155 write!(ctx, ")")?;
6156 Ok(())
6157 }
6158 Expression::Noexcept(ref expr) => {
6159 write!(ctx, "noexcept (")?;
6160 expr.demangle(ctx, scope)?;
6161 write!(ctx, ")")?;
6162 Ok(())
6163 }
6164 Expression::Subobject(ref expr) => expr.demangle(ctx, scope),
6165 Expression::TemplateParam(ref param) => param.demangle(ctx, scope),
6166 Expression::FunctionParam(ref param) => param.demangle(ctx, scope),
6167 Expression::Member(ref expr, ref name) => {
6168 expr.demangle_as_subexpr(ctx, scope)?;
6169 write!(ctx, ".")?;
6170 name.demangle(ctx, scope)
6171 }
6172 Expression::DerefMember(ref expr, ref name) => {
6173 expr.demangle(ctx, scope)?;
6174 write!(ctx, "->")?;
6175 name.demangle(ctx, scope)
6176 }
6177 Expression::PointerToMember(ref e1, ref e2) => {
6178 e1.demangle(ctx, scope)?;
6179 write!(ctx, ".*")?;
6180 e2.demangle(ctx, scope)
6181 }
6182 Expression::SizeofTemplatePack(ref param) => {
6183 write!(ctx, "sizeof...(")?;
6184 param.demangle(ctx, scope)?;
6185 write!(ctx, ")")?;
6186 Ok(())
6187 }
6188 Expression::SizeofFunctionPack(ref param) => {
6189 write!(ctx, "sizeof...(")?;
6190 param.demangle(ctx, scope)?;
6191 write!(ctx, ")")?;
6192 Ok(())
6193 }
6194 Expression::SizeofCapturedTemplatePack(ref args) => {
6195 write!(ctx, "sizeof...(")?;
6196 let mut need_comma = false;
6197 for arg in args {
6198 if need_comma {
6199 write!(ctx, ", ")?;
6200 }
6201 arg.demangle(ctx, scope)?;
6202 need_comma = true;
6203 }
6204 write!(ctx, ")")?;
6205 Ok(())
6206 }
6207 Expression::PackExpansion(ref pack) => {
6208 pack.demangle_as_subexpr(ctx, scope)?;
6209 write!(ctx, "...")?;
6210 Ok(())
6211 }
6212 Expression::Throw(ref expr) => {
6213 write!(ctx, "throw ")?;
6214 expr.demangle(ctx, scope)
6215 }
6216 Expression::Rethrow => {
6217 write!(ctx, "throw")?;
6218 Ok(())
6219 }
6220 Expression::UnresolvedName(ref name) => name.demangle(ctx, scope),
6221 Expression::Primary(ref expr) => expr.demangle(ctx, scope),
6222 }
6223 }
6224}
6225
6226impl Expression {
6227 fn demangle_as_subexpr<'subs, 'prev, 'ctx, W>(
6228 &'subs self,
6229 ctx: &'ctx mut DemangleContext<'subs, W>,
6230 scope: Option<ArgScopeStack<'prev, 'subs>>,
6231 ) -> fmt::Result
6232 where
6233 W: 'subs + DemangleWrite,
6234 {
6235 let needs_parens = match *self {
6236 Expression::FunctionParam(_) | Expression::Primary(ExprPrimary::External(_)) => false,
6237 _ => true,
6238 };
6239
6240 if needs_parens {
6241 write!(ctx, "(")?;
6242 }
6243
6244 self.demangle(ctx, scope)?;
6245
6246 if needs_parens {
6247 write!(ctx, ")")?;
6248 }
6249
6250 Ok(())
6251 }
6252}
6253
6254#[derive(Clone, Debug, PartialEq, Eq)]
6267pub enum UnresolvedName {
6268 Name(BaseUnresolvedName),
6270
6271 Global(BaseUnresolvedName),
6273
6274 Nested1(
6276 UnresolvedTypeHandle,
6277 Vec<UnresolvedQualifierLevel>,
6278 BaseUnresolvedName,
6279 ),
6280
6281 Nested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6283
6284 GlobalNested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6286}
6287
6288impl Parse for UnresolvedName {
6289 fn parse<'a, 'b>(
6290 ctx: &'a ParseContext,
6291 subs: &'a mut SubstitutionTable,
6292 input: IndexStr<'b>,
6293 ) -> Result<(UnresolvedName, IndexStr<'b>)> {
6294 try_begin_parse!("UnresolvedName", ctx, input);
6295
6296 if let Ok(tail) = consume(b"gs", input) {
6297 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, tail) {
6298 return Ok((UnresolvedName::Global(name), tail));
6299 }
6300
6301 let tail = consume(b"sr", tail)?;
6302 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6303 let tail = consume(b"E", tail)?;
6304 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6305 return Ok((UnresolvedName::GlobalNested2(levels, name), tail));
6306 }
6307
6308 if let Ok((name, tail)) = BaseUnresolvedName::parse(ctx, subs, input) {
6309 return Ok((UnresolvedName::Name(name), tail));
6310 }
6311
6312 let tail = consume(b"sr", input)?;
6313
6314 if tail.peek() == Some(b'N') {
6315 let tail = consume(b"N", tail).unwrap();
6316 let (ty, tail) = UnresolvedTypeHandle::parse(ctx, subs, tail)?;
6317 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6318 let tail = consume(b"E", tail)?;
6319 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6320 return Ok((UnresolvedName::Nested1(ty, levels, name), tail));
6321 }
6322
6323 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, tail) {
6324 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6325 return Ok((UnresolvedName::Nested1(ty, vec![], name), tail));
6326 }
6327
6328 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6329 let tail = consume(b"E", tail)?;
6330 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6331 Ok((UnresolvedName::Nested2(levels, name), tail))
6332 }
6333}
6334
6335impl<'subs, W> Demangle<'subs, W> for UnresolvedName
6336where
6337 W: 'subs + DemangleWrite,
6338{
6339 fn demangle<'prev, 'ctx>(
6340 &'subs self,
6341 ctx: &'ctx mut DemangleContext<'subs, W>,
6342 scope: Option<ArgScopeStack<'prev, 'subs>>,
6343 ) -> fmt::Result {
6344 let ctx = try_begin_demangle!(self, ctx, scope);
6345
6346 match *self {
6347 UnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6348 UnresolvedName::Global(ref name) => {
6349 write!(ctx, "::")?;
6350 name.demangle(ctx, scope)
6351 }
6352 UnresolvedName::Nested1(ref ty, ref levels, ref name) => {
6353 ty.demangle(ctx, scope)?;
6354 write!(ctx, "::")?;
6355 for lvl in &levels[..] {
6356 lvl.demangle(ctx, scope)?;
6357 write!(ctx, "::")?;
6358 }
6359 name.demangle(ctx, scope)
6360 }
6361 UnresolvedName::Nested2(ref levels, ref name) => {
6362 for lvl in &levels[..] {
6363 lvl.demangle(ctx, scope)?;
6364 write!(ctx, "::")?;
6365 }
6366 name.demangle(ctx, scope)
6367 }
6368 UnresolvedName::GlobalNested2(ref levels, ref name) => {
6370 write!(ctx, "::")?;
6371 for lvl in &levels[..] {
6372 lvl.demangle(ctx, scope)?;
6373 write!(ctx, "::")?;
6374 }
6375 name.demangle(ctx, scope)
6376 }
6377 }
6378 }
6379}
6380
6381#[derive(Clone, Debug, PartialEq, Eq)]
6389pub enum UnresolvedType {
6390 Template(TemplateParam, Option<TemplateArgs>),
6392
6393 Decltype(Decltype),
6395}
6396
6397define_handle! {
6398 pub enum UnresolvedTypeHandle
6400}
6401
6402impl Parse for UnresolvedTypeHandle {
6403 fn parse<'a, 'b>(
6404 ctx: &'a ParseContext,
6405 subs: &'a mut SubstitutionTable,
6406 input: IndexStr<'b>,
6407 ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)> {
6408 try_begin_parse!("UnresolvedTypeHandle", ctx, input);
6409
6410 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, input) {
6411 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6412 (Some(args), tail)
6413 } else {
6414 (None, tail)
6415 };
6416 let ty = UnresolvedType::Template(param, args);
6417 let ty = Substitutable::UnresolvedType(ty);
6418 let idx = subs.insert(ty);
6419 let handle = UnresolvedTypeHandle::BackReference(idx);
6420 return Ok((handle, tail));
6421 }
6422
6423 if let Ok((decltype, tail)) = Decltype::parse(ctx, subs, input) {
6424 let ty = UnresolvedType::Decltype(decltype);
6425 let ty = Substitutable::UnresolvedType(ty);
6426 let idx = subs.insert(ty);
6427 let handle = UnresolvedTypeHandle::BackReference(idx);
6428 return Ok((handle, tail));
6429 }
6430
6431 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
6432 match sub {
6433 Substitution::WellKnown(component) => {
6434 Ok((UnresolvedTypeHandle::WellKnown(component), tail))
6435 }
6436 Substitution::BackReference(idx) => {
6437 Ok((UnresolvedTypeHandle::BackReference(idx), tail))
6440 }
6441 }
6442 }
6443}
6444
6445impl<'subs, W> Demangle<'subs, W> for UnresolvedType
6446where
6447 W: 'subs + DemangleWrite,
6448{
6449 fn demangle<'prev, 'ctx>(
6450 &'subs self,
6451 ctx: &'ctx mut DemangleContext<'subs, W>,
6452 scope: Option<ArgScopeStack<'prev, 'subs>>,
6453 ) -> fmt::Result {
6454 let ctx = try_begin_demangle!(self, ctx, scope);
6455
6456 match *self {
6457 UnresolvedType::Decltype(ref dt) => dt.demangle(ctx, scope),
6458 UnresolvedType::Template(ref param, ref args) => {
6459 if let Some(ref args) = *args {
6460 let scope = scope.push(args);
6461 param.demangle(ctx, scope)?;
6462 args.demangle(ctx, scope)?;
6463 } else {
6464 param.demangle(ctx, scope)?;
6465 }
6466 Ok(())
6467 }
6468 }
6469 }
6470}
6471
6472#[derive(Clone, Debug, PartialEq, Eq)]
6478pub struct UnresolvedQualifierLevel(SimpleId);
6479
6480impl Parse for UnresolvedQualifierLevel {
6481 fn parse<'a, 'b>(
6482 ctx: &'a ParseContext,
6483 subs: &'a mut SubstitutionTable,
6484 input: IndexStr<'b>,
6485 ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)> {
6486 try_begin_parse!("UnresolvedQualifierLevel", ctx, input);
6487
6488 let (id, tail) = SimpleId::parse(ctx, subs, input)?;
6489 Ok((UnresolvedQualifierLevel(id), tail))
6490 }
6491}
6492
6493impl<'subs, W> Demangle<'subs, W> for UnresolvedQualifierLevel
6494where
6495 W: 'subs + DemangleWrite,
6496{
6497 #[inline]
6498 fn demangle<'prev, 'ctx>(
6499 &'subs self,
6500 ctx: &'ctx mut DemangleContext<'subs, W>,
6501 scope: Option<ArgScopeStack<'prev, 'subs>>,
6502 ) -> fmt::Result {
6503 let ctx = try_begin_demangle!(self, ctx, scope);
6504
6505 self.0.demangle(ctx, scope)
6506 }
6507}
6508
6509#[derive(Clone, Debug, PartialEq, Eq)]
6515pub struct SimpleId(SourceName, Option<TemplateArgs>);
6516
6517impl Parse for SimpleId {
6518 fn parse<'a, 'b>(
6519 ctx: &'a ParseContext,
6520 subs: &'a mut SubstitutionTable,
6521 input: IndexStr<'b>,
6522 ) -> Result<(SimpleId, IndexStr<'b>)> {
6523 try_begin_parse!("SimpleId", ctx, input);
6524
6525 let (name, tail) = SourceName::parse(ctx, subs, input)?;
6526 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6527 (Some(args), tail)
6528 } else {
6529 (None, tail)
6530 };
6531 Ok((SimpleId(name, args), tail))
6532 }
6533}
6534
6535impl<'subs, W> Demangle<'subs, W> for SimpleId
6536where
6537 W: 'subs + DemangleWrite,
6538{
6539 fn demangle<'prev, 'ctx>(
6540 &'subs self,
6541 ctx: &'ctx mut DemangleContext<'subs, W>,
6542 scope: Option<ArgScopeStack<'prev, 'subs>>,
6543 ) -> fmt::Result {
6544 let ctx = try_begin_demangle!(self, ctx, scope);
6545
6546 self.0.demangle(ctx, scope)?;
6547 if let Some(ref args) = self.1 {
6548 args.demangle(ctx, scope)?;
6549 }
6550 Ok(())
6551 }
6552}
6553
6554#[derive(Clone, Debug, PartialEq, Eq)]
6564pub enum BaseUnresolvedName {
6565 Name(SimpleId),
6567
6568 Operator(OperatorName, Option<TemplateArgs>),
6570
6571 Destructor(DestructorName),
6573}
6574
6575impl Parse for BaseUnresolvedName {
6576 fn parse<'a, 'b>(
6577 ctx: &'a ParseContext,
6578 subs: &'a mut SubstitutionTable,
6579 input: IndexStr<'b>,
6580 ) -> Result<(BaseUnresolvedName, IndexStr<'b>)> {
6581 try_begin_parse!("BaseUnresolvedName", ctx, input);
6582
6583 if let Ok((name, tail)) = SimpleId::parse(ctx, subs, input) {
6584 return Ok((BaseUnresolvedName::Name(name), tail));
6585 }
6586
6587 if let Ok(tail) = consume(b"on", input) {
6588 let (opname, tail) = OperatorName::parse(ctx, subs, tail)?;
6589 let (args, tail) = if let Ok((args, tail)) = TemplateArgs::parse(ctx, subs, tail) {
6590 (Some(args), tail)
6591 } else {
6592 (None, tail)
6593 };
6594 return Ok((BaseUnresolvedName::Operator(opname, args), tail));
6595 }
6596
6597 let tail = consume(b"dn", input)?;
6598 let (name, tail) = DestructorName::parse(ctx, subs, tail)?;
6599 Ok((BaseUnresolvedName::Destructor(name), tail))
6600 }
6601}
6602
6603impl<'subs, W> Demangle<'subs, W> for BaseUnresolvedName
6604where
6605 W: 'subs + DemangleWrite,
6606{
6607 fn demangle<'prev, 'ctx>(
6608 &'subs self,
6609 ctx: &'ctx mut DemangleContext<'subs, W>,
6610 scope: Option<ArgScopeStack<'prev, 'subs>>,
6611 ) -> fmt::Result {
6612 let ctx = try_begin_demangle!(self, ctx, scope);
6613
6614 match *self {
6615 BaseUnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6616 BaseUnresolvedName::Destructor(ref dtor) => dtor.demangle(ctx, scope),
6617 BaseUnresolvedName::Operator(ref op, ref args) => {
6618 op.demangle(ctx, scope)?;
6619 if let Some(ref args) = *args {
6620 args.demangle(ctx, scope)?;
6621 }
6622 Ok(())
6623 }
6624 }
6625 }
6626}
6627
6628#[derive(Clone, Debug, PartialEq, Eq)]
6635pub enum DestructorName {
6636 Unresolved(UnresolvedTypeHandle),
6638
6639 Name(SimpleId),
6641}
6642
6643impl Parse for DestructorName {
6644 fn parse<'a, 'b>(
6645 ctx: &'a ParseContext,
6646 subs: &'a mut SubstitutionTable,
6647 input: IndexStr<'b>,
6648 ) -> Result<(DestructorName, IndexStr<'b>)> {
6649 try_begin_parse!("DestructorName", ctx, input);
6650
6651 if let Ok((ty, tail)) = UnresolvedTypeHandle::parse(ctx, subs, input) {
6652 return Ok((DestructorName::Unresolved(ty), tail));
6653 }
6654
6655 let (name, tail) = SimpleId::parse(ctx, subs, input)?;
6656 Ok((DestructorName::Name(name), tail))
6657 }
6658}
6659
6660impl<'subs, W> Demangle<'subs, W> for DestructorName
6661where
6662 W: 'subs + DemangleWrite,
6663{
6664 fn demangle<'prev, 'ctx>(
6665 &'subs self,
6666 ctx: &'ctx mut DemangleContext<'subs, W>,
6667 scope: Option<ArgScopeStack<'prev, 'subs>>,
6668 ) -> fmt::Result {
6669 let ctx = try_begin_demangle!(self, ctx, scope);
6670
6671 write!(ctx, "~")?;
6672 match *self {
6673 DestructorName::Unresolved(ref ty) => ty.demangle(ctx, scope),
6674 DestructorName::Name(ref name) => name.demangle(ctx, scope),
6675 }
6676 }
6677}
6678
6679#[derive(Clone, Debug, PartialEq, Eq)]
6691pub enum ExprPrimary {
6692 Literal(TypeHandle, usize, usize),
6694
6695 External(MangledName),
6697}
6698
6699impl Parse for ExprPrimary {
6700 fn parse<'a, 'b>(
6701 ctx: &'a ParseContext,
6702 subs: &'a mut SubstitutionTable,
6703 input: IndexStr<'b>,
6704 ) -> Result<(ExprPrimary, IndexStr<'b>)> {
6705 try_begin_parse!("ExprPrimary", ctx, input);
6706
6707 let tail = consume(b"L", input)?;
6708
6709 if let Ok((ty, tail)) = TypeHandle::parse(ctx, subs, tail) {
6710 let start = tail.index();
6711 let num_bytes_in_literal = tail.as_ref().iter().take_while(|&&c| c != b'E').count();
6712 let tail = tail.range_from(num_bytes_in_literal..);
6713 let end = tail.index();
6714 let tail = consume(b"E", tail)?;
6715 let expr = ExprPrimary::Literal(ty, start, end);
6716 return Ok((expr, tail));
6717 }
6718
6719 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
6720 let tail = consume(b"E", tail)?;
6721 let expr = ExprPrimary::External(name);
6722 Ok((expr, tail))
6723 }
6724}
6725
6726impl<'subs, W> Demangle<'subs, W> for ExprPrimary
6727where
6728 W: 'subs + DemangleWrite,
6729{
6730 fn demangle<'prev, 'ctx>(
6731 &'subs self,
6732 ctx: &'ctx mut DemangleContext<'subs, W>,
6733 scope: Option<ArgScopeStack<'prev, 'subs>>,
6734 ) -> fmt::Result {
6735 let ctx = try_begin_demangle!(self, ctx, scope);
6736
6737 fn write_literal<W>(ctx: &mut DemangleContext<W>, start: usize, end: usize) -> fmt::Result
6738 where
6739 W: DemangleWrite,
6740 {
6741 debug_assert!(start <= end);
6742 let start = if start < end && ctx.input[start] == b'n' {
6743 write!(ctx, "-")?;
6744 start + 1
6745 } else {
6746 start
6747 };
6748 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6749 log!("Error writing literal: {}", e);
6750 fmt::Error
6751 })?;
6752 ctx.write_str(s)
6753 }
6754
6755 match *self {
6756 ExprPrimary::External(ref name) => {
6757 let saved_show_params = ctx.show_params;
6758 ctx.show_params = true;
6759 let ret = name.demangle(ctx, scope);
6760 ctx.show_params = saved_show_params;
6761 ret
6762 }
6763 ExprPrimary::Literal(
6764 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool)),
6765 start,
6766 end,
6767 ) => match &ctx.input[start..end] {
6768 b"0" => write!(ctx, "false"),
6769 b"1" => write!(ctx, "true"),
6770 _ => {
6771 write!(ctx, "(bool)")?;
6772 write_literal(ctx, start, end)
6773 }
6774 },
6775 ExprPrimary::Literal(
6776 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Nullptr)),
6777 _,
6778 _,
6779 ) => write!(ctx, "nullptr"),
6780 ExprPrimary::Literal(
6781 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Double)),
6782 start,
6783 end,
6784 )
6785 | ExprPrimary::Literal(
6786 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Float)),
6787 start,
6788 end,
6789 ) => {
6790 if ctx.show_expression_literal_types {
6791 write!(ctx, "(")?;
6792 ty.demangle(ctx, scope)?;
6793 write!(ctx, ")")?;
6794 }
6795 let start = if start < end && ctx.input[start] == b'n' {
6796 write!(ctx, "-[")?;
6797 start + 1
6798 } else {
6799 write!(ctx, "[")?;
6800 start
6801 };
6802 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
6803 log!("Error writing literal: {}", e);
6804 fmt::Error
6805 })?;
6806 ctx.write_str(s)?;
6807 write!(ctx, "]")
6808 }
6809 ExprPrimary::Literal(
6810 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int)),
6811 start,
6812 end,
6813 ) => write_literal(ctx, start, end),
6814 ExprPrimary::Literal(ref ty, start, end) => {
6815 if ctx.show_expression_literal_types {
6816 write!(ctx, "(")?;
6817 ty.demangle(ctx, scope)?;
6818 write!(ctx, ")")?;
6819 }
6820 write_literal(ctx, start, end)
6821 }
6822 }
6823 }
6824}
6825
6826#[derive(Clone, Debug, PartialEq, Eq)]
6832pub struct Initializer(Vec<Expression>);
6833
6834impl Parse for Initializer {
6835 fn parse<'a, 'b>(
6836 ctx: &'a ParseContext,
6837 subs: &'a mut SubstitutionTable,
6838 input: IndexStr<'b>,
6839 ) -> Result<(Initializer, IndexStr<'b>)> {
6840 try_begin_parse!("Initializer", ctx, input);
6841
6842 let tail = consume(b"pi", input)?;
6843 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6844 let tail = consume(b"E", tail)?;
6845 Ok((Initializer(exprs), tail))
6846 }
6847}
6848
6849impl<'subs, W> Demangle<'subs, W> for Initializer
6850where
6851 W: 'subs + DemangleWrite,
6852{
6853 fn demangle<'prev, 'ctx>(
6854 &'subs self,
6855 ctx: &'ctx mut DemangleContext<'subs, W>,
6856 scope: Option<ArgScopeStack<'prev, 'subs>>,
6857 ) -> fmt::Result {
6858 let ctx = try_begin_demangle!(self, ctx, scope);
6859
6860 write!(ctx, "(")?;
6861 let mut need_comma = false;
6862 for expr in &self.0 {
6863 if need_comma {
6864 write!(ctx, ", ")?;
6865 }
6866 expr.demangle(ctx, scope)?;
6867 need_comma = true;
6868 }
6869 write!(ctx, ")")?;
6870 Ok(())
6871 }
6872}
6873
6874#[derive(Clone, Debug, PartialEq, Eq)]
6882pub enum LocalName {
6883 Relative(Box<Encoding>, Option<Box<Name>>, Option<Discriminator>),
6886
6887 Default(Box<Encoding>, Option<usize>, Box<Name>),
6889}
6890
6891impl Parse for LocalName {
6892 fn parse<'a, 'b>(
6893 ctx: &'a ParseContext,
6894 subs: &'a mut SubstitutionTable,
6895 input: IndexStr<'b>,
6896 ) -> Result<(LocalName, IndexStr<'b>)> {
6897 try_begin_parse!("LocalName", ctx, input);
6898
6899 let tail = consume(b"Z", input)?;
6900 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
6901 let tail = consume(b"E", tail)?;
6902
6903 if let Ok(tail) = consume(b"s", tail) {
6904 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6905 (Some(disc), tail)
6906 } else {
6907 (None, tail)
6908 };
6909 return Ok((LocalName::Relative(Box::new(encoding), None, disc), tail));
6910 }
6911
6912 if let Ok(tail) = consume(b"d", tail) {
6913 let (param, tail) = if let Ok((num, tail)) = Number::parse(ctx, subs, tail) {
6914 (Some(num as _), tail)
6915 } else {
6916 (None, tail)
6917 };
6918 let tail = consume(b"_", tail)?;
6919 let (name, tail) = Name::parse(ctx, subs, tail)?;
6920 return Ok((
6921 LocalName::Default(Box::new(encoding), param, Box::new(name)),
6922 tail,
6923 ));
6924 }
6925
6926 let (name, tail) = Name::parse(ctx, subs, tail)?;
6927 let (disc, tail) = if let Ok((disc, tail)) = Discriminator::parse(ctx, subs, tail) {
6928 (Some(disc), tail)
6929 } else {
6930 (None, tail)
6931 };
6932
6933 Ok((
6934 LocalName::Relative(Box::new(encoding), Some(Box::new(name)), disc),
6935 tail,
6936 ))
6937 }
6938}
6939
6940impl<'subs, W> Demangle<'subs, W> for LocalName
6941where
6942 W: 'subs + DemangleWrite,
6943{
6944 fn demangle<'prev, 'ctx>(
6945 &'subs self,
6946 ctx: &'ctx mut DemangleContext<'subs, W>,
6947 scope: Option<ArgScopeStack<'prev, 'subs>>,
6948 ) -> fmt::Result {
6949 let ctx = try_begin_demangle!(self, ctx, scope);
6950
6951 let saved_show_params = ctx.show_params;
6952 ctx.show_params = true;
6953 let ret = match *self {
6954 LocalName::Relative(ref encoding, Some(ref name), _) => {
6955 encoding.demangle(ctx, scope)?;
6956 write!(ctx, "::")?;
6957 name.demangle(ctx, scope)
6958 }
6959 LocalName::Relative(ref encoding, None, _) => {
6960 encoding.demangle(ctx, scope)?;
6962 write!(ctx, "::string literal")?;
6963 Ok(())
6964 }
6965 LocalName::Default(ref encoding, _, _) => encoding.demangle(ctx, scope),
6966 };
6967 ctx.show_params = saved_show_params;
6968 ret
6969 }
6970}
6971
6972impl GetTemplateArgs for LocalName {
6973 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
6974 match *self {
6975 LocalName::Relative(_, None, _) => None,
6976 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6977 name.get_template_args(subs)
6978 }
6979 }
6980 }
6981}
6982
6983impl<'a> GetLeafName<'a> for LocalName {
6984 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
6985 match *self {
6986 LocalName::Relative(_, None, _) => None,
6987 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
6988 name.get_leaf_name(subs)
6989 }
6990 }
6991 }
6992}
6993
6994#[derive(Clone, Debug, PartialEq, Eq)]
7001pub struct Discriminator(usize);
7002
7003impl Parse for Discriminator {
7004 fn parse<'a, 'b>(
7005 ctx: &'a ParseContext,
7006 _subs: &'a mut SubstitutionTable,
7007 input: IndexStr<'b>,
7008 ) -> Result<(Discriminator, IndexStr<'b>)> {
7009 try_begin_parse!("Discriminator", ctx, input);
7010
7011 let tail = consume(b"_", input)?;
7012
7013 if let Ok(tail) = consume(b"_", tail) {
7014 let (num, tail) = parse_number(10, false, tail)?;
7015 debug_assert!(num >= 0);
7016 if num < 10 {
7017 return Err(error::Error::UnexpectedText);
7018 }
7019 let tail = consume(b"_", tail)?;
7020 return Ok((Discriminator(num as _), tail));
7021 }
7022
7023 match tail.try_split_at(1) {
7024 None => Err(error::Error::UnexpectedEnd),
7025 Some((head, tail)) => match head.as_ref()[0] {
7026 b'0' => Ok((Discriminator(0), tail)),
7027 b'1' => Ok((Discriminator(1), tail)),
7028 b'2' => Ok((Discriminator(2), tail)),
7029 b'3' => Ok((Discriminator(3), tail)),
7030 b'4' => Ok((Discriminator(4), tail)),
7031 b'5' => Ok((Discriminator(5), tail)),
7032 b'6' => Ok((Discriminator(6), tail)),
7033 b'7' => Ok((Discriminator(7), tail)),
7034 b'8' => Ok((Discriminator(8), tail)),
7035 b'9' => Ok((Discriminator(9), tail)),
7036 _ => Err(error::Error::UnexpectedText),
7037 },
7038 }
7039 }
7040}
7041
7042#[derive(Clone, Debug, PartialEq, Eq)]
7048pub struct ClosureTypeName(LambdaSig, Option<usize>);
7049
7050impl Parse for ClosureTypeName {
7051 fn parse<'a, 'b>(
7052 ctx: &'a ParseContext,
7053 subs: &'a mut SubstitutionTable,
7054 input: IndexStr<'b>,
7055 ) -> Result<(ClosureTypeName, IndexStr<'b>)> {
7056 try_begin_parse!("ClosureTypeName", ctx, input);
7057
7058 let tail = consume(b"Ul", input)?;
7059 let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
7060 let tail = consume(b"E", tail)?;
7061 let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
7062 (Some(num as _), tail)
7063 } else {
7064 (None, tail)
7065 };
7066 let tail = consume(b"_", tail)?;
7067 Ok((ClosureTypeName(sig, num), tail))
7068 }
7069}
7070
7071impl<'subs, W> Demangle<'subs, W> for ClosureTypeName
7072where
7073 W: 'subs + DemangleWrite,
7074{
7075 fn demangle<'prev, 'ctx>(
7076 &'subs self,
7077 ctx: &'ctx mut DemangleContext<'subs, W>,
7078 scope: Option<ArgScopeStack<'prev, 'subs>>,
7079 ) -> fmt::Result {
7080 let ctx = try_begin_demangle!(self, ctx, scope);
7081
7082 write!(ctx, "{{lambda(")?;
7083 self.0.demangle(ctx, scope)?;
7084 write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
7085 Ok(())
7086 }
7087}
7088
7089impl<'subs> ArgScope<'subs, 'subs> for ClosureTypeName {
7090 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
7091 Ok(LeafName::Closure(self))
7092 }
7093
7094 fn get_template_arg(
7095 &'subs self,
7096 _: usize,
7097 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
7098 Err(error::Error::BadTemplateArgReference)
7099 }
7100
7101 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
7102 Err(error::Error::BadFunctionArgReference)
7103 }
7104}
7105
7106impl<'a> GetLeafName<'a> for ClosureTypeName {
7107 #[inline]
7108 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7109 Some(LeafName::Closure(self))
7110 }
7111}
7112
7113impl ClosureTypeName {
7114 #[inline]
7115 fn starts_with(byte: u8, input: &IndexStr) -> bool {
7116 byte == b'U' && input.peek_second().map(|b| b == b'l').unwrap_or(false)
7117 }
7118}
7119
7120#[derive(Clone, Debug, PartialEq, Eq)]
7126pub struct LambdaSig(Vec<TypeHandle>);
7127
7128impl LambdaSig {
7129 fn demangle_args<'subs, 'prev, 'ctx, W>(
7130 &'subs self,
7131 ctx: &'ctx mut DemangleContext<'subs, W>,
7132 scope: Option<ArgScopeStack<'prev, 'subs>>,
7133 ) -> fmt::Result
7134 where
7135 W: 'subs + DemangleWrite,
7136 {
7137 let mut need_comma = false;
7138 for ty in &self.0 {
7139 if need_comma {
7140 write!(ctx, ", ")?;
7141 }
7142 ty.demangle(ctx, scope)?;
7143 need_comma = true;
7144 }
7145 Ok(())
7146 }
7147}
7148
7149impl Parse for LambdaSig {
7150 fn parse<'a, 'b>(
7151 ctx: &'a ParseContext,
7152 subs: &'a mut SubstitutionTable,
7153 input: IndexStr<'b>,
7154 ) -> Result<(LambdaSig, IndexStr<'b>)> {
7155 try_begin_parse!("LambdaSig", ctx, input);
7156
7157 let (types, tail) = if let Ok(tail) = consume(b"v", input) {
7158 (vec![], tail)
7159 } else {
7160 one_or_more::<TypeHandle>(ctx, subs, input)?
7161 };
7162 Ok((LambdaSig(types), tail))
7163 }
7164}
7165
7166impl<'subs, W> Demangle<'subs, W> for LambdaSig
7167where
7168 W: 'subs + DemangleWrite,
7169{
7170 fn demangle<'prev, 'ctx>(
7171 &'subs self,
7172 ctx: &'ctx mut DemangleContext<'subs, W>,
7173 scope: Option<ArgScopeStack<'prev, 'subs>>,
7174 ) -> fmt::Result {
7175 let ctx = try_begin_demangle!(self, ctx, scope);
7176
7177 ctx.is_lambda_arg = true;
7178 let r = self.demangle_args(ctx, scope);
7179 ctx.is_lambda_arg = false;
7180 r
7181 }
7182}
7183
7184#[derive(Clone, Debug, PartialEq, Eq)]
7190pub struct DataMemberPrefix(SourceName);
7191
7192impl Parse for DataMemberPrefix {
7193 fn parse<'a, 'b>(
7194 ctx: &'a ParseContext,
7195 subs: &'a mut SubstitutionTable,
7196 input: IndexStr<'b>,
7197 ) -> Result<(DataMemberPrefix, IndexStr<'b>)> {
7198 try_begin_parse!("DataMemberPrefix", ctx, input);
7199
7200 let (name, tail) = SourceName::parse(ctx, subs, input)?;
7201 let tail = consume(b"M", tail)?;
7202 Ok((DataMemberPrefix(name), tail))
7203 }
7204}
7205
7206impl<'a> GetLeafName<'a> for DataMemberPrefix {
7207 #[inline]
7208 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7209 Some(LeafName::SourceName(&self.0))
7210 }
7211}
7212
7213impl DataMemberPrefix {
7214 fn starts_with(byte: u8) -> bool {
7215 SourceName::starts_with(byte)
7216 }
7217}
7218
7219impl<'subs, W> Demangle<'subs, W> for DataMemberPrefix
7220where
7221 W: 'subs + DemangleWrite,
7222{
7223 #[inline]
7224 fn demangle<'prev, 'ctx>(
7225 &'subs self,
7226 ctx: &'ctx mut DemangleContext<'subs, W>,
7227 scope: Option<ArgScopeStack<'prev, 'subs>>,
7228 ) -> fmt::Result {
7229 let ctx = try_begin_demangle!(self, ctx, scope);
7230
7231 ctx.push_demangle_node(DemangleNodeType::DataMemberPrefix);
7232 let ret = self.0.demangle(ctx, scope);
7233 ctx.pop_demangle_node();
7234 ret
7235 }
7236}
7237
7238#[derive(Clone, Debug, PartialEq, Eq)]
7255pub enum Substitution {
7256 BackReference(usize),
7259
7260 WellKnown(WellKnownComponent),
7264}
7265
7266impl Parse for Substitution {
7267 fn parse<'a, 'b>(
7268 ctx: &'a ParseContext,
7269 subs: &'a mut SubstitutionTable,
7270 input: IndexStr<'b>,
7271 ) -> Result<(Substitution, IndexStr<'b>)> {
7272 try_begin_parse!("Substitution", ctx, input);
7273
7274 if let Ok((well_known, tail)) = WellKnownComponent::parse(ctx, subs, input) {
7275 return Ok((Substitution::WellKnown(well_known), tail));
7276 }
7277
7278 let tail = consume(b"S", input)?;
7279 let (idx, tail) = if let Ok((idx, tail)) = SeqId::parse(ctx, subs, tail) {
7280 (idx.0 + 1, tail)
7281 } else {
7282 (0, tail)
7283 };
7284
7285 if !subs.contains(idx) {
7286 return Err(error::Error::BadBackReference);
7287 }
7288
7289 let tail = consume(b"_", tail)?;
7290 log!("Found a reference to @ {}", idx);
7291 Ok((Substitution::BackReference(idx), tail))
7292 }
7293}
7294
7295define_vocabulary! {
7296#[derive(Clone, Debug, PartialEq, Eq)]
7300 pub enum WellKnownComponent {
7301 Std (b"St", "std"),
7302 StdAllocator (b"Sa", "std::allocator"),
7303 StdString1 (b"Sb", "std::basic_string"),
7304 StdString2 (b"Ss", "std::string"),
7305 StdIstream (b"Si", "std::basic_istream<char, std::char_traits<char> >"),
7306 StdOstream (b"So", "std::ostream"),
7307 StdIostream (b"Sd", "std::basic_iostream<char, std::char_traits<char> >")
7308 }
7309}
7310
7311impl<'a> GetLeafName<'a> for WellKnownComponent {
7312 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7313 match *self {
7314 WellKnownComponent::Std => None,
7315 _ => Some(LeafName::WellKnownComponent(self)),
7316 }
7317 }
7318}
7319
7320impl<'a> ArgScope<'a, 'a> for WellKnownComponent {
7321 fn leaf_name(&'a self) -> Result<LeafName<'a>> {
7322 Ok(LeafName::WellKnownComponent(self))
7323 }
7324
7325 fn get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)> {
7326 Err(error::Error::BadTemplateArgReference)
7327 }
7328
7329 fn get_function_arg(&'a self, _: usize) -> Result<&'a Type> {
7330 Err(error::Error::BadFunctionArgReference)
7331 }
7332}
7333
7334impl<'subs, W> DemangleAsLeaf<'subs, W> for WellKnownComponent
7335where
7336 W: 'subs + DemangleWrite,
7337{
7338 fn demangle_as_leaf<'me, 'ctx>(
7339 &'me self,
7340 ctx: &'ctx mut DemangleContext<'subs, W>,
7341 ) -> fmt::Result {
7342 match *self {
7343 WellKnownComponent::Std => {
7344 panic!("should never treat `WellKnownComponent::Std` as a leaf name")
7345 }
7346 WellKnownComponent::StdAllocator => write!(ctx, "allocator"),
7347 WellKnownComponent::StdString1 => write!(ctx, "basic_string"),
7348 WellKnownComponent::StdString2 => write!(ctx, "string"),
7349 WellKnownComponent::StdIstream => write!(ctx, "basic_istream"),
7350 WellKnownComponent::StdOstream => write!(ctx, "ostream"),
7351 WellKnownComponent::StdIostream => write!(ctx, "basic_iostream"),
7352 }
7353 }
7354}
7355
7356#[derive(Clone, Debug, PartialEq, Eq)]
7409pub enum SpecialName {
7410 VirtualTable(TypeHandle),
7412
7413 Vtt(TypeHandle),
7415
7416 Typeinfo(TypeHandle),
7418
7419 TypeinfoName(TypeHandle),
7421
7422 VirtualOverrideThunk(CallOffset, Box<Encoding>),
7424
7425 VirtualOverrideThunkCovariant(CallOffset, CallOffset, Box<Encoding>),
7427
7428 Guard(Name),
7430
7431 GuardTemporary(Name, usize),
7434
7435 ConstructionVtable(TypeHandle, usize, TypeHandle),
7437
7438 TypeinfoFunction(TypeHandle),
7440
7441 TlsInit(Name),
7443
7444 TlsWrapper(Name),
7446
7447 JavaResource(Vec<ResourceName>),
7449
7450 TransactionClone(Box<Encoding>),
7452
7453 NonTransactionClone(Box<Encoding>),
7455}
7456
7457impl Parse for SpecialName {
7458 fn parse<'a, 'b>(
7459 ctx: &'a ParseContext,
7460 subs: &'a mut SubstitutionTable,
7461 input: IndexStr<'b>,
7462 ) -> Result<(SpecialName, IndexStr<'b>)> {
7463 try_begin_parse!("SpecialName", ctx, input);
7464
7465 let (head, tail) = match input.try_split_at(2) {
7466 None => return Err(error::Error::UnexpectedEnd),
7467 Some((head, tail)) => (head, tail),
7468 };
7469
7470 match head.as_ref() {
7471 b"TV" => {
7472 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7473 Ok((SpecialName::VirtualTable(ty), tail))
7474 }
7475 b"TT" => {
7476 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7477 Ok((SpecialName::Vtt(ty), tail))
7478 }
7479 b"TI" => {
7480 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7481 Ok((SpecialName::Typeinfo(ty), tail))
7482 }
7483 b"TS" => {
7484 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7485 Ok((SpecialName::TypeinfoName(ty), tail))
7486 }
7487 b"Tc" => {
7488 let (first, tail) = CallOffset::parse(ctx, subs, tail)?;
7489 let (second, tail) = CallOffset::parse(ctx, subs, tail)?;
7490 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7491 Ok((
7492 SpecialName::VirtualOverrideThunkCovariant(first, second, Box::new(base)),
7493 tail,
7494 ))
7495 }
7496 b"Th" | b"Tv" => {
7497 let tail = consume(b"T", input).unwrap();
7500 let (offset, tail) = CallOffset::parse(ctx, subs, tail)?;
7501 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7502 Ok((
7503 SpecialName::VirtualOverrideThunk(offset, Box::new(base)),
7504 tail,
7505 ))
7506 }
7507 b"TC" => {
7508 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
7509 let (n, tail) = parse_number(10, false, tail)?;
7510 let tail = consume(b"_", tail)?;
7511 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
7512 Ok((SpecialName::ConstructionVtable(ty1, n as usize, ty2), tail))
7513 }
7514 b"TF" => {
7515 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7516 Ok((SpecialName::TypeinfoFunction(ty), tail))
7517 }
7518 b"TH" => {
7519 let (name, tail) = Name::parse(ctx, subs, tail)?;
7520 Ok((SpecialName::TlsInit(name), tail))
7521 }
7522 b"TW" => {
7523 let (name, tail) = Name::parse(ctx, subs, tail)?;
7524 Ok((SpecialName::TlsWrapper(name), tail))
7525 }
7526 b"GV" => {
7527 let (name, tail) = Name::parse(ctx, subs, tail)?;
7528 Ok((SpecialName::Guard(name), tail))
7529 }
7530 b"GR" => {
7531 let (name, tail) = Name::parse(ctx, subs, tail)?;
7532 let (idx, tail) = if let Ok(tail) = consume(b"_", tail) {
7533 (0, tail)
7534 } else {
7535 let (idx, tail) = SeqId::parse(ctx, subs, tail)?;
7536 let tail = consume(b"_", tail)?;
7537 (idx.0 + 1, tail)
7538 };
7539 Ok((SpecialName::GuardTemporary(name, idx), tail))
7540 }
7541 b"Gr" => {
7542 let (resource_name_len, tail) = parse_number(10, false, tail)?;
7543 if resource_name_len == 0 {
7544 return Err(error::Error::UnexpectedText);
7545 }
7546
7547 let (head, tail) = match tail.try_split_at(resource_name_len as _) {
7548 Some((head, tail)) => (head, tail),
7549 None => return Err(error::Error::UnexpectedEnd),
7550 };
7551
7552 let head = consume(b"_", head)?;
7553
7554 let (resource_names, empty) = zero_or_more::<ResourceName>(ctx, subs, head)?;
7555 if !empty.is_empty() {
7556 return Err(error::Error::UnexpectedText);
7557 }
7558
7559 Ok((SpecialName::JavaResource(resource_names), tail))
7560 }
7561 b"GT" => {
7562 match tail.next_or(error::Error::UnexpectedEnd)? {
7563 (b'n', tail) => {
7564 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7565 Ok((SpecialName::NonTransactionClone(Box::new(base)), tail))
7566 }
7567 (b't', tail) | (_, tail) => {
7570 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7571 Ok((SpecialName::TransactionClone(Box::new(base)), tail))
7572 }
7573 }
7574 }
7575 _ => Err(error::Error::UnexpectedText),
7576 }
7577 }
7578}
7579
7580impl<'subs, W> Demangle<'subs, W> for SpecialName
7581where
7582 W: 'subs + DemangleWrite,
7583{
7584 fn demangle<'prev, 'ctx>(
7585 &'subs self,
7586 ctx: &'ctx mut DemangleContext<'subs, W>,
7587 scope: Option<ArgScopeStack<'prev, 'subs>>,
7588 ) -> fmt::Result {
7589 let ctx = try_begin_demangle!(self, ctx, scope);
7590
7591 match *self {
7592 SpecialName::VirtualTable(ref ty) => {
7593 write!(ctx, "{{vtable(")?;
7594 ctx.push_demangle_node(DemangleNodeType::VirtualTable);
7595 ty.demangle(ctx, scope)?;
7596 ctx.pop_demangle_node();
7597 write!(ctx, ")}}")?;
7598 Ok(())
7599 }
7600 SpecialName::Vtt(ref ty) => {
7601 write!(ctx, "{{vtt(")?;
7602 ty.demangle(ctx, scope)?;
7603 write!(ctx, ")}}")?;
7604 Ok(())
7605 }
7606 SpecialName::Typeinfo(ref ty) => {
7607 write!(ctx, "typeinfo for ")?;
7608 ty.demangle(ctx, scope)
7609 }
7610 SpecialName::TypeinfoName(ref ty) => {
7611 write!(ctx, "typeinfo name for ")?;
7612 ty.demangle(ctx, scope)
7613 }
7614 SpecialName::VirtualOverrideThunk(ref offset, ref encoding) => {
7615 write!(ctx, "{{virtual override thunk(")?;
7616 offset.demangle(ctx, scope)?;
7617 write!(ctx, ", ")?;
7618 encoding.demangle(ctx, scope)?;
7619 write!(ctx, ")}}")?;
7620 Ok(())
7621 }
7622 SpecialName::VirtualOverrideThunkCovariant(
7623 ref this_offset,
7624 ref result_offset,
7625 ref encoding,
7626 ) => {
7627 write!(ctx, "{{virtual override thunk(")?;
7628 this_offset.demangle(ctx, scope)?;
7629 write!(ctx, ", ")?;
7630 result_offset.demangle(ctx, scope)?;
7631 write!(ctx, ", ")?;
7632 encoding.demangle(ctx, scope)?;
7633 write!(ctx, ")}}")?;
7634 Ok(())
7635 }
7636 SpecialName::Guard(ref name) => {
7637 write!(ctx, "guard variable for ")?;
7638 name.demangle(ctx, scope)
7639 }
7640 SpecialName::GuardTemporary(ref name, n) => {
7641 write!(ctx, "reference temporary #{} for ", n)?;
7642 name.demangle(ctx, scope)
7643 }
7644 SpecialName::ConstructionVtable(ref ty1, _, ref ty2) => {
7645 write!(ctx, "construction vtable for ")?;
7646 ty1.demangle(ctx, scope)?;
7647 write!(ctx, "-in-")?;
7648 ty2.demangle(ctx, scope)
7649 }
7650 SpecialName::TypeinfoFunction(ref ty) => {
7651 write!(ctx, "typeinfo fn for ")?;
7652 ty.demangle(ctx, scope)
7653 }
7654 SpecialName::TlsInit(ref name) => {
7655 write!(ctx, "TLS init function for ")?;
7656 name.demangle(ctx, scope)
7657 }
7658 SpecialName::TlsWrapper(ref name) => {
7659 write!(ctx, "TLS wrapper function for ")?;
7660 name.demangle(ctx, scope)
7661 }
7662 SpecialName::TransactionClone(ref encoding) => {
7663 write!(ctx, "transaction clone for ")?;
7664 encoding.demangle(ctx, scope)
7665 }
7666 SpecialName::NonTransactionClone(ref encoding) => {
7667 write!(ctx, "non-transaction clone for ")?;
7668 encoding.demangle(ctx, scope)
7669 }
7670 SpecialName::JavaResource(ref names) => {
7671 write!(ctx, "java resource ")?;
7672 for name in names {
7673 name.demangle(ctx, scope)?;
7674 }
7675 Ok(())
7676 }
7677 }
7678 }
7679}
7680
7681#[derive(Clone, Debug, PartialEq, Eq)]
7683pub struct ResourceName {
7684 start: usize,
7685 end: usize,
7686}
7687
7688impl Parse for ResourceName {
7689 fn parse<'a, 'b>(
7690 ctx: &'a ParseContext,
7691 _subs: &'a mut SubstitutionTable,
7692 input: IndexStr<'b>,
7693 ) -> Result<(ResourceName, IndexStr<'b>)> {
7694 try_begin_parse!("ResourceName", ctx, input);
7695
7696 if input.is_empty() {
7697 return Err(error::Error::UnexpectedEnd);
7698 }
7699
7700 let mut end = input
7701 .as_ref()
7702 .iter()
7703 .map(|&c| c as char)
7704 .take_while(|&c| c != '$' || c.is_digit(36))
7705 .count();
7706
7707 if end == 0 {
7708 return Err(error::Error::UnexpectedText);
7709 }
7710
7711 if input.range_from(end..).peek() == Some(b'$') {
7712 match input.range_from(end..).peek_second() {
7713 Some(b'S') | Some(b'_') | Some(b'$') => end += 2,
7714 _ => return Err(error::Error::UnexpectedText),
7715 }
7716 }
7717
7718 let tail = input.range_from(end..);
7719
7720 let resource_name = ResourceName {
7721 start: input.index(),
7722 end: tail.index(),
7723 };
7724
7725 Ok((resource_name, tail))
7726 }
7727}
7728
7729impl<'subs, W> Demangle<'subs, W> for ResourceName
7730where
7731 W: 'subs + DemangleWrite,
7732{
7733 #[inline]
7734 fn demangle<'prev, 'ctx>(
7735 &'subs self,
7736 ctx: &'ctx mut DemangleContext<'subs, W>,
7737 scope: Option<ArgScopeStack<'prev, 'subs>>,
7738 ) -> fmt::Result {
7739 let ctx = try_begin_demangle!(self, ctx, scope);
7740
7741 let mut i = self.start;
7742 while i < self.end {
7743 let ch = ctx.input[i];
7744 if ch == b'$' {
7745 i += 1;
7747 match ctx.input[i] {
7748 b'S' => write!(ctx, "{}", '/')?,
7749 b'_' => write!(ctx, "{}", '.')?,
7750 b'$' => write!(ctx, "{}", '$')?,
7751 _ => {
7752 }
7754 }
7755 } else {
7756 write!(ctx, "{}", ch as char)?;
7757 }
7758 i += 1;
7759 }
7760
7761 Ok(())
7762 }
7763}
7764
7765#[derive(Clone, Debug, PartialEq, Eq)]
7773pub struct SubobjectExpr {
7774 ty: TypeHandle,
7775 expr: Box<Expression>,
7776 offset: isize,
7777}
7778
7779impl Parse for SubobjectExpr {
7780 fn parse<'a, 'b>(
7781 ctx: &'a ParseContext,
7782 subs: &'a mut SubstitutionTable,
7783 input: IndexStr<'b>,
7784 ) -> Result<(SubobjectExpr, IndexStr<'b>)> {
7785 try_begin_parse!("SubobjectExpr", ctx, input);
7786
7787 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
7788 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
7789 let (offset, tail) = parse_number(10, true, tail).unwrap_or((0, tail));
7790
7791 let tail = consume(b"E", tail)?;
7793 Ok((
7794 SubobjectExpr {
7795 ty: ty,
7796 expr: Box::new(expr),
7797 offset: offset,
7798 },
7799 tail,
7800 ))
7801 }
7802}
7803
7804impl<'subs, W> Demangle<'subs, W> for SubobjectExpr
7805where
7806 W: 'subs + DemangleWrite,
7807{
7808 #[inline]
7809 fn demangle<'prev, 'ctx>(
7810 &'subs self,
7811 ctx: &'ctx mut DemangleContext<'subs, W>,
7812 scope: Option<ArgScopeStack<'prev, 'subs>>,
7813 ) -> fmt::Result {
7814 let ctx = try_begin_demangle!(self, ctx, scope);
7815
7816 self.expr.demangle(ctx, scope)?;
7817 write!(ctx, ".<")?;
7818 self.ty.demangle(ctx, scope)?;
7819 write!(ctx, " at offset {}>", self.offset)
7820 }
7821}
7822
7823#[inline]
7828fn consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>> {
7829 match input.try_split_at(expected.len()) {
7830 Some((head, tail)) if head == expected => Ok(tail),
7831 Some(_) => Err(error::Error::UnexpectedText),
7832 None => Err(error::Error::UnexpectedEnd),
7833 }
7834}
7835
7836fn one_or_more<'a, 'b, P>(
7837 ctx: &'a ParseContext,
7838 subs: &'a mut SubstitutionTable,
7839 input: IndexStr<'b>,
7840) -> Result<(Vec<P>, IndexStr<'b>)>
7841where
7842 P: Parse,
7843{
7844 let (first, mut tail) = P::parse(ctx, subs, input)?;
7845 let mut results = vec![first];
7846 loop {
7847 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7848 results.push(parsed);
7849 tail = tail_tail;
7850 } else {
7851 return Ok((results, tail));
7852 }
7853 }
7854}
7855
7856fn zero_or_more<'a, 'b, P>(
7857 ctx: &'a ParseContext,
7858 subs: &'a mut SubstitutionTable,
7859 input: IndexStr<'b>,
7860) -> Result<(Vec<P>, IndexStr<'b>)>
7861where
7862 P: Parse,
7863{
7864 let mut tail = input;
7865 let mut results = vec![];
7866 loop {
7867 if let Ok((parsed, tail_tail)) = P::parse(ctx, subs, tail) {
7868 results.push(parsed);
7869 tail = tail_tail;
7870 } else {
7871 return Ok((results, tail));
7872 }
7873 }
7874}
7875
7876#[allow(unsafe_code)]
7879fn parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)> {
7880 if input.is_empty() {
7881 return Err(error::Error::UnexpectedEnd);
7882 }
7883
7884 let num_is_negative = if allow_signed && input.as_ref()[0] == b'n' {
7885 input = input.range_from(1..);
7886
7887 if input.is_empty() {
7888 return Err(error::Error::UnexpectedEnd);
7889 }
7890
7891 true
7892 } else {
7893 false
7894 };
7895
7896 let num_numeric = input
7897 .as_ref()
7898 .iter()
7899 .map(|&c| c as char)
7900 .take_while(|c| c.is_digit(base) && (c.is_numeric() || c.is_uppercase()))
7901 .count();
7902 if num_numeric == 0 {
7903 return Err(error::Error::UnexpectedText);
7904 }
7905
7906 let (head, tail) = input.split_at(num_numeric);
7907 let head = head.as_ref();
7908
7909 if num_numeric > 1 && head[0] == b'0' {
7910 return Err(error::Error::UnexpectedText);
7913 }
7914
7915 let head = unsafe {
7916 str::from_utf8_unchecked(head)
7919 };
7920
7921 let mut number = isize::from_str_radix(head, base).map_err(|_| error::Error::Overflow)?;
7922 if num_is_negative {
7923 number = -number;
7924 }
7925
7926 Ok((number, tail))
7927}
7928
7929#[cfg(test)]
7930mod tests {
7931 use super::{
7932 ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset, ClassEnumType,
7933 ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype, DestructorName,
7934 Discriminator, Encoding, ExceptionSpec, ExprPrimary, Expression, FunctionParam,
7935 FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName, MangledName,
7936 MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName, Parse,
7937 ParseContext, PointerToMemberType, Prefix, PrefixHandle, RefQualifier, ResourceName, SeqId,
7938 SimpleId, SimpleOperatorName, SourceName, SpecialName, StandardBuiltinType, SubobjectExpr,
7939 Substitution, TaggedName, TemplateArg, TemplateArgs, TemplateParam, TemplateTemplateParam,
7940 TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName, UnqualifiedName,
7941 UnresolvedName, UnresolvedQualifierLevel, UnresolvedType, UnresolvedTypeHandle,
7942 UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle, VOffset, VectorType,
7943 WellKnownComponent,
7944 };
7945
7946 use crate::error::Error;
7947 use crate::index_str::IndexStr;
7948 use crate::subs::{Substitutable, SubstitutionTable};
7949 use alloc::boxed::Box;
7950 use alloc::string::String;
7951 use core::fmt::Debug;
7952 use core::iter::FromIterator;
7953
7954 fn assert_parse_ok<P, S1, S2, I1, I2>(
7955 production: &'static str,
7956 subs: S1,
7957 input: I1,
7958 expected: P,
7959 expected_tail: I2,
7960 expected_new_subs: S2,
7961 ) where
7962 P: Debug + Parse + PartialEq,
7963 S1: AsRef<[Substitutable]>,
7964 S2: AsRef<[Substitutable]>,
7965 I1: AsRef<[u8]>,
7966 I2: AsRef<[u8]>,
7967 {
7968 let ctx = ParseContext::new(Default::default());
7969 let input = input.as_ref();
7970 let expected_tail = expected_tail.as_ref();
7971
7972 let expected_subs = SubstitutionTable::from_iter(
7973 subs.as_ref()
7974 .iter()
7975 .cloned()
7976 .chain(expected_new_subs.as_ref().iter().cloned()),
7977 );
7978 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
7979
7980 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
7981 Err(error) => panic!(
7982 "Parsing {:?} as {} failed: {}",
7983 String::from_utf8_lossy(input),
7984 production,
7985 error
7986 ),
7987 Ok((value, tail)) => {
7988 if value != expected {
7989 panic!(
7990 "Parsing {:?} as {} produced\n\n{:#?}\n\nbut we expected\n\n{:#?}",
7991 String::from_utf8_lossy(input),
7992 production,
7993 value,
7994 expected
7995 );
7996 }
7997 if tail != expected_tail {
7998 panic!(
7999 "Parsing {:?} as {} left a tail of {:?}, expected {:?}",
8000 String::from_utf8_lossy(input),
8001 production,
8002 tail,
8003 String::from_utf8_lossy(expected_tail)
8004 );
8005 }
8006 if subs[..] != expected_subs[..] {
8007 panic!(
8008 "Parsing {:?} as {} produced a substitutions table of\n\n\
8009 {:#?}\n\n\
8010 but we expected\n\n\
8011 {:#?}",
8012 String::from_utf8_lossy(input),
8013 production,
8014 subs,
8015 expected_subs
8016 );
8017 }
8018 }
8019 }
8020
8021 log!("=== assert_parse_ok PASSED ====================================");
8022 }
8023
8024 fn simple_assert_parse_ok<P, I1, I2>(
8025 production: &'static str,
8026 input: I1,
8027 expected: P,
8028 expected_tail: I2,
8029 ) where
8030 P: Debug + Parse + PartialEq,
8031 I1: AsRef<[u8]>,
8032 I2: AsRef<[u8]>,
8033 {
8034 assert_parse_ok::<P, _, _, _, _>(production, [], input, expected, expected_tail, []);
8035 }
8036
8037 fn assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error)
8038 where
8039 P: Debug + Parse + PartialEq,
8040 S: AsRef<[Substitutable]>,
8041 I: AsRef<[u8]>,
8042 {
8043 let input = input.as_ref();
8044 let ctx = ParseContext::new(Default::default());
8045 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
8046
8047 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
8048 Err(ref error) if *error == expected_error => {}
8049 Err(ref error) => {
8050 panic!(
8051 "Parsing {:?} as {} produced an error of kind {:?}, but we expected kind {:?}",
8052 String::from_utf8_lossy(input),
8053 production,
8054 error,
8055 expected_error
8056 );
8057 }
8058 Ok((value, tail)) => {
8059 panic!(
8060 "Parsing {:?} as {} produced value\
8061 \n\n\
8062 {:#?}\
8063 \n\n\
8064 and tail {:?}, but we expected error kind {:?}",
8065 String::from_utf8_lossy(input),
8066 production,
8067 value,
8068 tail,
8069 expected_error
8070 );
8071 }
8072 }
8073
8074 log!("=== assert_parse_err PASSED ===================================");
8075 }
8076
8077 fn simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error)
8078 where
8079 P: Debug + Parse + PartialEq,
8080 I: AsRef<[u8]>,
8081 {
8082 assert_parse_err::<P, _, _>(production, [], input, expected_error);
8083 }
8084
8085 #[test]
8086 fn recursion_limit() {
8087 let mut mangled = String::new();
8091 for _ in 0..10_000 {
8092 mangled.push('P');
8093 }
8094 mangled += "c";
8095
8096 simple_assert_parse_err::<TypeHandle, _>("TypeHandle", mangled, Error::TooMuchRecursion);
8097 }
8098
8099 macro_rules! assert_parse {
8100 ( $production:ident {
8101 $( with subs $subs:expr => {
8102 Ok => {
8103 $( $input:expr => {
8104 $expected:expr ,
8105 $expected_tail:expr ,
8106 $expected_new_subs:expr
8107 } )*
8108 }
8109 Err => {
8110 $( $error_input:expr => $error:expr , )*
8111 }
8112 } )*
8113 } ) => {
8114 $( $(
8115 assert_parse_ok::<$production, _, _, _, _>(stringify!($production),
8116 $subs,
8117 $input,
8118 $expected,
8119 $expected_tail,
8120 $expected_new_subs);
8121 )* )*
8122
8123 $( $(
8124 assert_parse_err::<$production, _, _>(stringify!($production),
8125 $subs,
8126 $error_input,
8127 $error);
8128 )* )*
8129 };
8130
8131 ( $production:ident {
8132 Ok => {
8133 $( $input:expr => {
8134 $expected:expr ,
8135 $expected_tail:expr
8136 } )*
8137 }
8138 Err => {
8139 $( $error_input:expr => $error:expr , )*
8140 }
8141 } ) => {
8142 $(
8143 simple_assert_parse_ok::<$production, _, _>(stringify!($production),
8144 $input,
8145 $expected,
8146 $expected_tail);
8147 )*
8148
8149
8150 $(
8151 simple_assert_parse_err::<$production, _>(stringify!($production),
8152 $error_input,
8153 $error);
8154 )*
8155 };
8156 }
8157
8158 #[test]
8159 fn parse_mangled_name() {
8160 assert_parse!(MangledName {
8161 Ok => {
8162 b"_Z3foo..." => {
8163 MangledName::Encoding(
8164 Encoding::Data(
8165 Name::Unscoped(
8166 UnscopedName::Unqualified(
8167 UnqualifiedName::Source(
8168 SourceName(Identifier {
8169 start: 3,
8170 end: 6,
8171 }))))), vec![]),
8172 b"..."
8173 }
8174 b"_GLOBAL__I__Z3foo..." => {
8175 MangledName::GlobalCtorDtor(
8176 GlobalCtorDtor::Ctor(
8177 Box::new(
8178 MangledName::Encoding(
8179 Encoding::Data(
8180 Name::Unscoped(
8181 UnscopedName::Unqualified(
8182 UnqualifiedName::Source(
8183 SourceName(
8184 Identifier {
8185 start: 14,
8186 end: 17,
8187 }))))), vec![])))),
8188 b"..."
8189 }
8190 }
8191 Err => {
8192 b"_Y" => Error::UnexpectedText,
8193 b"_Z" => Error::UnexpectedEnd,
8194 b"_" => Error::UnexpectedEnd,
8195 b"" => Error::UnexpectedEnd,
8196 b"_GLOBAL_" => Error::UnexpectedEnd,
8197 }
8198 });
8199 }
8200
8201 #[test]
8202 fn parse_encoding() {
8203 assert_parse!(Encoding {
8204 with subs [] => {
8205 Ok => {
8206 b"3fooi..." => {
8207 Encoding::Function(
8208 Name::Unscoped(
8209 UnscopedName::Unqualified(
8210 UnqualifiedName::Source(
8211 SourceName(Identifier {
8212 start: 1,
8213 end: 4,
8214 })))),
8215 BareFunctionType(vec![
8216 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
8217 ])),
8218 b"...",
8219 []
8220 }
8221 b"3foo..." => {
8222 Encoding::Data(
8223 Name::Unscoped(
8224 UnscopedName::Unqualified(
8225 UnqualifiedName::Source(
8226 SourceName(Identifier {
8227 start: 1,
8228 end: 4,
8229 }))))),
8230 b"...",
8231 []
8232 }
8233 b"GV3abc..." => {
8234 Encoding::Special(
8235 SpecialName::Guard(
8236 Name::Unscoped(
8237 UnscopedName::Unqualified(
8238 UnqualifiedName::Source(
8239 SourceName(Identifier {
8240 start: 3,
8241 end: 6,
8242 })))))),
8243 b"...",
8244 []
8245 }
8246 }
8247 Err => {
8248 b"zzz" => Error::UnexpectedText,
8249 b"" => Error::UnexpectedEnd,
8250 }
8251 }
8252 });
8253 }
8254
8255 #[test]
8256 fn parse_global_ctor_dtor() {
8257 assert_parse!(GlobalCtorDtor {
8258 Ok => {
8259 b"_I__Z3foo..." => {
8260 GlobalCtorDtor::Ctor(
8261 Box::new(
8262 MangledName::Encoding(
8263 Encoding::Data(
8264 Name::Unscoped(
8265 UnscopedName::Unqualified(
8266 UnqualifiedName::Source(
8267 SourceName(
8268 Identifier {
8269 start: 6,
8270 end: 9,
8271 }))))), vec![]))),
8272 b"..."
8273 }
8274 b".I__Z3foo..." => {
8275 GlobalCtorDtor::Ctor(
8276 Box::new(
8277 MangledName::Encoding(
8278 Encoding::Data(
8279 Name::Unscoped(
8280 UnscopedName::Unqualified(
8281 UnqualifiedName::Source(
8282 SourceName(
8283 Identifier {
8284 start: 6,
8285 end: 9,
8286 }))))), vec![]))),
8287 b"..."
8288 }
8289 b"$I__Z3foo..." => {
8290 GlobalCtorDtor::Ctor(
8291 Box::new(
8292 MangledName::Encoding(
8293 Encoding::Data(
8294 Name::Unscoped(
8295 UnscopedName::Unqualified(
8296 UnqualifiedName::Source(
8297 SourceName(
8298 Identifier {
8299 start: 6,
8300 end: 9,
8301 }))))), vec![]))),
8302 b"..."
8303 }
8304 b"_D__Z3foo..." => {
8305 GlobalCtorDtor::Dtor(
8306 Box::new(
8307 MangledName::Encoding(
8308 Encoding::Data(
8309 Name::Unscoped(
8310 UnscopedName::Unqualified(
8311 UnqualifiedName::Source(
8312 SourceName(
8313 Identifier {
8314 start: 6,
8315 end: 9,
8316 }))))), vec![]))),
8317 b"..."
8318 }
8319 b".D__Z3foo..." => {
8320 GlobalCtorDtor::Dtor(
8321 Box::new(
8322 MangledName::Encoding(
8323 Encoding::Data(
8324 Name::Unscoped(
8325 UnscopedName::Unqualified(
8326 UnqualifiedName::Source(
8327 SourceName(
8328 Identifier {
8329 start: 6,
8330 end: 9,
8331 }))))), vec![]))),
8332 b"..."
8333 }
8334 b"$D__Z3foo..." => {
8335 GlobalCtorDtor::Dtor(
8336 Box::new(
8337 MangledName::Encoding(
8338 Encoding::Data(
8339 Name::Unscoped(
8340 UnscopedName::Unqualified(
8341 UnqualifiedName::Source(
8342 SourceName(
8343 Identifier {
8344 start: 6,
8345 end: 9,
8346 }))))), vec![]))),
8347 b"..."
8348 }
8349 }
8350 Err => {
8351 b"_I" => Error::UnexpectedEnd,
8352 b"_" => Error::UnexpectedEnd,
8353 b"" => Error::UnexpectedEnd,
8354 b"blag" => Error::UnexpectedText,
8355 b"_J" => Error::UnexpectedText,
8356 b"_IJ" => Error::UnexpectedText,
8357 }
8358 });
8359 }
8360
8361 #[test]
8362 fn parse_name() {
8363 assert_parse!(Name {
8364 with subs [
8365 Substitutable::Prefix(
8366 Prefix::Unqualified(
8367 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8368 Substitutable::Prefix(
8369 Prefix::Nested(PrefixHandle::BackReference(0),
8370 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New)))),
8371 ] => {
8372 Ok => {
8373 b"NS0_3abcE..." => {
8374 Name::Nested(NestedName::Unqualified(CvQualifiers::default(),
8375 None,
8376 PrefixHandle::BackReference(1),
8377 UnqualifiedName::Source(SourceName(Identifier {
8378 start: 5,
8379 end: 8,
8380 })))),
8381 b"...",
8382 []
8383 }
8384 b"3abc..." => {
8385 Name::Unscoped(
8386 UnscopedName::Unqualified(
8387 UnqualifiedName::Source(
8388 SourceName(Identifier {
8389 start: 1,
8390 end: 4,
8391 })))),
8392 b"...",
8393 []
8394 }
8395 b"dlIcE..." => {
8396 Name::UnscopedTemplate(
8397 UnscopedTemplateNameHandle::BackReference(2),
8398 TemplateArgs(vec![
8399 TemplateArg::Type(
8400 TypeHandle::Builtin(
8401 BuiltinType::Standard(StandardBuiltinType::Char)))
8402 ])),
8403 b"...",
8404 [
8405 Substitutable::UnscopedTemplateName(
8406 UnscopedTemplateName(
8407 UnscopedName::Unqualified(
8408 UnqualifiedName::Operator(
8409 OperatorName::Simple(
8410 SimpleOperatorName::Delete))))),
8411 ]
8412 }
8413 b"Z3abcEs..." => {
8414 Name::Local(
8415 LocalName::Relative(
8416 Box::new(Encoding::Data(
8417 Name::Unscoped(
8418 UnscopedName::Unqualified(
8419 UnqualifiedName::Source(
8420 SourceName(Identifier {
8421 start: 2,
8422 end: 5,
8423 })))))),
8424 None,
8425 None)),
8426 b"...",
8427 []
8428 }
8429 }
8430 Err => {
8431 b"zzz" => Error::UnexpectedText,
8432 b"" => Error::UnexpectedEnd,
8433 }
8434 }
8435 });
8436 }
8437
8438 #[test]
8439 fn parse_unscoped_template_name_handle() {
8440 assert_parse!(UnscopedTemplateNameHandle {
8441 with subs [
8442 Substitutable::UnscopedTemplateName(
8443 UnscopedTemplateName(
8444 UnscopedName::Unqualified(
8445 UnqualifiedName::Operator(
8446 OperatorName::Simple(
8447 SimpleOperatorName::New))))),
8448 ] => {
8449 Ok => {
8450 b"S_..." => {
8451 UnscopedTemplateNameHandle::BackReference(0),
8452 b"...",
8453 []
8454 }
8455 b"dl..." => {
8456 UnscopedTemplateNameHandle::BackReference(1),
8457 b"...",
8458 [
8459 Substitutable::UnscopedTemplateName(
8460 UnscopedTemplateName(
8461 UnscopedName::Unqualified(
8462 UnqualifiedName::Operator(
8463 OperatorName::Simple(
8464 SimpleOperatorName::Delete)))))
8465 ]
8466 }
8467 }
8468 Err => {
8469 b"zzzz" => Error::UnexpectedText,
8470 b"" => Error::UnexpectedEnd,
8471 }
8472 }
8473 });
8474 }
8475
8476 #[test]
8477 fn parse_nested_name() {
8478 assert_parse!(NestedName {
8481 with subs [
8482 Substitutable::Prefix(
8483 Prefix::Unqualified(
8484 UnqualifiedName::Operator(
8485 OperatorName::Simple(
8486 SimpleOperatorName::New)))),
8487 ] => {
8488 Ok => {
8489 b"NKOS_3abcE..." => {
8490 NestedName::Unqualified(
8491 CvQualifiers {
8492 restrict: false,
8493 volatile: false,
8494 const_: true,
8495 },
8496 Some(RefQualifier::RValueRef),
8497 PrefixHandle::BackReference(0),
8498 UnqualifiedName::Source(
8499 SourceName(Identifier {
8500 start: 6,
8501 end: 9,
8502 }))),
8503 b"...",
8504 []
8505 }
8506 b"NOS_3abcE..." => {
8507 NestedName::Unqualified(
8508 CvQualifiers {
8509 restrict: false,
8510 volatile: false,
8511 const_: false,
8512 },
8513 Some(RefQualifier::RValueRef),
8514 PrefixHandle::BackReference(0),
8515 UnqualifiedName::Source(
8516 SourceName(Identifier {
8517 start: 5,
8518 end: 8,
8519 }))),
8520 b"...",
8521 []
8522 }
8523 b"NS_3abcE..." => {
8524 NestedName::Unqualified(
8525 CvQualifiers {
8526 restrict: false,
8527 volatile: false,
8528 const_: false,
8529 },
8530 None,
8531 PrefixHandle::BackReference(0),
8532 UnqualifiedName::Source(
8533 SourceName(Identifier {
8534 start: 4,
8535 end: 7,
8536 }))),
8537 b"...",
8538 []
8539 }
8540 b"NKOS_3abcIJEEE..." => {
8541 NestedName::Template(
8542 CvQualifiers {
8543 restrict: false,
8544 volatile: false,
8545 const_: true,
8546 },
8547 Some(RefQualifier::RValueRef),
8548 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8549 b"...",
8550 [
8551 Substitutable::Prefix(
8552 Prefix::Nested(
8553 PrefixHandle::BackReference(0),
8554 UnqualifiedName::Source(
8555 SourceName(Identifier {
8556 start: 6,
8557 end: 9,
8558 })))),
8559 ]
8560 }
8561 b"NOS_3abcIJEEE..." => {
8562 NestedName::Template(
8563 CvQualifiers {
8564 restrict: false,
8565 volatile: false,
8566 const_: false,
8567 },
8568 Some(RefQualifier::RValueRef),
8569 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8570 b"...",
8571 [
8572 Substitutable::Prefix(
8573 Prefix::Nested(
8574 PrefixHandle::BackReference(0),
8575 UnqualifiedName::Source(
8576 SourceName(Identifier {
8577 start: 5,
8578 end: 8,
8579 })))),
8580 ]
8581 }
8582 b"NS_3abcIJEEE..." => {
8583 NestedName::Template(
8584 CvQualifiers {
8585 restrict: false,
8586 volatile: false,
8587 const_: false,
8588 },
8589 None,
8590 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8591 b"...",
8592 [
8593 Substitutable::Prefix(
8594 Prefix::Nested(
8595 PrefixHandle::BackReference(0),
8596 UnqualifiedName::Source(
8597 SourceName(Identifier {
8598 start: 4,
8599 end: 7,
8600 })))),
8601 ]
8602 }
8603 }
8604 Err => {
8605 b"NS_E..." => Error::UnexpectedText,
8607 b"NS_DttrEE..." => Error::UnexpectedText,
8608
8609 b"zzz" => Error::UnexpectedText,
8610 b"Nzzz" => Error::UnexpectedText,
8611 b"NKzzz" => Error::UnexpectedText,
8612 b"NKOzzz" => Error::UnexpectedText,
8613 b"NKO3abczzz" => Error::UnexpectedText,
8614 b"NKO3abc3abczzz" => Error::UnexpectedText,
8615 b"" => Error::UnexpectedEnd,
8616 b"N" => Error::UnexpectedEnd,
8617 b"NK" => Error::UnexpectedEnd,
8618 b"NKO" => Error::UnexpectedEnd,
8619 b"NKO3abc" => Error::UnexpectedEnd,
8620 b"NKO3abc3abc" => Error::UnexpectedEnd,
8621 }
8622 }
8623 });
8624 }
8625
8626 #[test]
8627 fn parse_prefix_handle() {
8628 assert_parse!(PrefixHandle {
8636 with subs [
8637 Substitutable::Prefix(
8638 Prefix::Unqualified(
8639 UnqualifiedName::Operator(
8640 OperatorName::Simple(
8641 SimpleOperatorName::New)))),
8642 ] => {
8643 Ok => {
8644 b"3foo..." => {
8645 PrefixHandle::BackReference(1),
8646 b"...",
8647 [
8648 Substitutable::Prefix(
8649 Prefix::Unqualified(
8650 UnqualifiedName::Source(
8651 SourceName(Identifier {
8652 start: 1,
8653 end: 4,
8654 }))))
8655 ]
8656 }
8657 b"3abc3def..." => {
8658 PrefixHandle::BackReference(2),
8659 b"...",
8660 [
8661 Substitutable::Prefix(
8662 Prefix::Unqualified(
8663 UnqualifiedName::Source(
8664 SourceName(Identifier {
8665 start: 1,
8666 end: 4,
8667 })))),
8668 Substitutable::Prefix(
8669 Prefix::Nested(
8670 PrefixHandle::BackReference(1),
8671 UnqualifiedName::Source(
8672 SourceName(Identifier {
8673 start: 5,
8674 end: 8,
8675 })))),
8676 ]
8677 }
8678 b"3fooIJEE..." => {
8679 PrefixHandle::BackReference(2),
8680 b"...",
8681 [
8682 Substitutable::Prefix(
8683 Prefix::Unqualified(
8684 UnqualifiedName::Source(
8685 SourceName(Identifier {
8686 start: 1,
8687 end: 4,
8688 })))),
8689 Substitutable::Prefix(
8690 Prefix::Template(PrefixHandle::BackReference(1),
8691 TemplateArgs(vec![
8692 TemplateArg::ArgPack(vec![]),
8693 ])))
8694 ]
8695 }
8696 b"T_..." => {
8697 PrefixHandle::BackReference(1),
8698 b"...",
8699 [
8700 Substitutable::Prefix(Prefix::TemplateParam(TemplateParam(0))),
8701 ]
8702 }
8703 b"DTtrE..." => {
8704 PrefixHandle::BackReference(1),
8705 b"...",
8706 [
8707 Substitutable::Prefix(
8708 Prefix::Decltype(
8709 Decltype::Expression(Expression::Rethrow))),
8710 ]
8711 }
8712 b"3abc3defM..." => {
8713 PrefixHandle::BackReference(2),
8714 b"...",
8715 [
8716 Substitutable::Prefix(
8717 Prefix::Unqualified(
8718 UnqualifiedName::Source(
8719 SourceName(Identifier {
8720 start: 1,
8721 end: 4,
8722 })))),
8723 Substitutable::Prefix(
8724 Prefix::DataMember(
8725 PrefixHandle::BackReference(1),
8726 DataMemberPrefix(
8727 SourceName(Identifier {
8728 start: 5,
8729 end: 8,
8730 })))),
8731 ]
8732 }
8733 b"S_..." => {
8734 PrefixHandle::BackReference(0),
8735 b"...",
8736 []
8737 }
8738 b"3abc3defE..." => {
8740 PrefixHandle::NonSubstitution(NonSubstitution(0)),
8741 b"E...",
8742 [
8743 Substitutable::Prefix(
8744 Prefix::Unqualified(
8745 UnqualifiedName::Source(
8746 SourceName(Identifier {
8747 start: 1,
8748 end: 4,
8749 })))),
8750 ]
8751 }
8752 }
8753 Err => {
8754 b"zzz" => Error::UnexpectedText,
8755 b"" => Error::UnexpectedEnd,
8756 }
8757 }
8758 });
8759 }
8760
8761 #[test]
8762 fn parse_type_handle() {
8763 assert_parse!(TypeHandle {
8764 with subs [
8765 Substitutable::Type(
8766 Type::PointerTo(
8767 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8768 ] => {
8769 Ok => {
8770 b"S_..." => {
8771 TypeHandle::BackReference(0),
8772 b"...",
8773 []
8774 }
8775 b"c..." => {
8776 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
8777 b"...",
8778 []
8779 }
8780 b"FS_E..." => {
8781 TypeHandle::BackReference(1),
8782 b"...",
8783 [
8784 Substitutable::Type(
8785 Type::Function(FunctionType {
8786 cv_qualifiers: CvQualifiers {
8787 restrict: false,
8788 volatile: false,
8789 const_: false,
8790 },
8791 exception_spec: None,
8792 transaction_safe: false,
8793 extern_c: false,
8794 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
8795 ref_qualifier: None,
8796 })),
8797 ]
8798 }
8799 b"A_S_..." => {
8800 TypeHandle::BackReference(1),
8801 b"...",
8802 [
8803 Substitutable::Type(
8804 Type::Array(ArrayType::NoDimension(TypeHandle::BackReference(0)))),
8805 ]
8806 }
8807 b"MS_S_..." => {
8808 TypeHandle::BackReference(1),
8809 b"...",
8810 [
8811 Substitutable::Type(
8812 Type::PointerToMember(
8813 PointerToMemberType(TypeHandle::BackReference(0),
8814 TypeHandle::BackReference(0)))),
8815 ]
8816 }
8817 b"T_..." => {
8818 TypeHandle::BackReference(1),
8819 b"...",
8820 [
8821 Substitutable::Type(Type::TemplateParam(TemplateParam(0))),
8822 ]
8823 }
8824 b"T_IS_E..." => {
8825 TypeHandle::BackReference(2),
8826 b"...",
8827 [
8828 Substitutable::TemplateTemplateParam(
8829 TemplateTemplateParam(TemplateParam(0))),
8830 Substitutable::Type(
8831 Type::TemplateTemplate(
8832 TemplateTemplateParamHandle::BackReference(1),
8833 TemplateArgs(vec![
8834 TemplateArg::Type(TypeHandle::BackReference(0))
8835 ]))),
8836 ]
8837 }
8838 b"DTtrE..." => {
8839 TypeHandle::BackReference(1),
8840 b"...",
8841 [
8842 Substitutable::Type(
8843 Type::Decltype(Decltype::Expression(Expression::Rethrow))),
8844 ]
8845 }
8846 b"KS_..." => {
8847 TypeHandle::BackReference(1),
8848 b"...",
8849 [
8850 Substitutable::Type(Type::Qualified(CvQualifiers {
8851 restrict: false,
8852 volatile: false,
8853 const_: true,
8854 }, TypeHandle::BackReference(0)))
8855 ]
8856 }
8857 b"PS_..." => {
8858 TypeHandle::BackReference(1),
8859 b"...",
8860 [
8861 Substitutable::Type(Type::PointerTo(TypeHandle::BackReference(0)))
8862 ]
8863 }
8864 b"RS_..." => {
8865 TypeHandle::BackReference(1),
8866 b"...",
8867 [
8868 Substitutable::Type(Type::LvalueRef(TypeHandle::BackReference(0)))
8869 ]
8870 }
8871 b"OS_..." => {
8872 TypeHandle::BackReference(1),
8873 b"...",
8874 [
8875 Substitutable::Type(Type::RvalueRef(TypeHandle::BackReference(0)))
8876 ]
8877 }
8878 b"CS_..." => {
8879 TypeHandle::BackReference(1),
8880 b"...",
8881 [
8882 Substitutable::Type(Type::Complex(TypeHandle::BackReference(0)))
8883 ]
8884 }
8885 b"GS_..." => {
8886 TypeHandle::BackReference(1),
8887 b"...",
8888 [
8889 Substitutable::Type(Type::Imaginary(TypeHandle::BackReference(0)))
8890 ]
8891 }
8892 b"U3abcS_..." => {
8893 TypeHandle::BackReference(1),
8894 b"...",
8895 [
8896 Substitutable::Type(
8897 Type::VendorExtension(
8898 SourceName(Identifier {
8899 start: 2,
8900 end: 5,
8901 }),
8902 None,
8903 TypeHandle::BackReference(0)))
8904 ]
8905 }
8906 b"U3abcIS_ES_..." => {
8907 TypeHandle::BackReference(1),
8908 b"...",
8909 [
8910 Substitutable::Type(
8911 Type::VendorExtension(
8912 SourceName(Identifier {
8913 start: 2,
8914 end: 5,
8915 }),
8916 Some(TemplateArgs(vec![
8917 TemplateArg::Type(TypeHandle::BackReference(0))
8918 ])),
8919 TypeHandle::BackReference(0)))
8920 ]
8921 }
8922 b"DpS_..." => {
8923 TypeHandle::BackReference(1),
8924 b"...",
8925 [
8926 Substitutable::Type(
8927 Type::PackExpansion(TypeHandle::BackReference(0))),
8928 ]
8929 }
8930 b"3abc..." => {
8931 TypeHandle::BackReference(1),
8932 b"...",
8933 [
8934 Substitutable::Type(
8935 Type::ClassEnum(
8936 ClassEnumType::Named(
8937 Name::Unscoped(
8938 UnscopedName::Unqualified(
8939 UnqualifiedName::Source(
8940 SourceName(Identifier {
8941 start: 1,
8942 end: 4,
8943 })))))))
8944 ]
8945 }
8946 }
8947 Err => {
8948 b"P" => Error::UnexpectedEnd,
8949 b"R" => Error::UnexpectedEnd,
8950 b"O" => Error::UnexpectedEnd,
8951 b"C" => Error::UnexpectedEnd,
8952 b"G" => Error::UnexpectedEnd,
8953 b"Dp" => Error::UnexpectedEnd,
8954 b"D" => Error::UnexpectedEnd,
8955 b"P" => Error::UnexpectedEnd,
8956 b"" => Error::UnexpectedEnd,
8957 }
8958 }
8959 });
8960 }
8961
8962 #[test]
8963 fn parse_exception_spec() {
8964 assert_parse!(ExceptionSpec {
8965 Ok => {
8966 b"Do..." => {
8967 ExceptionSpec::NoExcept,
8968 b"..."
8969 }
8970 b"DOtrE..." => {
8971 ExceptionSpec::Computed(Expression::Rethrow),
8972 b"..."
8973 }
8974 }
8975 Err => {
8976 b"DOtre" => Error::UnexpectedText,
8977 b"DOE" => Error::UnexpectedText,
8978 b"D" => Error::UnexpectedEnd,
8979 b"" => Error::UnexpectedEnd,
8980 }
8981 });
8982 }
8983
8984 #[test]
8985 fn parse_function_type() {
8986 assert_parse!(FunctionType {
8987 with subs [
8988 Substitutable::Type(
8989 Type::PointerTo(
8990 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
8991 ] => {
8992 Ok => {
8993 b"KDxFYS_RE..." => {
8994 FunctionType {
8995 cv_qualifiers: CvQualifiers {
8996 restrict: false,
8997 volatile: false,
8998 const_: true,
8999 },
9000 exception_spec: None,
9001 transaction_safe: true,
9002 extern_c: true,
9003 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9004 ref_qualifier: Some(RefQualifier::LValueRef),
9005 },
9006 b"...",
9007 []
9008 }
9009 b"DxFYS_RE..." => {
9010 FunctionType {
9011 cv_qualifiers: CvQualifiers {
9012 restrict: false,
9013 volatile: false,
9014 const_: false,
9015 },
9016 exception_spec: None,
9017 transaction_safe: true,
9018 extern_c: true,
9019 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9020 ref_qualifier: Some(RefQualifier::LValueRef),
9021 },
9022 b"...",
9023 []
9024 }
9025 b"FYS_RE..." => {
9026 FunctionType {
9027 cv_qualifiers: CvQualifiers {
9028 restrict: false,
9029 volatile: false,
9030 const_: false,
9031 },
9032 exception_spec: None,
9033 transaction_safe: false,
9034 extern_c: true,
9035 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9036 ref_qualifier: Some(RefQualifier::LValueRef),
9037 },
9038 b"...",
9039 []
9040 }
9041 b"FS_RE..." => {
9042 FunctionType {
9043 cv_qualifiers: CvQualifiers {
9044 restrict: false,
9045 volatile: false,
9046 const_: false,
9047 },
9048 exception_spec: None,
9049 transaction_safe: false,
9050 extern_c: false,
9051 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9052 ref_qualifier: Some(RefQualifier::LValueRef),
9053 },
9054 b"...",
9055 []
9056 }
9057 b"FS_E..." => {
9058 FunctionType {
9059 cv_qualifiers: CvQualifiers {
9060 restrict: false,
9061 volatile: false,
9062 const_: false,
9063 },
9064 exception_spec: None,
9065 transaction_safe: false,
9066 extern_c: false,
9067 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9068 ref_qualifier: None,
9069 },
9070 b"...",
9071 []
9072 }
9073 }
9074 Err => {
9075 b"DFYS_E" => Error::UnexpectedText,
9076 b"KKFS_E" => Error::UnexpectedText,
9077 b"FYS_..." => Error::UnexpectedText,
9078 b"FYS_" => Error::UnexpectedEnd,
9079 b"F" => Error::UnexpectedEnd,
9080 b"" => Error::UnexpectedEnd,
9081 }
9082 }
9083 });
9084 }
9085
9086 #[test]
9087 fn parse_bare_function_type() {
9088 assert_parse!(BareFunctionType {
9089 with subs [
9090 Substitutable::Type(
9091 Type::PointerTo(
9092 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9093 ] => {
9094 Ok => {
9095 b"S_S_..." => {
9096 BareFunctionType(vec![
9097 TypeHandle::BackReference(0),
9098 TypeHandle::BackReference(0),
9099 ]),
9100 b"...",
9101 []
9102 }
9103 }
9104 Err => {
9105 b"" => Error::UnexpectedEnd,
9106 }
9107 }
9108 });
9109 }
9110
9111 #[test]
9112 fn parse_decltype() {
9113 assert_parse!(Decltype {
9114 Ok => {
9115 b"DTtrE..." => {
9116 Decltype::Expression(Expression::Rethrow),
9117 b"..."
9118 }
9119 b"DttrE..." => {
9120 Decltype::IdExpression(Expression::Rethrow),
9121 b"..."
9122 }
9123 }
9124 Err => {
9125 b"Dtrtz" => Error::UnexpectedText,
9126 b"DTrtz" => Error::UnexpectedText,
9127 b"Dz" => Error::UnexpectedText,
9128 b"Dtrt" => Error::UnexpectedText,
9129 b"DTrt" => Error::UnexpectedText,
9130 b"Dt" => Error::UnexpectedEnd,
9131 b"DT" => Error::UnexpectedEnd,
9132 b"D" => Error::UnexpectedEnd,
9133 b"" => Error::UnexpectedEnd,
9134 }
9135 });
9136 }
9137
9138 #[test]
9139 fn parse_class_enum_type() {
9140 assert_parse!(ClassEnumType {
9141 Ok => {
9142 b"3abc..." => {
9143 ClassEnumType::Named(
9144 Name::Unscoped(
9145 UnscopedName::Unqualified(
9146 UnqualifiedName::Source(
9147 SourceName(Identifier {
9148 start: 1,
9149 end: 4,
9150 }))))),
9151 b"..."
9152 }
9153 b"Ts3abc..." => {
9154 ClassEnumType::ElaboratedStruct(
9155 Name::Unscoped(
9156 UnscopedName::Unqualified(
9157 UnqualifiedName::Source(
9158 SourceName(Identifier {
9159 start: 3,
9160 end: 6,
9161 }))))),
9162 b"..."
9163 }
9164 b"Tu3abc..." => {
9165 ClassEnumType::ElaboratedUnion(
9166 Name::Unscoped(
9167 UnscopedName::Unqualified(
9168 UnqualifiedName::Source(
9169 SourceName(Identifier {
9170 start: 3,
9171 end: 6,
9172 }))))),
9173 b"..."
9174 }
9175 b"Te3abc..." => {
9176 ClassEnumType::ElaboratedEnum(
9177 Name::Unscoped(
9178 UnscopedName::Unqualified(
9179 UnqualifiedName::Source(
9180 SourceName(Identifier {
9181 start: 3,
9182 end: 6,
9183 }))))),
9184 b"..."
9185 }
9186 }
9187 Err => {
9188 b"zzz" => Error::UnexpectedText,
9189 b"Tzzz" => Error::UnexpectedText,
9190 b"T" => Error::UnexpectedEnd,
9191 b"" => Error::UnexpectedEnd,
9192 }
9193 });
9194 }
9195
9196 #[test]
9197 fn parse_array_type() {
9198 assert_parse!(ArrayType {
9199 with subs [
9200 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9201 ] => {
9202 Ok => {
9203 b"A10_S_..." => {
9204 ArrayType::DimensionNumber(10, TypeHandle::BackReference(0)),
9205 b"...",
9206 []
9207 }
9208 b"A10_Sb..." => {
9209 ArrayType::DimensionNumber(10,
9210 TypeHandle::WellKnown(
9211 WellKnownComponent::StdString1)),
9212 b"...",
9213 []
9214 }
9215 b"Atr_S_..." => {
9216 ArrayType::DimensionExpression(Expression::Rethrow,
9217 TypeHandle::BackReference(0)),
9218 b"...",
9219 []
9220 }
9221 b"A_S_..." => {
9222 ArrayType::NoDimension(TypeHandle::BackReference(0)),
9223 b"...",
9224 []
9225 }
9226 }
9227 Err => {
9228 b"A10_" => Error::UnexpectedEnd,
9229 b"A10" => Error::UnexpectedEnd,
9230 b"A" => Error::UnexpectedEnd,
9231 b"" => Error::UnexpectedEnd,
9232 b"A10_..." => Error::UnexpectedText,
9233 b"A10..." => Error::UnexpectedText,
9234 b"A..." => Error::UnexpectedText,
9235 b"..." => Error::UnexpectedText,
9236 }
9237 }
9238 });
9239 }
9240
9241 #[test]
9242 fn parse_vector_type() {
9243 assert_parse!(VectorType {
9244 with subs [
9245 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9246 ] => {
9247 Ok => {
9248 b"Dv10_S_..." => {
9249 VectorType::DimensionNumber(10, TypeHandle::BackReference(0)),
9250 b"...",
9251 []
9252 }
9253 b"Dv10_Sb..." => {
9254 VectorType::DimensionNumber(10,
9255 TypeHandle::WellKnown(
9256 WellKnownComponent::StdString1)),
9257 b"...",
9258 []
9259 }
9260 b"Dvtr_S_..." => {
9261 VectorType::DimensionExpression(Expression::Rethrow,
9262 TypeHandle::BackReference(0)),
9263 b"...",
9264 []
9265 }
9266 }
9267 Err => {
9268 b"Dq" => Error::UnexpectedText,
9269 b"Dv" => Error::UnexpectedEnd,
9270 b"Dv42_" => Error::UnexpectedEnd,
9271 b"Dv42_..." => Error::UnexpectedText,
9272 b"Dvtr_" => Error::UnexpectedEnd,
9273 b"Dvtr_..." => Error::UnexpectedText,
9274 b"" => Error::UnexpectedEnd,
9275 b"..." => Error::UnexpectedText,
9276 }
9277 }
9278 });
9279 }
9280
9281 #[test]
9282 fn parse_pointer_to_member_type() {
9283 assert_parse!(PointerToMemberType {
9284 with subs [
9285 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9286 ] => {
9287 Ok => {
9288 b"MS_S_..." => {
9289 PointerToMemberType(TypeHandle::BackReference(0),
9290 TypeHandle::BackReference(0)),
9291 b"...",
9292 []
9293 }
9294 }
9295 Err => {
9296 b"MS_S" => Error::UnexpectedEnd,
9297 b"MS_" => Error::UnexpectedEnd,
9298 b"MS" => Error::UnexpectedEnd,
9299 b"M" => Error::UnexpectedEnd,
9300 b"" => Error::UnexpectedEnd,
9301 b"MS_..." => Error::UnexpectedText,
9302 b"M..." => Error::UnexpectedText,
9303 b"..." => Error::UnexpectedText,
9304 }
9305 }
9306 });
9307 }
9308
9309 #[test]
9310 fn parse_template_template_param_handle() {
9311 assert_parse!(TemplateTemplateParamHandle {
9312 with subs [
9313 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(0)))
9314 ] => {
9315 Ok => {
9316 b"S_..." => {
9317 TemplateTemplateParamHandle::BackReference(0),
9318 b"...",
9319 []
9320 }
9321 b"T1_..." => {
9322 TemplateTemplateParamHandle::BackReference(1),
9323 b"...",
9324 [
9325 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(2)))
9326 ]
9327 }
9328 }
9329 Err => {
9330 b"S" => Error::UnexpectedText,
9331 b"T" => Error::UnexpectedEnd,
9332 b"" => Error::UnexpectedEnd,
9333 b"S..." => Error::UnexpectedText,
9334 b"T..." => Error::UnexpectedText,
9335 b"..." => Error::UnexpectedText,
9336 }
9337 }
9338 });
9339 }
9340
9341 #[test]
9342 fn parse_template_args() {
9343 assert_parse!(TemplateArgs {
9344 with subs [
9345 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9346 ] => {
9347 Ok => {
9348 b"IS_E..." => {
9349 TemplateArgs(vec![TemplateArg::Type(TypeHandle::BackReference(0))]),
9350 b"...",
9351 []
9352 }
9353 b"IS_S_S_S_E..." => {
9354 TemplateArgs(vec![
9355 TemplateArg::Type(TypeHandle::BackReference(0)),
9356 TemplateArg::Type(TypeHandle::BackReference(0)),
9357 TemplateArg::Type(TypeHandle::BackReference(0)),
9358 TemplateArg::Type(TypeHandle::BackReference(0)),
9359 ]),
9360 b"...",
9361 []
9362 }
9363 }
9364 Err => {
9365 b"zzz" => Error::UnexpectedText,
9366 b"IE" => Error::UnexpectedText,
9367 b"IS_" => Error::UnexpectedEnd,
9368 b"I" => Error::UnexpectedEnd,
9369 b"" => Error::UnexpectedEnd,
9370 }
9371 }
9372 });
9373 }
9374
9375 #[test]
9376 fn parse_template_arg() {
9377 assert_parse!(TemplateArg {
9378 with subs [
9379 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9380 ] => {
9381 Ok => {
9382 b"S_..." => {
9383 TemplateArg::Type(TypeHandle::BackReference(0)),
9384 b"...",
9385 []
9386 }
9387 b"XtrE..." => {
9388 TemplateArg::Expression(Expression::Rethrow),
9389 b"...",
9390 []
9391 }
9392 b"XsrS_1QE..." => {
9393 TemplateArg::Expression(
9394 Expression::UnresolvedName(
9395 UnresolvedName::Nested1(
9396 UnresolvedTypeHandle::BackReference(0),
9397 vec![],
9398 BaseUnresolvedName::Name(
9399 SimpleId(
9400 SourceName(Identifier {
9401 start: 6,
9402 end: 7
9403 }),
9404 None
9405 )
9406 )
9407 )
9408 )
9409 ),
9410 b"...",
9411 []
9412 }
9413 b"XsrS_1QIlEE..." => {
9414 TemplateArg::Expression(
9415 Expression::UnresolvedName(
9416 UnresolvedName::Nested1(
9417 UnresolvedTypeHandle::BackReference(0),
9418 vec![],
9419 BaseUnresolvedName::Name(
9420 SimpleId(
9421 SourceName(Identifier {
9422 start: 6,
9423 end: 7
9424 }),
9425 Some(
9426 TemplateArgs(
9427 vec![
9428 TemplateArg::Type(
9429 TypeHandle::Builtin(
9430 BuiltinType::Standard(
9431 StandardBuiltinType::Long
9432 )
9433 )
9434 )
9435 ]
9436 )
9437 )
9438 )
9439 )
9440 )
9441 )
9442 ),
9443 b"...",
9444 []
9445 }
9446 b"LS_E..." => {
9447 TemplateArg::SimpleExpression(
9448 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3)),
9449 b"...",
9450 []
9451 }
9452 b"JE..." => {
9453 TemplateArg::ArgPack(vec![]),
9454 b"...",
9455 []
9456 }
9457 b"JS_XtrELS_EJEE..." => {
9458 TemplateArg::ArgPack(vec![
9459 TemplateArg::Type(TypeHandle::BackReference(0)),
9460 TemplateArg::Expression(Expression::Rethrow),
9461 TemplateArg::SimpleExpression(
9462 ExprPrimary::Literal(TypeHandle::BackReference(0), 10, 10)),
9463 TemplateArg::ArgPack(vec![]),
9464 ]),
9465 b"...",
9466 []
9467 }
9468 }
9469 Err => {
9470 b"..." => Error::UnexpectedText,
9471 b"X..." => Error::UnexpectedText,
9472 b"J..." => Error::UnexpectedText,
9473 b"JS_..." => Error::UnexpectedText,
9474 b"JS_" => Error::UnexpectedEnd,
9475 b"X" => Error::UnexpectedEnd,
9476 b"J" => Error::UnexpectedEnd,
9477 b"" => Error::UnexpectedEnd,
9478 }
9479 }
9480 });
9481 }
9482
9483 #[test]
9484 fn parse_expression() {
9485 assert_parse!(Expression {
9486 with subs [
9487 Substitutable::Type(
9488 Type::PointerTo(TypeHandle::Builtin(
9489 BuiltinType::Standard(StandardBuiltinType::Int)))),
9490 ] => {
9491 Ok => {
9492 b"psLS_1E..." => {
9493 Expression::Unary(OperatorName::Simple(SimpleOperatorName::UnaryPlus),
9494 Box::new(Expression::Primary(
9495 ExprPrimary::Literal(
9496 TypeHandle::BackReference(0),
9497 5,
9498 6)))),
9499 b"...",
9500 []
9501 }
9502 b"rsLS_1ELS_1E..." => {
9503 Expression::Binary(OperatorName::Simple(SimpleOperatorName::Shr),
9504 Box::new(Expression::Primary(
9505 ExprPrimary::Literal(
9506 TypeHandle::BackReference(0),
9507 5,
9508 6))),
9509 Box::new(Expression::Primary(
9510 ExprPrimary::Literal(
9511 TypeHandle::BackReference(0),
9512 10,
9513 11)))),
9514 b"...",
9515 []
9516 }
9517 b"quLS_1ELS_2ELS_3E..." => {
9518 Expression::Ternary(OperatorName::Simple(SimpleOperatorName::Question),
9519 Box::new(Expression::Primary(
9520 ExprPrimary::Literal(
9521 TypeHandle::BackReference(0),
9522 5,
9523 6))),
9524 Box::new(Expression::Primary(
9525 ExprPrimary::Literal(
9526 TypeHandle::BackReference(0),
9527 10,
9528 11))),
9529 Box::new(Expression::Primary(
9530 ExprPrimary::Literal(
9531 TypeHandle::BackReference(0),
9532 15,
9533 16)))),
9534 b"...",
9535 []
9536 }
9537 b"pp_LS_1E..." => {
9538 Expression::PrefixInc(
9539 Box::new(Expression::Primary(
9540 ExprPrimary::Literal(
9541 TypeHandle::BackReference(0),
9542 6,
9543 7)))),
9544 b"...",
9545 []
9546 }
9547 b"mm_LS_1E..." => {
9548 Expression::PrefixDec(
9549 Box::new(Expression::Primary(
9550 ExprPrimary::Literal(
9551 TypeHandle::BackReference(0),
9552 6,
9553 7)))),
9554 b"...",
9555 []
9556 }
9557 b"clLS_1EE..." => {
9558 Expression::Call(
9559 Box::new(Expression::Primary(
9560 ExprPrimary::Literal(
9561 TypeHandle::BackReference(0),
9562 5,
9563 6))),
9564 vec![]),
9565 b"...",
9566 []
9567 }
9568 b"cvS_LS_1E..." => {
9570 Expression::ConversionOne(
9571 TypeHandle::BackReference(0),
9572 Box::new(Expression::Primary(
9573 ExprPrimary::Literal(
9574 TypeHandle::BackReference(0),
9575 7,
9576 8)))),
9577 b"...",
9578 []
9579 }
9580 b"cvS__LS_1ELS_1EE..." => {
9581 Expression::ConversionMany(
9582 TypeHandle::BackReference(0),
9583 vec![
9584 Expression::Primary(
9585 ExprPrimary::Literal(
9586 TypeHandle::BackReference(0),
9587 8,
9588 9)),
9589 Expression::Primary(
9590 ExprPrimary::Literal(
9591 TypeHandle::BackReference(0),
9592 13,
9593 14)),
9594 ]),
9595 b"...",
9596 []
9597 }
9598 b"tlS_LS_1ELS_1EE..." => {
9599 Expression::ConversionBraced(
9600 TypeHandle::BackReference(0),
9601 vec![
9602 Expression::Primary(
9603 ExprPrimary::Literal(
9604 TypeHandle::BackReference(0),
9605 7,
9606 8)),
9607 Expression::Primary(
9608 ExprPrimary::Literal(
9609 TypeHandle::BackReference(0),
9610 12,
9611 13)),
9612 ]),
9613 b"...",
9614 []
9615 }
9616 b"ilLS_1EE..." => {
9617 Expression::BracedInitList(
9618 Box::new(Expression::Primary(
9619 ExprPrimary::Literal(
9620 TypeHandle::BackReference(0),
9621 5,
9622 6)))),
9623 b"...",
9624 []
9625 }
9626 b"gsnwLS_1E_S_E..." => {
9627 Expression::GlobalNew(
9628 vec![
9629 Expression::Primary(
9630 ExprPrimary::Literal(
9631 TypeHandle::BackReference(0),
9632 7,
9633 8))
9634 ],
9635 TypeHandle::BackReference(0),
9636 None),
9637 b"...",
9638 []
9639 }
9640 b"nwLS_1E_S_E..." => {
9641 Expression::New(
9642 vec![
9643 Expression::Primary(
9644 ExprPrimary::Literal(
9645 TypeHandle::BackReference(0),
9646 5,
9647 6))
9648 ],
9649 TypeHandle::BackReference(0),
9650 None),
9651 b"...",
9652 []
9653 }
9654 b"gsnwLS_1E_S_piE..." => {
9655 Expression::GlobalNew(
9656 vec![
9657 Expression::Primary(
9658 ExprPrimary::Literal(
9659 TypeHandle::BackReference(0),
9660 7,
9661 8))
9662 ],
9663 TypeHandle::BackReference(0),
9664 Some(Initializer(vec![]))),
9665 b"...",
9666 []
9667 }
9668 b"nwLS_1E_S_piE..." => {
9669 Expression::New(
9670 vec![
9671 Expression::Primary(
9672 ExprPrimary::Literal(
9673 TypeHandle::BackReference(0),
9674 5,
9675 6))
9676 ],
9677 TypeHandle::BackReference(0),
9678 Some(Initializer(vec![]))),
9679 b"...",
9680 []
9681 }
9682 b"gsnaLS_1E_S_E..." => {
9683 Expression::GlobalNewArray(
9684 vec![
9685 Expression::Primary(
9686 ExprPrimary::Literal(
9687 TypeHandle::BackReference(0),
9688 7,
9689 8))
9690 ],
9691 TypeHandle::BackReference(0),
9692 None),
9693 b"...",
9694 []
9695 }
9696 b"naLS_1E_S_E..." => {
9697 Expression::NewArray(
9698 vec![
9699 Expression::Primary(
9700 ExprPrimary::Literal(
9701 TypeHandle::BackReference(0),
9702 5,
9703 6))
9704 ],
9705 TypeHandle::BackReference(0),
9706 None),
9707 b"...",
9708 []
9709 }
9710 b"gsnaLS_1E_S_piE..." => {
9711 Expression::GlobalNewArray(
9712 vec![
9713 Expression::Primary(
9714 ExprPrimary::Literal(
9715 TypeHandle::BackReference(0),
9716 7,
9717 8))
9718 ],
9719 TypeHandle::BackReference(0),
9720 Some(Initializer(vec![]))),
9721 b"...",
9722 []
9723 }
9724 b"naLS_1E_S_piE..." => {
9725 Expression::NewArray(
9726 vec![
9727 Expression::Primary(
9728 ExprPrimary::Literal(
9729 TypeHandle::BackReference(0),
9730 5,
9731 6))
9732 ],
9733 TypeHandle::BackReference(0),
9734 Some(Initializer(vec![]))),
9735 b"...",
9736 []
9737 }
9738 b"gsdlLS_1E..." => {
9739 Expression::GlobalDelete(
9740 Box::new(Expression::Primary(
9741 ExprPrimary::Literal(
9742 TypeHandle::BackReference(0),
9743 7,
9744 8)))),
9745 b"...",
9746 []
9747 }
9748 b"dlLS_1E..." => {
9749 Expression::Delete(
9750 Box::new(Expression::Primary(
9751 ExprPrimary::Literal(
9752 TypeHandle::BackReference(0),
9753 5,
9754 6)))),
9755 b"...",
9756 []
9757 }
9758 b"gsdaLS_1E..." => {
9760 Expression::GlobalDeleteArray(
9761 Box::new(Expression::Primary(
9762 ExprPrimary::Literal(
9763 TypeHandle::BackReference(0),
9764 7,
9765 8)))),
9766 b"...",
9767 []
9768 }
9769 b"daLS_1E..." => {
9770 Expression::DeleteArray(
9771 Box::new(Expression::Primary(
9772 ExprPrimary::Literal(
9773 TypeHandle::BackReference(0),
9774 5,
9775 6)))),
9776 b"...",
9777 []
9778 }
9779 b"dcS_LS_1E..." => {
9780 Expression::DynamicCast(
9781 TypeHandle::BackReference(0),
9782 Box::new(Expression::Primary(
9783 ExprPrimary::Literal(
9784 TypeHandle::BackReference(0),
9785 7,
9786 8)))),
9787 b"...",
9788 []
9789 }
9790 b"scS_LS_1E..." => {
9791 Expression::StaticCast(
9792 TypeHandle::BackReference(0),
9793 Box::new(Expression::Primary(
9794 ExprPrimary::Literal(
9795 TypeHandle::BackReference(0),
9796 7,
9797 8)))),
9798 b"...",
9799 []
9800 }
9801 b"ccS_LS_1E..." => {
9802 Expression::ConstCast(
9803 TypeHandle::BackReference(0),
9804 Box::new(Expression::Primary(
9805 ExprPrimary::Literal(
9806 TypeHandle::BackReference(0),
9807 7,
9808 8)))),
9809 b"...",
9810 []
9811 }
9812 b"rcS_LS_1E..." => {
9813 Expression::ReinterpretCast(
9814 TypeHandle::BackReference(0),
9815 Box::new(Expression::Primary(
9816 ExprPrimary::Literal(
9817 TypeHandle::BackReference(0),
9818 7,
9819 8)))),
9820 b"...",
9821 []
9822 }
9823 b"tiS_..." => {
9824 Expression::TypeidType(TypeHandle::BackReference(0)),
9825 b"...",
9826 []
9827 }
9828 b"teLS_1E..." => {
9829 Expression::TypeidExpr(
9830 Box::new(Expression::Primary(
9831 ExprPrimary::Literal(
9832 TypeHandle::BackReference(0),
9833 5,
9834 6)))),
9835 b"...",
9836 []
9837 }
9838 b"stS_..." => {
9839 Expression::SizeofType(TypeHandle::BackReference(0)),
9840 b"...",
9841 []
9842 }
9843 b"szLS_1E..." => {
9844 Expression::SizeofExpr(
9845 Box::new(Expression::Primary(
9846 ExprPrimary::Literal(
9847 TypeHandle::BackReference(0),
9848 5,
9849 6)))),
9850 b"...",
9851 []
9852 }
9853 b"atS_..." => {
9854 Expression::AlignofType(TypeHandle::BackReference(0)),
9855 b"...",
9856 []
9857 }
9858 b"azLS_1E..." => {
9859 Expression::AlignofExpr(
9860 Box::new(Expression::Primary(
9861 ExprPrimary::Literal(
9862 TypeHandle::BackReference(0),
9863 5,
9864 6)))),
9865 b"...",
9866 []
9867 }
9868 b"nxLS_1E..." => {
9869 Expression::Noexcept(
9870 Box::new(Expression::Primary(
9871 ExprPrimary::Literal(
9872 TypeHandle::BackReference(0),
9873 5,
9874 6)))),
9875 b"...",
9876 []
9877 }
9878 b"T_..." => {
9879 Expression::TemplateParam(TemplateParam(0)),
9880 b"...",
9881 []
9882 }
9883 b"fp_..." => {
9884 Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0))),
9885 b"...",
9886 []
9887 }
9888 b"dtT_3abc..." => {
9889 Expression::Member(
9890 Box::new(Expression::TemplateParam(TemplateParam(0))),
9891 MemberName(
9892 Name::Unscoped(
9893 UnscopedName::Unqualified(
9894 UnqualifiedName::Source(
9895 SourceName(
9896 Identifier {
9897 start: 5,
9898 end: 8,
9899 })))))),
9900 b"...",
9901 []
9902 }
9903 b"ptT_3abc..." => {
9904 Expression::DerefMember(
9905 Box::new(Expression::TemplateParam(TemplateParam(0))),
9906 MemberName(
9907 Name::Unscoped(
9908 UnscopedName::Unqualified(
9909 UnqualifiedName::Source(
9910 SourceName(
9911 Identifier {
9912 start: 5,
9913 end: 8,
9914 })))))),
9915 b"...",
9916 []
9917 }
9918 b"dtfp_clI3abcE..." => {
9919 Expression::Member(
9920 Box::new(Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0)))),
9921 MemberName(
9922 Name::UnscopedTemplate(
9923 UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(0)),
9924 TemplateArgs(vec![
9925 TemplateArg::Type(
9926 TypeHandle::BackReference(1))])))),
9927 b"...",
9928 [
9929 Substitutable::Type(
9930 Type::ClassEnum(
9931 ClassEnumType::Named(
9932 Name::Unscoped(
9933 UnscopedName::Unqualified(
9934 UnqualifiedName::Source(
9935 SourceName(
9936 Identifier {
9937 start: 9,
9938 end: 12
9939 })))))))
9940 ]
9941 }
9942 b"dsT_T_..." => {
9944 Expression::PointerToMember(
9945 Box::new(Expression::TemplateParam(TemplateParam(0))),
9946 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9947 b"...",
9948 []
9949 }
9950 b"sZT_..." => {
9951 Expression::SizeofTemplatePack(TemplateParam(0)),
9952 b"...",
9953 []
9954 }
9955 b"sZfp_..." => {
9956 Expression::SizeofFunctionPack(
9957 FunctionParam(0, CvQualifiers::default(), Some(0))),
9958 b"...",
9959 []
9960 }
9961 b"sPE..." => {
9962 Expression::SizeofCapturedTemplatePack(vec![]),
9963 b"...",
9964 []
9965 }
9966 b"spT_..." => {
9967 Expression::PackExpansion(
9968 Box::new(Expression::TemplateParam(TemplateParam(0)))),
9969 b"...",
9970 []
9971 }
9972 b"twT_..." => {
9973 Expression::Throw(Box::new(Expression::TemplateParam(TemplateParam(0)))),
9974 b"...",
9975 []
9976 }
9977 b"tr..." => {
9978 Expression::Rethrow,
9979 b"...",
9980 []
9981 }
9982 b"3abc..." => {
9983 Expression::UnresolvedName(
9984 UnresolvedName::Name(
9985 BaseUnresolvedName::Name(
9986 SimpleId(
9987 SourceName(Identifier {
9988 start: 1,
9989 end: 4,
9990 }),
9991 None)))),
9992 b"...",
9993 []
9994 }
9995 b"L_Z3abcE..." => {
9996 Expression::Primary(
9997 ExprPrimary::External(
9998 MangledName::Encoding(
9999 Encoding::Data(
10000 Name::Unscoped(
10001 UnscopedName::Unqualified(
10002 UnqualifiedName::Source(
10003 SourceName(Identifier {
10004 start: 4,
10005 end: 7,
10006 }))))), vec![]))),
10007 b"...",
10008 []
10009 }
10010 b"cldtdefpT4TypeadsrT_5EnterE..." => {
10012 Expression::Call(
10013 Box::new(Expression::Member(
10014 Box::new(Expression::Unary(OperatorName::Simple(SimpleOperatorName::Deref),
10015 Box::new(Expression::FunctionParam(
10016 FunctionParam(0,
10017 CvQualifiers::default(),
10018 None)
10019 ))
10020 )),
10021 MemberName(
10022 Name::Unscoped(
10023 UnscopedName::Unqualified(
10024 UnqualifiedName::Source(
10025 SourceName(Identifier {
10026 start: 10,
10027 end: 14,
10028 })))
10029 )
10030 )
10031 )),
10032 vec![Expression::Unary(OperatorName::Simple(SimpleOperatorName::AddressOf),
10033 Box::new(Expression::UnresolvedName(
10034 UnresolvedName::Nested1(
10035 UnresolvedTypeHandle::BackReference(1),
10036 vec![],
10037 BaseUnresolvedName::Name(
10038 SimpleId(
10039 SourceName(Identifier {
10040 start: 21,
10041 end: 26
10042 }
10043 ),
10044 None
10045 )
10046 )
10047 ))))]
10048 ),
10049 b"...",
10050 [
10051 Substitutable::UnresolvedType(UnresolvedType::Template(TemplateParam(0), None))
10052 ]
10053 }
10054 }
10055 Err => {
10056 b"dtStfp_clI3abcE..." => Error::UnexpectedText,
10057 }
10058 }
10059 });
10060 }
10061
10062 #[test]
10063 fn parse_unresolved_name() {
10064 assert_parse!(UnresolvedName {
10065 with subs [
10066 Substitutable::UnresolvedType(
10067 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10068 ] => {
10069 Ok => {
10070 b"gs3abc..." => {
10071 UnresolvedName::Global(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10072 start: 3,
10073 end: 6,
10074 }), None))),
10075 b"...",
10076 []
10077 }
10078 b"3abc..." => {
10079 UnresolvedName::Name(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10080 start: 1,
10081 end: 4,
10082 }), None))),
10083 b"...",
10084 []
10085 }
10086 b"srS_3abc..." => {
10087 UnresolvedName::Nested1(UnresolvedTypeHandle::BackReference(0),
10088 vec![],
10089 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10090 start: 5,
10091 end: 8,
10092 }), None))),
10093 b"...",
10094 []
10095 }
10096 b"srNS_3abc3abcE3abc..." => {
10097 UnresolvedName::Nested1(
10098 UnresolvedTypeHandle::BackReference(0),
10099 vec![
10100 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10101 start: 6,
10102 end: 9,
10103 }), None)),
10104 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10105 start: 10,
10106 end: 13,
10107 }), None)),
10108 ],
10109 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10110 start: 15,
10111 end: 18,
10112 }), None))),
10113 b"...",
10114 []
10115 }
10116 b"gssr3abcE3abc..." => {
10117 UnresolvedName::GlobalNested2(
10118 vec![
10119 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10120 start: 5,
10121 end: 8,
10122 }), None)),
10123 ],
10124 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10125 start: 10,
10126 end: 13,
10127 }), None))),
10128 b"...",
10129 []
10130 }
10131 b"sr3abcE3abc..." => {
10132 UnresolvedName::Nested2(
10133 vec![
10134 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10135 start: 3,
10136 end: 6,
10137 }), None)),
10138 ],
10139 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10140 start: 8,
10141 end: 11,
10142 }), None))),
10143 b"...",
10144 []
10145 }
10146 }
10147 Err => {
10148 b"zzzzzz" => Error::UnexpectedText,
10149 b"gszzz" => Error::UnexpectedText,
10150 b"gssrzzz" => Error::UnexpectedText,
10151 b"srNzzz" => Error::UnexpectedText,
10152 b"srzzz" => Error::UnexpectedText,
10153 b"srN3abczzzz" => Error::UnexpectedText,
10154 b"srN3abcE" => Error::UnexpectedText,
10155 b"srN3abc" => Error::UnexpectedText,
10156 b"srN" => Error::UnexpectedEnd,
10157 b"sr" => Error::UnexpectedEnd,
10158 b"gssr" => Error::UnexpectedEnd,
10159 b"gs" => Error::UnexpectedEnd,
10160 b"" => Error::UnexpectedEnd,
10161 }
10162 }
10163 });
10164 }
10165
10166 #[test]
10167 fn parse_unresolved_type_handle() {
10168 assert_parse!(UnresolvedTypeHandle {
10169 with subs [
10170 Substitutable::UnresolvedType(
10171 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10172 ] => {
10173 Ok => {
10174 b"S_..." => {
10175 UnresolvedTypeHandle::BackReference(0),
10176 b"...",
10177 []
10178 }
10179 b"T_..." => {
10180 UnresolvedTypeHandle::BackReference(1),
10181 b"...",
10182 [
10183 Substitutable::UnresolvedType(
10184 UnresolvedType::Template(TemplateParam(0), None)),
10185 ]
10186 }
10187 b"T_IS_E..." => {
10188 UnresolvedTypeHandle::BackReference(1),
10189 b"...",
10190 [
10191 Substitutable::UnresolvedType(
10192 UnresolvedType::Template(TemplateParam(0), Some(TemplateArgs(vec![
10193 TemplateArg::Type(TypeHandle::BackReference(0))
10194 ])))),
10195 ]
10196 }
10197 b"DTtrE..." => {
10198 UnresolvedTypeHandle::BackReference(1),
10199 b"...",
10200 [
10201 Substitutable::UnresolvedType(
10202 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow)))
10203 ]
10204
10205 }
10206 }
10207 Err => {
10208 b"zzzzzzz" => Error::UnexpectedText,
10209 b"" => Error::UnexpectedEnd,
10210 }
10211 }
10212 });
10213 }
10214
10215 #[test]
10216 fn parse_unresolved_qualifier_level() {
10217 assert_parse!(UnresolvedQualifierLevel {
10218 with subs [
10219 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10220 ] => {
10221 Ok => {
10222 b"3abc..." => {
10223 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10224 start: 1,
10225 end: 4,
10226 }), None)),
10227 b"...",
10228 []
10229 }
10230 b"3abcIS_E..." => {
10231 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10232 start: 1,
10233 end: 4,
10234 }), Some(TemplateArgs(vec![
10235 TemplateArg::Type(TypeHandle::BackReference(0))
10236 ])))),
10237 b"...",
10238 []
10239 }
10240 }
10241 Err => {
10242 b"zzz" => Error::UnexpectedText,
10243 b"" => Error::UnexpectedEnd,
10244 }
10245 }
10246 });
10247 }
10248
10249 #[test]
10250 fn parse_simple_id() {
10251 assert_parse!(SimpleId {
10252 with subs [
10253 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10254 ] => {
10255 Ok => {
10256 b"3abc..." => {
10257 SimpleId(SourceName(Identifier {
10258 start: 1,
10259 end: 4,
10260 }), None),
10261 b"...",
10262 []
10263 }
10264 b"3abcIS_E..." => {
10265 SimpleId(SourceName(Identifier {
10266 start: 1,
10267 end: 4,
10268 }), Some(TemplateArgs(vec![
10269 TemplateArg::Type(TypeHandle::BackReference(0))
10270 ]))),
10271 b"...",
10272 []
10273 }
10274 }
10275 Err => {
10276 b"zzz" => Error::UnexpectedText,
10277 b"" => Error::UnexpectedEnd,
10278 }
10279 }
10280 });
10281 }
10282
10283 #[test]
10284 fn parse_base_unresolved_name() {
10285 assert_parse!(BaseUnresolvedName {
10286 with subs [
10287 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10288 ] => {
10289 Ok => {
10290 b"3abc..." => {
10291 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10292 start: 1,
10293 end: 4,
10294 }), None)),
10295 b"...",
10296 []
10297 }
10298 b"onnw..." => {
10299 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New), None),
10300 b"...",
10301 []
10302 }
10303 b"onnwIS_E..." => {
10304 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
10305 Some(TemplateArgs(vec![
10306 TemplateArg::Type(TypeHandle::BackReference(0))
10307 ]))),
10308 b"...",
10309 []
10310 }
10311 b"dn3abc..." => {
10312 BaseUnresolvedName::Destructor(DestructorName::Name(SimpleId(SourceName(Identifier {
10313 start: 3,
10314 end: 6,
10315 }), None))),
10316 b"...",
10317 []
10318 }
10319 }
10320 Err => {
10321 b"ozzz" => Error::UnexpectedText,
10322 b"dzzz" => Error::UnexpectedText,
10323 b"dn" => Error::UnexpectedEnd,
10324 b"on" => Error::UnexpectedEnd,
10325 b"" => Error::UnexpectedEnd,
10326 }
10327 }
10328 });
10329 }
10330
10331 #[test]
10332 fn parse_destructor_name() {
10333 assert_parse!(DestructorName {
10334 with subs [
10335 Substitutable::UnresolvedType(
10336 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10337 ] => {
10338 Ok => {
10339 b"S_..." => {
10340 DestructorName::Unresolved(UnresolvedTypeHandle::BackReference(0)),
10341 b"...",
10342 []
10343 }
10344 b"3abc..." => {
10345 DestructorName::Name(SimpleId(SourceName(Identifier {
10346 start: 1,
10347 end: 4,
10348 }), None)),
10349 b"...",
10350 []
10351 }
10352 }
10353 Err => {
10354 b"zzz" => Error::UnexpectedText,
10355 b"" => Error::UnexpectedEnd,
10356 }
10357 }
10358 });
10359 }
10360
10361 #[test]
10362 fn parse_expr_primary() {
10363 assert_parse!(ExprPrimary {
10364 with subs [
10365 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10366 ] => {
10367 Ok => {
10368 b"LS_12345E..." => {
10369 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 8),
10370 b"...",
10371 []
10372 }
10373 b"LS_E..." => {
10374 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3),
10375 b"...",
10376 []
10377 }
10378 b"L_Z3abcE..." => {
10379 ExprPrimary::External(
10380 MangledName::Encoding(
10381 Encoding::Data(
10382 Name::Unscoped(
10383 UnscopedName::Unqualified(
10384 UnqualifiedName::Source(
10385 SourceName(Identifier {
10386 start: 4,
10387 end: 7,
10388 }))))), vec![])),
10389 b"...",
10390 []
10391 }
10392 }
10393 Err => {
10394 b"zzz" => Error::UnexpectedText,
10395 b"LS_zzz" => Error::UnexpectedEnd,
10396 b"LS_12345" => Error::UnexpectedEnd,
10397 b"LS_" => Error::UnexpectedEnd,
10398 b"L" => Error::UnexpectedEnd,
10399 b"" => Error::UnexpectedEnd,
10400 }
10401 }
10402 });
10403 }
10404
10405 #[test]
10406 fn parse_initializer() {
10407 assert_parse!(Initializer {
10408 Ok => {
10409 b"piE..." => {
10410 Initializer(vec![]),
10411 b"..."
10412 }
10413 b"pitrtrtrE..." => {
10414 Initializer(vec![
10415 Expression::Rethrow,
10416 Expression::Rethrow,
10417 Expression::Rethrow,
10418 ]),
10419 b"..."
10420 }
10421 }
10422 Err => {
10423 b"pirtrtrt..." => Error::UnexpectedText,
10424 b"pi..." => Error::UnexpectedText,
10425 b"..." => Error::UnexpectedText,
10426 b"pirt" => Error::UnexpectedText,
10427 b"pi" => Error::UnexpectedEnd,
10428 b"p" => Error::UnexpectedEnd,
10429 b"" => Error::UnexpectedEnd,
10430 }
10431 });
10432 }
10433
10434 #[test]
10435 fn parse_local_name() {
10436 assert_parse!(LocalName {
10437 Ok => {
10438 b"Z3abcE3def_0..." => {
10439 LocalName::Relative(
10440 Box::new(Encoding::Data(
10441 Name::Unscoped(
10442 UnscopedName::Unqualified(
10443 UnqualifiedName::Source(
10444 SourceName(Identifier {
10445 start: 2,
10446 end: 5,
10447 })))))),
10448 Some(Box::new(Name::Unscoped(
10449 UnscopedName::Unqualified(
10450 UnqualifiedName::Source(
10451 SourceName(Identifier {
10452 start: 7,
10453 end: 10,
10454 })))))),
10455 Some(Discriminator(0))),
10456 b"..."
10457 }
10458 b"Z3abcE3def..." => {
10459 LocalName::Relative(
10460 Box::new(Encoding::Data(
10461 Name::Unscoped(
10462 UnscopedName::Unqualified(
10463 UnqualifiedName::Source(
10464 SourceName(Identifier {
10465 start: 2,
10466 end: 5,
10467 })))))),
10468 Some(Box::new(Name::Unscoped(
10469 UnscopedName::Unqualified(
10470 UnqualifiedName::Source(
10471 SourceName(Identifier {
10472 start: 7,
10473 end: 10,
10474 })))))),
10475 None),
10476 b"..."
10477 }
10478 b"Z3abcEs_0..." => {
10479 LocalName::Relative(
10480 Box::new(Encoding::Data(
10481 Name::Unscoped(
10482 UnscopedName::Unqualified(
10483 UnqualifiedName::Source(
10484 SourceName(Identifier {
10485 start: 2,
10486 end: 5,
10487 })))))),
10488 None,
10489 Some(Discriminator(0))),
10490 b"..."
10491 }
10492 b"Z3abcEs..." => {
10493 LocalName::Relative(
10494 Box::new(Encoding::Data(
10495 Name::Unscoped(
10496 UnscopedName::Unqualified(
10497 UnqualifiedName::Source(
10498 SourceName(Identifier {
10499 start: 2,
10500 end: 5,
10501 })))))),
10502 None,
10503 None),
10504 b"..."
10505 }
10506 b"Z3abcEd1_3abc..." => {
10507 LocalName::Default(
10508 Box::new(Encoding::Data(
10509 Name::Unscoped(
10510 UnscopedName::Unqualified(
10511 UnqualifiedName::Source(
10512 SourceName(Identifier {
10513 start: 2,
10514 end: 5,
10515 })))))),
10516 Some(1),
10517 Box::new(Name::Unscoped(
10518 UnscopedName::Unqualified(
10519 UnqualifiedName::Source(
10520 SourceName(Identifier {
10521 start: 10,
10522 end: 13,
10523 })))))),
10524 b"..."
10525 }
10526 b"Z3abcEd_3abc..." => {
10527 LocalName::Default(
10528 Box::new(Encoding::Data(
10529 Name::Unscoped(
10530 UnscopedName::Unqualified(
10531 UnqualifiedName::Source(
10532 SourceName(Identifier {
10533 start: 2,
10534 end: 5,
10535 })))))),
10536 None,
10537 Box::new(Name::Unscoped(
10538 UnscopedName::Unqualified(
10539 UnqualifiedName::Source(
10540 SourceName(Identifier {
10541 start: 9,
10542 end: 12,
10543 })))))),
10544 b"..."
10545 }
10546 }
10547 Err => {
10548 b"A" => Error::UnexpectedText,
10549 b"Z1a" => Error::UnexpectedEnd,
10550 b"Z1aE" => Error::UnexpectedEnd,
10551 b"Z" => Error::UnexpectedEnd,
10552 b"" => Error::UnexpectedEnd,
10553 }
10554 });
10555 }
10556
10557 #[test]
10558 fn parse_closure_type_name() {
10559 assert_parse!(ClosureTypeName {
10560 Ok => {
10561 b"UlvE_..." => {
10562 ClosureTypeName(LambdaSig(vec![]), None),
10563 b"..."
10564 }
10565 b"UlvE36_..." => {
10566 ClosureTypeName(LambdaSig(vec![]), Some(36)),
10567 b"..."
10568 }
10569 }
10570 Err => {
10571 b"UlvE36zzz" => Error::UnexpectedText,
10572 b"UlvEzzz" => Error::UnexpectedText,
10573 b"Ulvzzz" => Error::UnexpectedText,
10574 b"zzz" => Error::UnexpectedText,
10575 b"UlvE10" => Error::UnexpectedEnd,
10576 b"UlvE" => Error::UnexpectedEnd,
10577 b"Ulv" => Error::UnexpectedEnd,
10578 b"Ul" => Error::UnexpectedEnd,
10579 b"U" => Error::UnexpectedEnd,
10580 b"" => Error::UnexpectedEnd,
10581 }
10582 });
10583 }
10584
10585 #[test]
10586 fn parse_lambda_sig() {
10587 assert_parse!(LambdaSig {
10588 with subs [
10589 Substitutable::Type(
10590 Type::PointerTo(
10591 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool))))
10592 ] => {
10593 Ok => {
10594 b"v..." => {
10595 LambdaSig(vec![]),
10596 b"...",
10597 []
10598 }
10599 b"S_S_S_..." => {
10600 LambdaSig(vec![
10601 TypeHandle::BackReference(0),
10602 TypeHandle::BackReference(0),
10603 TypeHandle::BackReference(0),
10604 ]),
10605 b"...",
10606 []
10607 }
10608 }
10609 Err => {
10610 b"..." => Error::UnexpectedText,
10611 b"S" => Error::UnexpectedEnd,
10612 b"" => Error::UnexpectedEnd,
10613 }
10614 }
10615 });
10616 }
10617
10618 #[test]
10619 fn parse_substitution() {
10620 assert_parse!(Substitution {
10621 with subs [
10622 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10623 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
10624 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10625 ] => {
10626 Ok => {
10627 b"S_..." => {
10628 Substitution::BackReference(0),
10629 b"...",
10630 []
10631 }
10632 b"S1_..." => {
10633 Substitution::BackReference(2),
10634 b"...",
10635 []
10636 }
10637 b"St..." => {
10638 Substitution::WellKnown(WellKnownComponent::Std),
10639 b"...",
10640 []
10641 }
10642 b"Sa..." => {
10643 Substitution::WellKnown(WellKnownComponent::StdAllocator),
10644 b"...",
10645 []
10646 }
10647 b"Sb..." => {
10648 Substitution::WellKnown(WellKnownComponent::StdString1),
10649 b"...",
10650 []
10651 }
10652 b"Ss..." => {
10653 Substitution::WellKnown(WellKnownComponent::StdString2),
10654 b"...",
10655 []
10656 }
10657 b"Si..." => {
10658 Substitution::WellKnown(WellKnownComponent::StdIstream),
10659 b"...",
10660 []
10661 }
10662 b"So..." => {
10663 Substitution::WellKnown(WellKnownComponent::StdOstream),
10664 b"...",
10665 []
10666 }
10667 b"Sd..." => {
10668 Substitution::WellKnown(WellKnownComponent::StdIostream),
10669 b"...",
10670 []
10671 }
10672 }
10673 Err => {
10674 b"S999_" => Error::BadBackReference,
10675 b"Sz" => Error::UnexpectedText,
10676 b"zzz" => Error::UnexpectedText,
10677 b"S1" => Error::UnexpectedEnd,
10678 b"S" => Error::UnexpectedEnd,
10679 b"" => Error::UnexpectedEnd,
10680 }
10681 }
10682 });
10683 }
10684
10685 #[test]
10686 fn parse_special_name() {
10687 assert_parse!(SpecialName {
10688 Ok => {
10689 b"TVi..." => {
10690 SpecialName::VirtualTable(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10691 b"..."
10692 }
10693 b"TTi..." => {
10694 SpecialName::Vtt(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10695 b"..."
10696 }
10697 b"TIi..." => {
10698 SpecialName::Typeinfo(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10699 b"..."
10700 }
10701 b"TSi..." => {
10702 SpecialName::TypeinfoName(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10703 b"..."
10704 }
10705 b"Tv42_36_3abc..." => {
10706 SpecialName::VirtualOverrideThunk(
10707 CallOffset::Virtual(VOffset(42, 36)),
10708 Box::new(Encoding::Data(
10709 Name::Unscoped(
10710 UnscopedName::Unqualified(
10711 UnqualifiedName::Source(
10712 SourceName(Identifier {
10713 start: 9,
10714 end: 12,
10715 }))))))),
10716 b"..."
10717 }
10718 b"Tcv42_36_v42_36_3abc..." => {
10719 SpecialName::VirtualOverrideThunkCovariant(
10720 CallOffset::Virtual(VOffset(42, 36)),
10721 CallOffset::Virtual(VOffset(42, 36)),
10722 Box::new(Encoding::Data(
10723 Name::Unscoped(
10724 UnscopedName::Unqualified(
10725 UnqualifiedName::Source(
10726 SourceName(Identifier {
10727 start: 17,
10728 end: 20,
10729 }))))))),
10730 b"..."
10731 }
10732 b"GV3abc..." => {
10733 SpecialName::Guard(
10734 Name::Unscoped(
10735 UnscopedName::Unqualified(
10736 UnqualifiedName::Source(
10737 SourceName(Identifier {
10738 start: 3,
10739 end: 6,
10740 }))))),
10741 b"..."
10742 }
10743 b"GR3abc_..." => {
10744 SpecialName::GuardTemporary(
10745 Name::Unscoped(
10746 UnscopedName::Unqualified(
10747 UnqualifiedName::Source(
10748 SourceName(Identifier {
10749 start: 3,
10750 end: 6,
10751 })))),
10752 0),
10753 b"..."
10754 }
10755 b"GR3abc0_..." => {
10756 SpecialName::GuardTemporary(
10757 Name::Unscoped(
10758 UnscopedName::Unqualified(
10759 UnqualifiedName::Source(
10760 SourceName(Identifier {
10761 start: 3,
10762 end: 6,
10763 })))),
10764 1),
10765 b"..."
10766 }
10767 b"Gr4_abc..." => {
10768 SpecialName::JavaResource(vec![ResourceName {
10769 start: 4,
10770 end: 7,
10771 }]),
10772 b"..."
10773 }
10774 b"TCc7_i..." => {
10775 SpecialName::ConstructionVtable(
10776 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
10777 7,
10778 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
10779 ),
10780 b"..."
10781 }
10782 b"TFi..." => {
10783 SpecialName::TypeinfoFunction(
10784 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
10785 b"..."
10786 }
10787 b"TH4name..." => {
10788 SpecialName::TlsInit(
10789 Name::Unscoped(
10790 UnscopedName::Unqualified(
10791 UnqualifiedName::Source(
10792 SourceName(Identifier { start: 3, end: 7 }))))),
10793 b"..."
10794 }
10795 b"TW4name..." => {
10796 SpecialName::TlsWrapper(
10797 Name::Unscoped(
10798 UnscopedName::Unqualified(
10799 UnqualifiedName::Source(
10800 SourceName(Identifier { start: 3, end: 7 }))))),
10801 b"..."
10802 }
10803 }
10804 Err => {
10805 b"TZ" => Error::UnexpectedText,
10806 b"GZ" => Error::UnexpectedText,
10807 b"GR3abcz" => Error::UnexpectedText,
10808 b"GR3abc0z" => Error::UnexpectedText,
10809 b"T" => Error::UnexpectedEnd,
10810 b"G" => Error::UnexpectedEnd,
10811 b"" => Error::UnexpectedEnd,
10812 b"GR3abc" => Error::UnexpectedEnd,
10813 b"GR3abc0" => Error::UnexpectedEnd,
10814 b"TCcn7_i..." => Error::UnexpectedText,
10816 b"Gr3abc0" => Error::UnexpectedText,
10817 }
10818 });
10819 }
10820
10821 #[test]
10822 fn parse_function_param() {
10823 assert_parse!(FunctionParam {
10824 Ok => {
10825 b"fpK_..." => {
10826 FunctionParam(0,
10827 CvQualifiers {
10828 restrict: false,
10829 volatile: false,
10830 const_: true,
10831 },
10832 Some(0)),
10833 b"..."
10834 }
10835 b"fL1pK_..." => {
10836 FunctionParam(1,
10837 CvQualifiers {
10838 restrict: false,
10839 volatile: false,
10840 const_: true,
10841 },
10842 Some(0)),
10843 b"..."
10844 }
10845 b"fpK3_..." => {
10846 FunctionParam(0,
10847 CvQualifiers {
10848 restrict: false,
10849 volatile: false,
10850 const_: true,
10851 },
10852 Some(4)),
10853 b"..."
10854 }
10855 b"fL1pK4_..." => {
10856 FunctionParam(1,
10857 CvQualifiers {
10858 restrict: false,
10859 volatile: false,
10860 const_: true,
10861 },
10862 Some(5)),
10863 b"..."
10864 }
10865 }
10866 Err => {
10867 b"fz" => Error::UnexpectedText,
10868 b"fLp_" => Error::UnexpectedText,
10869 b"fpL_" => Error::UnexpectedText,
10870 b"fL1pK4z" => Error::UnexpectedText,
10871 b"fL1pK4" => Error::UnexpectedEnd,
10872 b"fL1p" => Error::UnexpectedEnd,
10873 b"fL1" => Error::UnexpectedEnd,
10874 b"fL" => Error::UnexpectedEnd,
10875 b"f" => Error::UnexpectedEnd,
10876 b"" => Error::UnexpectedEnd,
10877 }
10878 });
10879 }
10880
10881 #[test]
10882 fn parse_discriminator() {
10883 assert_parse!(Discriminator {
10884 Ok => {
10885 b"_0..." => {
10886 Discriminator(0),
10887 b"..."
10888 }
10889 b"_9..." => {
10890 Discriminator(9),
10891 b"..."
10892 }
10893 b"__99_..." => {
10894 Discriminator(99),
10895 b"..."
10896 }
10897 }
10898 Err => {
10899 b"_n1" => Error::UnexpectedText,
10900 b"__99..." => Error::UnexpectedText,
10901 b"__99" => Error::UnexpectedEnd,
10902 b"..." => Error::UnexpectedText,
10903 }
10904 });
10905 }
10906
10907 #[test]
10908 fn parse_data_member_prefix() {
10909 assert_parse!(DataMemberPrefix {
10910 Ok => {
10911 b"3fooM..." => {
10912 DataMemberPrefix(SourceName(Identifier {
10913 start: 1,
10914 end: 4,
10915 })),
10916 b"..."
10917 }
10918 }
10919 Err => {
10920 b"zzz" => Error::UnexpectedText,
10921 b"1" => Error::UnexpectedEnd,
10922 b"" => Error::UnexpectedEnd,
10923 }
10924 });
10925 }
10926
10927 #[test]
10928 fn parse_ref_qualifier() {
10929 assert_parse!(RefQualifier {
10930 Ok => {
10931 b"R..." => {
10932 RefQualifier::LValueRef,
10933 b"..."
10934 }
10935 b"O..." => {
10936 RefQualifier::RValueRef,
10937 b"..."
10938 }
10939 }
10940 Err => {
10941 b"..." => Error::UnexpectedText,
10942 b"" => Error::UnexpectedEnd,
10943 }
10944 });
10945 }
10946
10947 #[test]
10948 fn parse_cv_qualifiers() {
10949 assert_parse!(CvQualifiers {
10950 Ok => {
10951 b"" => {
10952 CvQualifiers { restrict: false, volatile: false, const_: false },
10953 b""
10954 }
10955 b"..." => {
10956 CvQualifiers { restrict: false, volatile: false, const_: false },
10957 b"..."
10958 }
10959 b"r..." => {
10960 CvQualifiers { restrict: true, volatile: false, const_: false },
10961 b"..."
10962 }
10963 b"rV..." => {
10964 CvQualifiers { restrict: true, volatile: true, const_: false },
10965 b"..."
10966 }
10967 b"rVK..." => {
10968 CvQualifiers { restrict: true, volatile: true, const_: true },
10969 b"..."
10970 }
10971 b"V" => {
10972 CvQualifiers { restrict: false, volatile: true, const_: false },
10973 b""
10974 }
10975 b"VK" => {
10976 CvQualifiers { restrict: false, volatile: true, const_: true },
10977 b""
10978 }
10979 b"K..." => {
10980 CvQualifiers { restrict: false, volatile: false, const_: true },
10981 b"..."
10982 }
10983 }
10984 Err => {
10985 }
10987 });
10988 }
10989
10990 #[test]
10991 fn parse_builtin_type() {
10992 assert_parse!(BuiltinType {
10993 Ok => {
10994 b"c..." => {
10995 BuiltinType::Standard(StandardBuiltinType::Char),
10996 b"..."
10997 }
10998 b"c" => {
10999 BuiltinType::Standard(StandardBuiltinType::Char),
11000 b""
11001 }
11002 b"u3abc..." => {
11003 BuiltinType::Extension(SourceName(Identifier {
11004 start: 2,
11005 end: 5,
11006 })),
11007 b"..."
11008 }
11009 }
11010 Err => {
11011 b"." => Error::UnexpectedText,
11012 b"" => Error::UnexpectedEnd,
11013 }
11014 });
11015 }
11016
11017 #[test]
11018 fn parse_template_param() {
11019 assert_parse!(TemplateParam {
11020 Ok => {
11021 b"T_..." => {
11022 TemplateParam(0),
11023 b"..."
11024 }
11025 b"T3_..." => {
11026 TemplateParam(4),
11027 b"..."
11028 }
11029 }
11030 Err => {
11031 b"wtf" => Error::UnexpectedText,
11032 b"Twtf" => Error::UnexpectedText,
11033 b"T3wtf" => Error::UnexpectedText,
11034 b"T" => Error::UnexpectedEnd,
11035 b"T3" => Error::UnexpectedEnd,
11036 b"" => Error::UnexpectedEnd,
11037 }
11038 });
11039 }
11040
11041 #[test]
11042 fn parse_unscoped_name() {
11043 assert_parse!(UnscopedName {
11044 Ok => {
11045 b"St5hello..." => {
11046 UnscopedName::Std(UnqualifiedName::Source(SourceName(Identifier {
11047 start: 3,
11048 end: 8,
11049 }))),
11050 b"..."
11051 }
11052 b"5hello..." => {
11053 UnscopedName::Unqualified(UnqualifiedName::Source(SourceName(Identifier {
11054 start: 1,
11055 end: 6,
11056 }))),
11057 b"..."
11058 }
11059 }
11060 Err => {
11061 b"St..." => Error::UnexpectedText,
11062 b"..." => Error::UnexpectedText,
11063 b"" => Error::UnexpectedEnd,
11064 }
11065 });
11066 }
11067
11068 #[test]
11069 fn parse_unqualified_name() {
11070 assert_parse!(UnqualifiedName {
11071 Ok => {
11072 b"qu.." => {
11073 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question)),
11074 b".."
11075 }
11076 b"C1.." => {
11077 UnqualifiedName::CtorDtor(CtorDtorName::CompleteConstructor(None)),
11078 b".."
11079 }
11080 b"10abcdefghij..." => {
11081 UnqualifiedName::Source(SourceName(Identifier {
11082 start: 2,
11083 end: 12,
11084 })),
11085 b"..."
11086 }
11087 b"UllE_..." => {
11088 UnqualifiedName::ClosureType(
11089 ClosureTypeName(
11090 LambdaSig(vec![
11091 TypeHandle::Builtin(
11092 BuiltinType::Standard(
11093 StandardBuiltinType::Long))
11094 ]),
11095 None)),
11096 b"..."
11097 }
11098 b"Ut5_..." => {
11099 UnqualifiedName::UnnamedType(UnnamedTypeName(Some(5))),
11100 b"..."
11101 }
11102 b"B5cxx11..." => {
11103 UnqualifiedName::ABITag(TaggedName(SourceName(Identifier {
11104 start: 2,
11105 end: 7,
11106 }))),
11107 b"..."
11108 }
11109 b"L3foo_0..." => {
11110 UnqualifiedName::LocalSourceName(
11111 SourceName(Identifier {
11112 start: 2,
11113 end: 5
11114 }),
11115 Some(Discriminator(0))
11116 ),
11117 "..."
11118 }
11119 b"L3foo..." => {
11120 UnqualifiedName::LocalSourceName(
11121 SourceName(Identifier {
11122 start: 2,
11123 end: 5
11124 }),
11125 None
11126 ),
11127 "..."
11128 }
11129 }
11130 Err => {
11131 b"zzz" => Error::UnexpectedText,
11132 b"Uq" => Error::UnexpectedText,
11133 b"C" => Error::UnexpectedEnd,
11134 b"" => Error::UnexpectedEnd,
11135 }
11136 });
11137 }
11138
11139 #[test]
11140 fn parse_unnamed_type_name() {
11141 assert_parse!(UnnamedTypeName {
11142 Ok => {
11143 b"Ut_abc" => {
11144 UnnamedTypeName(None),
11145 b"abc"
11146 }
11147 b"Ut42_abc" => {
11148 UnnamedTypeName(Some(42)),
11149 b"abc"
11150 }
11151 b"Ut42_" => {
11152 UnnamedTypeName(Some(42)),
11153 b""
11154 }
11155 }
11156 Err => {
11157 b"ut_" => Error::UnexpectedText,
11158 b"u" => Error::UnexpectedEnd,
11159 b"Ut" => Error::UnexpectedEnd,
11160 b"Ut._" => Error::UnexpectedText,
11161 b"Ut42" => Error::UnexpectedEnd,
11162 }
11163 });
11164 }
11165
11166 #[test]
11167 fn parse_identifier() {
11168 assert_parse!(Identifier {
11169 Ok => {
11170 b"1abc" => {
11171 Identifier { start: 0, end: 4 },
11172 b""
11173 }
11174 b"_Az1\0\0\0" => {
11175 Identifier { start: 0, end: 4 },
11176 b"\0\0\0"
11177 }
11178 b"$_0\0\0\0" => {
11179 Identifier { start: 0, end: 3 },
11180 b"\0\0\0"
11181 }
11182 }
11183 Err => {
11184 b"\0\0\0" => Error::UnexpectedText,
11185 b"" => Error::UnexpectedEnd,
11186 }
11187 });
11188 }
11189
11190 #[test]
11191 fn parse_source_name() {
11192 assert_parse!(SourceName {
11193 Ok => {
11194 b"1abc" => {
11195 SourceName(Identifier { start: 1, end: 2 }),
11196 b"bc"
11197 }
11198 b"10abcdefghijklm" => {
11199 SourceName(Identifier { start: 2, end: 12 }),
11200 b"klm"
11201 }
11202 }
11203 Err => {
11204 b"0abc" => Error::UnexpectedText,
11205 b"n1abc" => Error::UnexpectedText,
11206 b"10abcdef" => Error::UnexpectedEnd,
11207 b"" => Error::UnexpectedEnd,
11208 }
11209 });
11210 }
11211
11212 #[test]
11213 fn parse_number() {
11214 assert_parse!(Number {
11215 Ok => {
11216 b"n2n3" => {
11217 -2,
11218 b"n3"
11219 }
11220 b"12345abcdef" => {
11221 12345,
11222 b"abcdef"
11223 }
11224 b"0abcdef" => {
11225 0,
11226 b"abcdef"
11227 }
11228 b"42" => {
11229 42,
11230 b""
11231 }
11232 }
11233 Err => {
11234 b"001" => Error::UnexpectedText,
11235 b"wutang" => Error::UnexpectedText,
11236 b"n" => Error::UnexpectedEnd,
11237 b"" => Error::UnexpectedEnd,
11238 }
11239 });
11240 }
11241
11242 #[test]
11243 fn parse_call_offset() {
11244 assert_parse!(CallOffset {
11245 Ok => {
11246 b"hn42_..." => {
11247 CallOffset::NonVirtual(NvOffset(-42)),
11248 b"..."
11249 }
11250 b"vn42_36_..." => {
11251 CallOffset::Virtual(VOffset(-42, 36)),
11252 b"..."
11253 }
11254 }
11255 Err => {
11256 b"h1..." => Error::UnexpectedText,
11257 b"v1_1..." => Error::UnexpectedText,
11258 b"hh" => Error::UnexpectedText,
11259 b"vv" => Error::UnexpectedText,
11260 b"z" => Error::UnexpectedText,
11261 b"" => Error::UnexpectedEnd,
11262 }
11263 });
11264 }
11265
11266 #[test]
11267 fn parse_v_offset() {
11268 assert_parse!(VOffset {
11269 Ok => {
11270 b"n2_n3abcdef" => {
11271 VOffset(-2, -3),
11272 b"abcdef"
11273 }
11274 b"12345_12345abcdef" => {
11275 VOffset(12345, 12345),
11276 b"abcdef"
11277 }
11278 b"0_0abcdef" => {
11279 VOffset(0, 0),
11280 b"abcdef"
11281 }
11282 b"42_n3" => {
11283 VOffset(42, -3),
11284 b""
11285 }
11286 }
11287 Err => {
11288 b"001" => Error::UnexpectedText,
11289 b"1_001" => Error::UnexpectedText,
11290 b"wutang" => Error::UnexpectedText,
11291 b"n_" => Error::UnexpectedText,
11292 b"1_n" => Error::UnexpectedEnd,
11293 b"1_" => Error::UnexpectedEnd,
11294 b"n" => Error::UnexpectedEnd,
11295 b"" => Error::UnexpectedEnd,
11296 }
11297 });
11298 }
11299
11300 #[test]
11301 fn parse_nv_offset() {
11302 assert_parse!(NvOffset {
11303 Ok => {
11304 b"n2n3" => {
11305 NvOffset(-2),
11306 b"n3"
11307 }
11308 b"12345abcdef" => {
11309 NvOffset(12345),
11310 b"abcdef"
11311 }
11312 b"0abcdef" => {
11313 NvOffset(0),
11314 b"abcdef"
11315 }
11316 b"42" => {
11317 NvOffset(42),
11318 b""
11319 }
11320 }
11321 Err => {
11322 b"001" => Error::UnexpectedText,
11323 b"wutang" => Error::UnexpectedText,
11324 b"" => Error::UnexpectedEnd,
11325 }
11326 });
11327 }
11328
11329 #[test]
11330 fn parse_seq_id() {
11331 assert_parse!(SeqId {
11332 Ok => {
11333 b"1_" => {
11334 SeqId(1),
11335 b"_"
11336 }
11337 b"42" => {
11338 SeqId(146),
11339 b""
11340 }
11341 b"ABCabc" => {
11342 SeqId(13368),
11343 b"abc"
11344 }
11345 }
11346 Err => {
11347 b"abc" => Error::UnexpectedText,
11348 b"001" => Error::UnexpectedText,
11349 b"wutang" => Error::UnexpectedText,
11350 b"" => Error::UnexpectedEnd,
11351 }
11352 });
11353 }
11354
11355 #[test]
11356 fn parse_ctor_dtor_name() {
11357 assert_parse!(CtorDtorName {
11358 Ok => {
11359 b"D0" => {
11360 CtorDtorName::DeletingDestructor,
11361 b""
11362 }
11363 b"C101" => {
11364 CtorDtorName::CompleteConstructor(None),
11365 b"01"
11366 }
11367 }
11368 Err => {
11369 b"gayagaya" => Error::UnexpectedText,
11370 b"C" => Error::UnexpectedEnd,
11371 b"" => Error::UnexpectedEnd,
11372 }
11373 });
11374 }
11375
11376 #[test]
11377 fn parse_operator_name() {
11378 assert_parse!(OperatorName {
11379 Ok => {
11380 b"qu..." => {
11381 OperatorName::Simple(SimpleOperatorName::Question),
11382 b"..."
11383 }
11384 b"cvi..." => {
11385 OperatorName::Conversion(
11386 TypeHandle::Builtin(
11387 BuiltinType::Standard(
11388 StandardBuiltinType::Int))),
11389 b"..."
11390 }
11391 b"li3Foo..." => {
11392 OperatorName::Literal(SourceName(Identifier {
11393 start: 3,
11394 end: 6,
11395 })),
11396 b"..."
11397 }
11398 b"v33Foo..." => {
11399 OperatorName::VendorExtension(3, SourceName(Identifier {
11400 start: 3,
11401 end: 6
11402 })),
11403 b"..."
11404 }
11405 }
11406 Err => {
11407 b"cv" => Error::UnexpectedEnd,
11408 b"li3ab" => Error::UnexpectedEnd,
11409 b"li" => Error::UnexpectedEnd,
11410 b"v33ab" => Error::UnexpectedEnd,
11411 b"v3" => Error::UnexpectedEnd,
11412 b"v" => Error::UnexpectedEnd,
11413 b"" => Error::UnexpectedEnd,
11414 b"q" => Error::UnexpectedText,
11415 b"c" => Error::UnexpectedText,
11416 b"l" => Error::UnexpectedText,
11417 b"zzz" => Error::UnexpectedText,
11418 }
11419 });
11420 }
11421
11422 #[test]
11423 fn parse_simple_operator_name() {
11424 assert_parse!(SimpleOperatorName {
11425 Ok => {
11426 b"qu" => {
11427 SimpleOperatorName::Question,
11428 b""
11429 }
11430 b"quokka" => {
11431 SimpleOperatorName::Question,
11432 b"okka"
11433 }
11434 }
11435 Err => {
11436 b"bu-buuuu" => Error::UnexpectedText,
11437 b"q" => Error::UnexpectedEnd,
11438 b"" => Error::UnexpectedEnd,
11439 }
11440 });
11441 }
11442
11443 #[test]
11444 fn parse_subobject_expr() {
11445 assert_parse!(SubobjectExpr {
11446 with subs [] => {
11447 Ok => {
11448 "PKcL_Z3FooEE..." => {
11449 SubobjectExpr {
11450 ty: TypeHandle::BackReference(1),
11451 expr: Box::new(Expression::Primary(
11452 ExprPrimary::External(
11453 MangledName::Encoding(
11454 Encoding::Data(
11455 Name::Unscoped(
11456 UnscopedName::Unqualified(
11457 UnqualifiedName::Source(
11458 SourceName(
11459 Identifier {
11460 start: 7,
11461 end: 10,
11462 }
11463 )
11464 )
11465 )
11466 )
11467 ),
11468 vec![]
11469 )
11470 )
11471 )),
11472 offset: 0,
11473 },
11474 b"...",
11475 [
11476 Substitutable::Type(
11477 Type::Qualified(
11478 CvQualifiers {
11479 restrict: false,
11480 volatile: false,
11481 const_: true,
11482 },
11483 TypeHandle::Builtin(
11484 BuiltinType::Standard(
11485 StandardBuiltinType::Char,
11486 ),
11487 ),
11488 )
11489 ),
11490 Substitutable::Type(
11491 Type::PointerTo(
11492 TypeHandle::BackReference(
11493 0,
11494 ),
11495 ),
11496 )
11497 ]
11498 }
11499 }
11500 Err => {
11501 "" => Error::UnexpectedEnd,
11502 "" => Error::UnexpectedEnd,
11503 }
11504 }
11505 });
11506 }
11507}