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
20macro_rules! r#try_recurse {
21 ($expr:expr $(,)?) => {
22 match $expr {
23 Result::Err(error::Error::TooMuchRecursion) => {
24 return Result::Err(error::Error::TooMuchRecursion);
25 }
26 val => val,
27 }
28 };
29}
30
31struct AutoLogParse;
32
33#[cfg(feature = "logging")]
34thread_local! {
35 static LOG_DEPTH: RefCell<usize> = RefCell::new(0);
36}
37
38impl AutoLogParse {
39 #[cfg(feature = "logging")]
40 fn new(production: &'static str, input: IndexStr<'_>) -> AutoLogParse {
41 LOG_DEPTH.with(|depth| {
42 if *depth.borrow() == 0 {
43 println!();
44 }
45
46 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
47 log!(
48 "{}({} \"{}\" {}",
49 indent,
50 production,
51 String::from_utf8_lossy(input.as_ref()),
52 input.len(),
53 );
54 *depth.borrow_mut() += 1;
55 });
56 AutoLogParse
57 }
58
59 #[cfg(not(feature = "logging"))]
60 #[inline(always)]
61 fn new(_: &'static str, _: IndexStr) -> AutoLogParse {
62 AutoLogParse
63 }
64}
65
66#[cfg(feature = "logging")]
67impl Drop for AutoLogParse {
68 fn drop(&mut self) {
69 LOG_DEPTH.with(|depth| {
70 *depth.borrow_mut() -= 1;
71 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
72 log!("{})", indent);
73 });
74 }
75}
76
77macro_rules! try_begin_parse {
85 ( $production:expr , $ctx:expr , $input:expr ) => {
86 let _log = AutoLogParse::new($production, $input);
87 let _auto_check_recursion = AutoParseRecursion::new($ctx)?;
88 };
89}
90
91struct AutoLogDemangle;
92
93impl AutoLogDemangle {
94 #[cfg(feature = "logging")]
95 fn new<P, W>(
96 production: &P,
97 ctx: &DemangleContext<W>,
98 scope: Option<ArgScopeStack>,
99 is_inner: bool,
100 ) -> AutoLogDemangle
101 where
102 P: ?Sized + fmt::Debug,
103 W: DemangleWrite,
104 {
105 LOG_DEPTH.with(|depth| {
106 if *depth.borrow() == 0 {
107 println!();
108 }
109
110 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
111 log!("{}(", indent);
112 log!(
113 "{} {}{:?}",
114 indent,
115 if is_inner { "as_inner: " } else { "" },
116 production
117 );
118 log!("{} inner = {:?}", indent, ctx.inner);
119 log!("{} scope = {:?}", indent, scope);
120
121 *depth.borrow_mut() += 1;
122 });
123 AutoLogDemangle
124 }
125
126 #[cfg(not(feature = "logging"))]
127 #[inline(always)]
128 fn new<P, W>(
129 _: &P,
130 _: &DemangleContext<W>,
131 _: Option<ArgScopeStack>,
132 _: bool,
133 ) -> AutoLogDemangle
134 where
135 P: ?Sized + fmt::Debug,
136 W: DemangleWrite,
137 {
138 AutoLogDemangle
139 }
140}
141
142#[cfg(feature = "logging")]
143impl Drop for AutoLogDemangle {
144 fn drop(&mut self) {
145 LOG_DEPTH.with(|depth| {
146 *depth.borrow_mut() -= 1;
147 let indent: String = (0..*depth.borrow() * 4).map(|_| ' ').collect();
148 log!("{})", indent);
149 });
150 }
151}
152
153macro_rules! try_begin_demangle {
156 ( $production:expr, $ctx:expr, $scope:expr ) => {{
157 let _log = AutoLogDemangle::new($production, $ctx, $scope, false);
158 &mut AutoParseDemangle::new($ctx)?
159 }};
160}
161
162macro_rules! try_begin_demangle_as_inner {
165 ( $production:expr, $ctx:expr, $scope:expr ) => {{
166 let _log = AutoLogDemangle::new($production, $ctx, $scope, true);
167 &mut AutoParseDemangle::new($ctx)?
168 }};
169}
170
171#[derive(Debug, Default, Clone, Copy)]
172struct ParseContextState {
173 recursion_level: u32,
176 in_conversion: bool,
178}
179
180#[derive(Debug, Clone)]
182pub struct ParseContext {
183 max_recursion: u32,
186 state: Cell<ParseContextState>,
188}
189
190impl ParseContext {
191 pub fn new(options: ParseOptions) -> ParseContext {
193 ParseContext {
194 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(96),
195 state: Cell::new(ParseContextState::default()),
196 }
197 }
198
199 pub fn recursion_level(&self) -> u32 {
201 self.state.get().recursion_level
202 }
203
204 #[inline]
205 fn enter_recursion(&self) -> error::Result<()> {
206 let mut state = self.state.get();
207 let new_recursion_level = state.recursion_level + 1;
208
209 if new_recursion_level >= self.max_recursion {
210 log!("Hit too much recursion at level {}", self.max_recursion);
211 Err(error::Error::TooMuchRecursion)
212 } else {
213 state.recursion_level = new_recursion_level;
214 self.state.set(state);
215 Ok(())
216 }
217 }
218
219 #[inline]
220 fn exit_recursion(&self) {
221 let mut state = self.state.get();
222 debug_assert!(state.recursion_level >= 1);
223 state.recursion_level -= 1;
224 self.state.set(state);
225 }
226
227 #[inline]
228 fn in_conversion(&self) -> bool {
229 self.state.get().in_conversion
230 }
231
232 fn set_in_conversion(&self, in_conversion: bool) -> bool {
233 let mut state = self.state.get();
234 let previously_in_conversion = state.in_conversion;
235 state.in_conversion = in_conversion;
236 self.state.set(state);
237 previously_in_conversion
238 }
239}
240
241struct AutoParseRecursion<'a>(&'a ParseContext);
245
246impl<'a> AutoParseRecursion<'a> {
247 #[inline]
248 fn new(ctx: &'a ParseContext) -> error::Result<AutoParseRecursion<'a>> {
249 ctx.enter_recursion()?;
250 Ok(AutoParseRecursion(ctx))
251 }
252}
253
254impl<'a> Drop for AutoParseRecursion<'a> {
255 #[inline]
256 fn drop(&mut self) {
257 self.0.exit_recursion();
258 }
259}
260
261#[doc(hidden)]
272pub trait Parse: Sized {
273 fn parse<'a, 'b>(
276 ctx: &'a ParseContext,
277 subs: &'a mut SubstitutionTable,
278 input: IndexStr<'b>,
279 ) -> Result<(Self, IndexStr<'b>)>;
280}
281
282trait GetTemplateArgs {
289 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs>;
291}
292
293#[derive(Debug)]
300pub(crate) enum LeafName<'a> {
301 SourceName(&'a SourceName),
302 WellKnownComponent(&'a WellKnownComponent),
303 Closure(&'a ClosureTypeName),
304 UnnamedType(&'a UnnamedTypeName),
305}
306
307impl<'subs, W> DemangleAsLeaf<'subs, W> for LeafName<'subs>
308where
309 W: 'subs + DemangleWrite,
310{
311 fn demangle_as_leaf<'me, 'ctx>(
312 &'me self,
313 ctx: &'ctx mut DemangleContext<'subs, W>,
314 ) -> fmt::Result {
315 match *self {
316 LeafName::SourceName(sn) => sn.demangle(ctx, None),
317 LeafName::Closure(c) => c.demangle(ctx, None),
318 LeafName::WellKnownComponent(wkc) => wkc.demangle_as_leaf(ctx),
319 LeafName::UnnamedType(utn) => utn.demangle_as_leaf(ctx),
320 }
321 }
322}
323
324pub(crate) trait GetLeafName<'a> {
327 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>>;
328}
329
330pub(crate) trait IsCtorDtorConversion {
333 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool;
334}
335
336trait ArgScope<'me, 'ctx>: fmt::Debug {
351 fn leaf_name(&'me self) -> Result<LeafName<'ctx>>;
353
354 fn get_template_arg(&'me self, index: usize)
356 -> Result<(&'ctx TemplateArg, &'ctx TemplateArgs)>;
357
358 #[allow(unused)]
359 fn get_function_arg(&'me self, index: usize) -> Result<&'ctx Type>;
361}
362
363#[derive(Copy, Clone, Debug)]
369pub struct ArgScopeStack<'prev, 'subs>
370where
371 'subs: 'prev,
372{
373 item: &'subs dyn ArgScope<'subs, 'subs>,
374 in_arg: Option<(usize, &'subs TemplateArgs)>,
375 prev: Option<&'prev ArgScopeStack<'prev, 'subs>>,
376}
377
378trait ArgScopeStackExt<'prev, 'subs>: Copy {
387 fn push(
390 &'prev self,
391 item: &'subs dyn ArgScope<'subs, 'subs>,
392 ) -> Option<ArgScopeStack<'prev, 'subs>>;
393}
394
395impl<'prev, 'subs> ArgScopeStackExt<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
396 fn push(
397 &'prev self,
398 item: &'subs dyn ArgScope<'subs, 'subs>,
399 ) -> Option<ArgScopeStack<'prev, 'subs>> {
400 log!("ArgScopeStack::push: {:?}", item);
401 Some(ArgScopeStack {
402 prev: self.as_ref(),
403 in_arg: None,
404 item: item,
405 })
406 }
407}
408
409impl<'prev, 'subs> ArgScope<'prev, 'subs> for Option<ArgScopeStack<'prev, 'subs>> {
411 fn leaf_name(&'prev self) -> Result<LeafName<'subs>> {
412 let mut scope = self.as_ref();
413 while let Some(s) = scope {
414 if let Ok(c) = s.item.leaf_name() {
415 return Ok(c);
416 }
417 scope = s.prev;
418 }
419 Err(error::Error::BadLeafNameReference)
420 }
421
422 fn get_template_arg(
423 &'prev self,
424 idx: usize,
425 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
426 let mut scope = self.as_ref();
427 while let Some(s) = scope {
428 if let Ok((arg, args)) = s.item.get_template_arg(idx) {
429 if let Some((in_idx, in_args)) = s.in_arg {
430 if args as *const TemplateArgs == in_args as *const TemplateArgs
431 && in_idx <= idx
432 {
433 return Err(error::Error::ForwardTemplateArgReference);
434 }
435 }
436 return Ok((arg, args));
437 }
438 scope = s.prev;
439 }
440
441 Err(error::Error::BadTemplateArgReference)
442 }
443
444 fn get_function_arg(&'prev self, idx: usize) -> Result<&'subs Type> {
445 let mut scope = self.as_ref();
446 while let Some(s) = scope {
447 if let Ok(arg) = s.item.get_function_arg(idx) {
448 return Ok(arg);
449 }
450 scope = s.prev;
451 }
452
453 Err(error::Error::BadFunctionArgReference)
454 }
455}
456
457#[derive(Debug, Copy, Clone)]
458struct DemangleState {
459 pub recursion_level: u32,
461}
462
463struct AutoParseDemangle<'a, 'b, W: 'a + DemangleWrite>(&'b mut DemangleContext<'a, W>);
467
468impl<'a, 'b, W: 'a + DemangleWrite> AutoParseDemangle<'a, 'b, W> {
469 #[inline]
470 fn new(ctx: &'b mut DemangleContext<'a, W>) -> core::result::Result<Self, fmt::Error> {
471 ctx.enter_recursion()?;
472 Ok(AutoParseDemangle(ctx))
473 }
474}
475
476impl<'a, 'b, W: 'a + DemangleWrite> ops::Deref for AutoParseDemangle<'a, 'b, W> {
477 type Target = DemangleContext<'a, W>;
478
479 fn deref(&self) -> &Self::Target {
480 self.0
481 }
482}
483
484impl<'a, 'b, W: 'a + DemangleWrite> ops::DerefMut for AutoParseDemangle<'a, 'b, W> {
485 fn deref_mut(&mut self) -> &mut Self::Target {
486 self.0
487 }
488}
489
490impl<'a, 'b, W: 'a + DemangleWrite> Drop for AutoParseDemangle<'a, 'b, W> {
491 #[inline]
492 fn drop(&mut self) {
493 self.0.exit_recursion();
494 }
495}
496
497#[doc(hidden)]
499#[derive(Debug)]
500pub struct DemangleContext<'a, W>
501where
502 W: 'a + DemangleWrite,
503{
504 subs: &'a SubstitutionTable,
507
508 max_recursion: u32,
510
511 inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
527
528 input: &'a [u8],
530
531 source_name: Option<&'a str>,
534
535 out: &'a mut W,
537
538 bytes_written: usize,
541
542 last_char_written: Option<char>,
544
545 is_lambda_arg: bool,
548
549 is_template_prefix: bool,
551
552 is_template_prefix_in_nested_name: bool,
554
555 is_template_argument_pack: bool,
558
559 is_explicit_obj_param: bool,
561
562 show_params: bool,
566
567 show_return_type: bool,
571
572 show_expression_literal_types: bool,
574
575 state: Cell<DemangleState>,
577}
578
579impl<'a, W> fmt::Write for DemangleContext<'a, W>
580where
581 W: 'a + DemangleWrite,
582{
583 fn write_str(&mut self, s: &str) -> fmt::Result {
584 if s.is_empty() {
585 return Ok(());
586 }
587
588 log!("DemangleContext::write: '{}'", s);
589
590 self.out.write_string(s).map(|_| {
591 self.last_char_written = s.chars().last();
592 self.bytes_written += s.len();
593 })
594 }
595}
596
597impl<'a, W> DemangleContext<'a, W>
598where
599 W: 'a + DemangleWrite,
600{
601 pub fn new(
603 subs: &'a SubstitutionTable,
604 input: &'a [u8],
605 options: DemangleOptions,
606 out: &'a mut W,
607 ) -> DemangleContext<'a, W> {
608 DemangleContext {
609 subs: subs,
610 max_recursion: options.recursion_limit.map(|v| v.get()).unwrap_or(128),
611 inner: vec![],
612 input: input,
613 source_name: None,
614 out: out,
615 bytes_written: 0,
616 last_char_written: None,
617 is_lambda_arg: false,
618 is_template_prefix: false,
619 is_template_prefix_in_nested_name: false,
620 is_template_argument_pack: false,
621 is_explicit_obj_param: false,
622 show_params: !options.no_params,
623 show_return_type: !options.no_return_type,
624 show_expression_literal_types: !options.hide_expression_literal_types,
625 state: Cell::new(DemangleState { recursion_level: 0 }),
626 }
627 }
628
629 pub fn recursion_level(&self) -> u32 {
631 self.state.get().recursion_level
632 }
633
634 #[inline]
635 fn enter_recursion(&self) -> fmt::Result {
636 let mut state = self.state.get();
637 let new_recursion_level = state.recursion_level + 1;
638
639 if new_recursion_level >= self.max_recursion {
640 log!("Hit too much recursion at level {}", self.max_recursion);
641 Err(Default::default())
642 } else {
643 state.recursion_level = new_recursion_level;
644 self.state.set(state);
645 Ok(())
646 }
647 }
648
649 #[inline]
650 fn exit_recursion(&self) {
651 let mut state = self.state.get();
652 debug_assert!(state.recursion_level >= 1);
653 state.recursion_level -= 1;
654 self.state.set(state);
655 }
656
657 #[inline]
658 fn ensure(&mut self, ch: char) -> fmt::Result {
659 if self.last_char_written == Some(ch) {
660 Ok(())
661 } else {
662 write!(self, "{}", ch)?;
663 Ok(())
664 }
665 }
666
667 #[inline]
668 fn ensure_space(&mut self) -> fmt::Result {
669 self.ensure(' ')
670 }
671
672 #[inline]
673 fn push_inner(&mut self, item: &'a dyn DemangleAsInner<'a, W>) {
674 log!("DemangleContext::push_inner: {:?}", item);
675 self.inner.push(item);
676 }
677
678 #[inline]
679 fn pop_inner(&mut self) -> Option<&'a dyn DemangleAsInner<'a, W>> {
680 let popped = self.inner.pop();
681 log!("DemangleContext::pop_inner: {:?}", popped);
682 popped
683 }
684
685 #[inline]
686 fn pop_inner_if(&mut self, inner: &'a dyn DemangleAsInner<'a, W>) -> bool {
687 let last = match self.inner.last() {
688 None => return false,
689 Some(last) => *last,
690 };
691
692 if ptr::eq(last, inner) {
693 self.inner.pop();
694 true
695 } else {
696 false
697 }
698 }
699
700 fn demangle_inner_prefixes<'prev>(
701 &mut self,
702 scope: Option<ArgScopeStack<'prev, 'a>>,
703 ) -> fmt::Result {
704 log!("DemangleContext::demangle_inner_prefixes");
705 let mut new_inner = vec![];
706 while let Some(inner) = self.pop_inner() {
707 if inner
708 .downcast_to_function_type()
709 .map_or(false, |f| !f.cv_qualifiers.is_empty())
710 {
711 log!(
712 "DemangleContext::demangle_inner_prefixes: not a prefix, saving: {:?}",
713 inner
714 );
715 new_inner.push(inner);
716 } else {
717 log!(
718 "DemangleContext::demangle_inner_prefixes: demangling prefix: {:?}",
719 inner
720 );
721 inner.demangle_as_inner(self, scope)?;
722 }
723 }
724 new_inner.reverse();
725 self.inner = new_inner;
726 Ok(())
727 }
728
729 fn demangle_inners<'prev>(&mut self, scope: Option<ArgScopeStack<'prev, 'a>>) -> fmt::Result {
730 while let Some(inner) = self.pop_inner() {
731 inner.demangle_as_inner(self, scope)?;
732 }
733 Ok(())
734 }
735
736 fn set_source_name(&mut self, start: usize, end: usize) {
737 let ident = &self.input[start..end];
738 self.source_name = str::from_utf8(ident).ok();
739 }
740
741 fn push_demangle_node(&mut self, t: DemangleNodeType) {
742 self.out.push_demangle_node(t);
743 }
744
745 fn pop_demangle_node(&mut self) {
748 self.out.pop_demangle_node();
749 }
750}
751
752#[doc(hidden)]
753#[derive(Debug)]
754pub struct AutoDemangleContextInnerBarrier<'ctx, 'a, W>
755where
756 W: 'a + DemangleWrite,
757 'a: 'ctx,
758{
759 ctx: &'ctx mut DemangleContext<'a, W>,
760 saved_inner: Vec<&'a dyn DemangleAsInner<'a, W>>,
761}
762
763impl<'ctx, 'a, W> AutoDemangleContextInnerBarrier<'ctx, 'a, W>
764where
765 W: 'a + DemangleWrite,
766 'a: 'ctx,
767{
768 pub fn new(ctx: &'ctx mut DemangleContext<'a, W>) -> Self {
770 let mut saved_inner = vec![];
771 mem::swap(&mut saved_inner, &mut ctx.inner);
772 AutoDemangleContextInnerBarrier {
773 ctx: ctx,
774 saved_inner: saved_inner,
775 }
776 }
777}
778
779impl<'ctx, 'a, W> ops::Deref for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
780where
781 W: 'a + DemangleWrite,
782 'a: 'ctx,
783{
784 type Target = DemangleContext<'a, W>;
785
786 fn deref(&self) -> &Self::Target {
787 self.ctx
788 }
789}
790
791impl<'ctx, 'a, W> ops::DerefMut for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
792where
793 W: 'a + DemangleWrite,
794 'a: 'ctx,
795{
796 fn deref_mut(&mut self) -> &mut Self::Target {
797 self.ctx
798 }
799}
800
801impl<'ctx, 'a, W> Drop for AutoDemangleContextInnerBarrier<'ctx, 'a, W>
802where
803 W: 'a + DemangleWrite,
804 'a: 'ctx,
805{
806 fn drop(&mut self) {
807 if !self.ctx.inner.is_empty() {
811 log!("Context inner was not emptied, did demangling fail?");
812 }
813 mem::swap(&mut self.saved_inner, &mut self.ctx.inner);
814 }
815}
816
817macro_rules! inner_barrier {
834 ( $ctx:ident ) => {
835 let mut _ctx = AutoDemangleContextInnerBarrier::new($ctx);
836 let $ctx = &mut _ctx;
837 };
838}
839
840#[doc(hidden)]
842pub trait Demangle<'subs, W>: fmt::Debug
843where
844 W: 'subs + DemangleWrite,
845{
846 fn demangle<'prev, 'ctx>(
848 &'subs self,
849 ctx: &'ctx mut DemangleContext<'subs, W>,
850 scope: Option<ArgScopeStack<'prev, 'subs>>,
851 ) -> fmt::Result;
852}
853
854#[doc(hidden)]
858pub trait DemangleAsInner<'subs, W>: Demangle<'subs, W>
859where
860 W: 'subs + DemangleWrite,
861{
862 fn demangle_as_inner<'prev, 'ctx>(
864 &'subs self,
865 ctx: &'ctx mut DemangleContext<'subs, W>,
866 scope: Option<ArgScopeStack<'prev, 'subs>>,
867 ) -> fmt::Result {
868 self.demangle(ctx, scope)
869 }
870
871 fn downcast_to_type(&self) -> Option<&Type> {
873 None
874 }
875
876 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
878 None
879 }
880
881 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
883 None
884 }
885
886 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
888 None
889 }
890
891 fn is_qualified(&self) -> bool {
892 false
893 }
894}
895
896pub(crate) trait DemangleAsLeaf<'subs, W>
902where
903 W: 'subs + DemangleWrite,
904{
905 fn demangle_as_leaf<'me, 'ctx>(
906 &'me self,
907 ctx: &'ctx mut DemangleContext<'subs, W>,
908 ) -> fmt::Result;
909}
910
911macro_rules! reference_newtype {
912 ( $newtype_name:ident , $oldtype:ty ) => {
913 #[derive(Debug)]
914 struct $newtype_name($oldtype);
915
916 impl $newtype_name {
917 #[allow(clippy::ptr_arg)]
918 #[allow(unsafe_code)]
919 fn new(types: &$oldtype) -> &$newtype_name {
920 unsafe {
921 &*(types as *const $oldtype as *const $newtype_name)
927 }
928 }
929 }
930
931 impl Drop for $newtype_name {
932 fn drop(&mut self) {
933 unreachable!(
934 "Dropping implies we dereferenced and took ownership, which \
935 is not safe for this newtype"
936 );
937 }
938 }
939
940 impl ops::Deref for $newtype_name {
941 type Target = $oldtype;
942
943 fn deref(&self) -> &Self::Target {
944 &self.0
945 }
946 }
947 };
948}
949
950reference_newtype!(FunctionArgList, Vec<TypeHandle>);
957
958reference_newtype!(FunctionArgListAndReturnType, Vec<TypeHandle>);
961
962reference_newtype!(FunctionArgSlice, [TypeHandle]);
965
966impl<'subs, W> Demangle<'subs, W> for FunctionArgSlice
968where
969 W: 'subs + DemangleWrite,
970{
971 fn demangle<'prev, 'ctx>(
972 &'subs self,
973 ctx: &'ctx mut DemangleContext<'subs, W>,
974 scope: Option<ArgScopeStack<'prev, 'subs>>,
975 ) -> fmt::Result {
976 let ctx = try_begin_demangle!(self, ctx, scope);
977
978 let mut saw_needs_paren = false;
979 let (needs_space, needs_paren) = ctx
980 .inner
981 .iter()
982 .rev()
983 .map(|inner| {
984 if inner.downcast_to_pointer_to_member().is_some() {
985 (true, true)
986 } else {
987 match inner.downcast_to_type() {
988 Some(&Type::Qualified(..))
989 | Some(&Type::Complex(_))
990 | Some(&Type::Imaginary(_))
991 | Some(&Type::PointerToMember(_)) => (true, true),
992 Some(&Type::PointerTo(_))
993 | Some(&Type::LvalueRef(_))
994 | Some(&Type::RvalueRef(_)) => (false, true),
995 _ => (false, false),
996 }
997 }
998 })
999 .take_while(|&(_, needs_paren)| {
1000 if saw_needs_paren {
1001 false
1002 } else {
1003 saw_needs_paren |= needs_paren;
1004 true
1005 }
1006 })
1007 .fold(
1008 (false, false),
1009 |(space, paren), (next_space, next_paren)| {
1010 (space || next_space, paren || next_paren)
1011 },
1012 );
1013
1014 if needs_paren {
1015 let needs_space = needs_space
1016 || match ctx.last_char_written {
1017 Some('(') | Some('*') => false,
1018 _ => true,
1019 };
1020
1021 if needs_space {
1022 ctx.ensure_space()?;
1023 }
1024
1025 write!(ctx, "(")?;
1026 }
1027
1028 ctx.demangle_inner_prefixes(scope)?;
1029
1030 if needs_paren {
1031 write!(ctx, ")")?;
1032 }
1033
1034 write!(ctx, "(")?;
1035
1036 if self.len() == 1 && self[0].is_void() {
1039 write!(ctx, ")")?;
1040 return Ok(());
1041 }
1042
1043 if ctx.is_explicit_obj_param {
1045 write!(ctx, "this ")?;
1046 ctx.is_explicit_obj_param = false;
1047 }
1048
1049 let mut need_comma = false;
1050 for arg in self.iter() {
1051 if need_comma {
1052 write!(ctx, ", ")?;
1053 }
1054 arg.demangle(ctx, scope)?;
1055 need_comma = true;
1056 }
1057
1058 write!(ctx, ")")?;
1059
1060 ctx.demangle_inners(scope)
1061 }
1062}
1063
1064impl<'subs, W> Demangle<'subs, W> for FunctionArgList
1065where
1066 W: 'subs + DemangleWrite,
1067{
1068 fn demangle<'prev, 'ctx>(
1069 &'subs self,
1070 ctx: &'ctx mut DemangleContext<'subs, W>,
1071 scope: Option<ArgScopeStack<'prev, 'subs>>,
1072 ) -> fmt::Result {
1073 FunctionArgSlice::new(&self.0[..]).demangle(ctx, scope)
1074 }
1075}
1076
1077impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgList where W: 'subs + DemangleWrite {}
1078
1079impl<'subs, W> Demangle<'subs, W> for FunctionArgListAndReturnType
1080where
1081 W: 'subs + DemangleWrite,
1082{
1083 fn demangle<'prev, 'ctx>(
1084 &'subs self,
1085 ctx: &'ctx mut DemangleContext<'subs, W>,
1086 scope: Option<ArgScopeStack<'prev, 'subs>>,
1087 ) -> fmt::Result {
1088 FunctionArgSlice::new(&self.0[1..]).demangle(ctx, scope)
1089 }
1090}
1091
1092impl<'subs, W> DemangleAsInner<'subs, W> for FunctionArgListAndReturnType where
1093 W: 'subs + DemangleWrite
1094{
1095}
1096
1097macro_rules! define_handle {
1108 (
1109 $(#[$attr:meta])*
1110 pub enum $typename:ident
1111 ) => {
1112 define_handle! {
1113 $(#[$attr])*
1114 pub enum $typename {}
1115 }
1116 };
1117
1118 (
1119 $(#[$attr:meta])*
1120 pub enum $typename:ident {
1121 $(
1122 $( #[$extra_attr:meta] )*
1123 extra $extra_variant:ident ( $extra_variant_ty:ty ),
1124 )*
1125 }
1126 ) => {
1127 $(#[$attr])*
1128 #[derive(Clone, Debug, PartialEq, Eq)]
1129 pub enum $typename {
1130 WellKnown(WellKnownComponent),
1132
1133 BackReference(usize),
1136
1137 $(
1138 $( #[$extra_attr] )*
1139 $extra_variant( $extra_variant_ty ),
1140 )*
1141 }
1142
1143 impl $typename {
1144 pub fn back_reference(&self) -> Option<usize> {
1146 match *self {
1147 $typename::BackReference(n) => Some(n),
1148 _ => None,
1149 }
1150 }
1151 }
1152
1153 impl<'subs, W> Demangle<'subs, W> for $typename
1154 where
1155 W: 'subs + DemangleWrite
1156 {
1157 #[inline]
1158 fn demangle<'prev, 'ctx>(&'subs self,
1159 ctx: &'ctx mut DemangleContext<'subs, W>,
1160 scope: Option<ArgScopeStack<'prev, 'subs>>)
1161 -> fmt::Result {
1162 match *self {
1163 $typename::WellKnown(ref comp) => comp.demangle(ctx, scope),
1164 $typename::BackReference(idx) => ctx.subs[idx].demangle(ctx, scope),
1165 $(
1166 $typename::$extra_variant(ref extra) => extra.demangle(ctx, scope),
1167 )*
1168 }
1169 }
1170 }
1171
1172 impl<'a> GetLeafName<'a> for $typename {
1173 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1174 match *self {
1175 $typename::WellKnown(ref wk) => wk.get_leaf_name(subs),
1176 $typename::BackReference(idx) => {
1177 subs.get(idx).and_then(|s| s.get_leaf_name(subs))
1178 }
1179 $(
1180 $typename::$extra_variant(ref e) => e.get_leaf_name(subs),
1181 )*
1182 }
1183 }
1184 }
1185 };
1186}
1187
1188#[derive(Clone, Debug, PartialEq, Eq)]
1192pub struct NonSubstitution(usize);
1193
1194impl<'subs, W> Demangle<'subs, W> for NonSubstitution
1195where
1196 W: 'subs + DemangleWrite,
1197{
1198 fn demangle<'prev, 'ctx>(
1199 &'subs self,
1200 ctx: &'ctx mut DemangleContext<'subs, W>,
1201 scope: Option<ArgScopeStack<'prev, 'subs>>,
1202 ) -> fmt::Result {
1203 ctx.subs.non_substitution(self.0).demangle(ctx, scope)
1204 }
1205}
1206
1207impl<'a> GetLeafName<'a> for NonSubstitution {
1208 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1209 subs.get_non_substitution(self.0)
1210 .and_then(|ns| ns.get_leaf_name(subs))
1211 }
1212}
1213
1214macro_rules! define_vocabulary {
1229 ( $(#[$attr:meta])* pub enum $typename:ident {
1230 $($variant:ident ( $mangled:expr, $printable:expr )),*
1231 } ) => {
1232
1233 $(#[$attr])*
1234 pub enum $typename {
1235 $(
1236 #[doc=$printable]
1237 $variant
1238 ),*
1239 }
1240
1241 impl Parse for $typename {
1242 fn parse<'a, 'b>(ctx: &'a ParseContext,
1243 _subs: &'a mut SubstitutionTable,
1244 input: IndexStr<'b>)
1245 -> Result<($typename, IndexStr<'b>)> {
1246 try_begin_parse!(stringify!($typename), ctx, input);
1247
1248 let mut found_prefix = false;
1249 $(
1250 if let Some((head, tail)) = input.try_split_at($mangled.len()) {
1251 if head.as_ref() == $mangled {
1252 return Ok(($typename::$variant, tail));
1253 }
1254 } else {
1255 found_prefix |= 0 < input.len() &&
1256 input.len() < $mangled.len() &&
1257 input.as_ref() == &$mangled[..input.len()];
1258 }
1259 )*
1260
1261 if input.is_empty() || found_prefix {
1262 Err(error::Error::UnexpectedEnd)
1263 } else {
1264 Err(error::Error::UnexpectedText)
1265 }
1266 }
1267 }
1268
1269 impl<'subs, W> Demangle<'subs, W> for $typename
1270 where
1271 W: 'subs + DemangleWrite,
1272 {
1273 fn demangle<'prev, 'ctx>(
1274 &'subs self,
1275 ctx: &'ctx mut DemangleContext<'subs, W>,
1276 scope: Option<ArgScopeStack<'prev, 'subs>>
1277 ) -> fmt::Result {
1278 let ctx = try_begin_demangle!(self, ctx, scope);
1279
1280 write!(ctx, "{}", match *self {
1281 $(
1282 $typename::$variant => $printable
1283 ),*
1284 })
1285 }
1286 }
1287
1288 impl $typename {
1289 #[allow(dead_code)]
1290 #[inline]
1291 fn starts_with(byte: u8) -> bool {
1292 $(
1293 if $mangled[0] == byte {
1294 return true;
1295 }
1296 )*
1297
1298 false
1299 }
1300 }
1301 };
1302 ( $(#[$attr:meta])* pub enum $typename:ident {
1303 $($variant:ident ( $mangled:expr, $printable:expr, $userdata:expr)),*
1304 }
1305
1306 impl $typename2:ident {
1307 fn $fn_name:ident(&self) -> $userdata_ty:ty;
1308 } ) => {
1309 define_vocabulary! {
1310 $(#[$attr])*
1311 pub enum $typename {
1312 $(
1313 $variant ( $mangled, $printable )
1314 ),*
1315 }
1316 }
1317
1318 impl $typename2 {
1319 fn $fn_name(&self) -> $userdata_ty {
1320 match *self {
1321 $(
1322 $typename2::$variant => $userdata,
1323 )*
1324 }
1325 }
1326 }
1327 };
1328}
1329
1330#[derive(Clone, Debug, PartialEq, Eq)]
1342pub enum MangledName {
1343 Encoding(Encoding, Vec<CloneSuffix>),
1345
1346 BlockInvoke(Encoding, Option<isize>),
1348
1349 Type(TypeHandle),
1352
1353 GlobalCtorDtor(GlobalCtorDtor),
1357}
1358
1359impl Parse for MangledName {
1360 fn parse<'a, 'b>(
1361 ctx: &'a ParseContext,
1362 subs: &'a mut SubstitutionTable,
1363 input: IndexStr<'b>,
1364 ) -> Result<(MangledName, IndexStr<'b>)> {
1365 try_begin_parse!("MangledName", ctx, input);
1366
1367 if let Ok(tail) = consume(b"_Z", input).or_else(|_| consume(b"__Z", input)) {
1368 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1369 let (clone_suffixes, tail) = zero_or_more(ctx, subs, tail)?;
1370 return Ok((MangledName::Encoding(encoding, clone_suffixes), tail));
1371 }
1372
1373 if let Ok(tail) = consume(b"___Z", input).or_else(|_| consume(b"____Z", input)) {
1374 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
1375 let tail = consume(b"_block_invoke", tail)?;
1376
1377 let tail_opt = match consume(b"_", tail).or_else(|_| consume(b".", tail)) {
1378 Ok(tail) => Some(parse_number(10, false, tail)?),
1379 Err(_) => parse_number(10, false, tail).ok(),
1380 };
1381
1382 let (digits, tail) = match tail_opt {
1383 Some((digits, tail)) => (Some(digits), tail),
1384 None => (None, tail),
1385 };
1386
1387 return Ok((MangledName::BlockInvoke(encoding, digits), tail));
1388 }
1389
1390 if let Ok(tail) = consume(b"_GLOBAL_", input) {
1391 let (global_ctor_dtor, tail) = GlobalCtorDtor::parse(ctx, subs, tail)?;
1392 return Ok((MangledName::GlobalCtorDtor(global_ctor_dtor), tail));
1393 }
1394
1395 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
1398 Ok((MangledName::Type(ty), tail))
1399 }
1400}
1401
1402impl<'subs, W> Demangle<'subs, W> for MangledName
1403where
1404 W: 'subs + DemangleWrite,
1405{
1406 fn demangle<'prev, 'ctx>(
1407 &'subs self,
1408 ctx: &'ctx mut DemangleContext<'subs, W>,
1409 scope: Option<ArgScopeStack<'prev, 'subs>>,
1410 ) -> fmt::Result {
1411 let ctx = try_begin_demangle!(self, ctx, scope);
1412
1413 match *self {
1414 MangledName::Encoding(ref enc, ref cs) => {
1415 enc.demangle(ctx, scope)?;
1416 if !cs.is_empty() && ctx.show_params {
1417 for clone_suffix in cs {
1418 clone_suffix.demangle(ctx, scope)?;
1419 }
1420 }
1421 Ok(())
1422 }
1423 MangledName::BlockInvoke(ref enc, _) => {
1424 write!(ctx, "invocation function for block in ")?;
1425 enc.demangle(ctx, scope)?;
1426 Ok(())
1427 }
1428 MangledName::Type(ref ty) => ty.demangle(ctx, scope),
1429 MangledName::GlobalCtorDtor(ref gcd) => gcd.demangle(ctx, scope),
1430 }
1431 }
1432}
1433
1434#[derive(Clone, Debug, PartialEq, Eq)]
1442pub enum Encoding {
1443 Function(Name, BareFunctionType),
1445
1446 Data(Name),
1448
1449 Special(SpecialName),
1451}
1452
1453impl Parse for Encoding {
1454 fn parse<'a, 'b>(
1455 ctx: &'a ParseContext,
1456 subs: &'a mut SubstitutionTable,
1457 input: IndexStr<'b>,
1458 ) -> Result<(Encoding, IndexStr<'b>)> {
1459 try_begin_parse!("Encoding", ctx, input);
1460
1461 if let Ok((name, tail)) = try_recurse!(Name::parse(ctx, subs, input)) {
1462 if let Ok((ty, tail)) = try_recurse!(BareFunctionType::parse(ctx, subs, tail)) {
1463 return Ok((Encoding::Function(name, ty), tail));
1464 } else {
1465 return Ok((Encoding::Data(name), tail));
1466 }
1467 }
1468
1469 let (name, tail) = SpecialName::parse(ctx, subs, input)?;
1470 Ok((Encoding::Special(name), tail))
1471 }
1472}
1473
1474impl<'subs, W> Demangle<'subs, W> for Encoding
1475where
1476 W: 'subs + DemangleWrite,
1477{
1478 fn demangle<'prev, 'ctx>(
1479 &'subs self,
1480 ctx: &'ctx mut DemangleContext<'subs, W>,
1481 scope: Option<ArgScopeStack<'prev, 'subs>>,
1482 ) -> fmt::Result {
1483 let ctx = try_begin_demangle!(self, ctx, scope);
1484 inner_barrier!(ctx);
1485
1486 match *self {
1487 Encoding::Function(ref name, ref fun_ty) => {
1488 debug_assert!(!fun_ty.0.is_empty());
1491
1492 let scope = if let Some(leaf) = name.get_leaf_name(ctx.subs) {
1493 match leaf {
1494 LeafName::SourceName(leaf) => scope.push(leaf),
1495 LeafName::WellKnownComponent(leaf) => scope.push(leaf),
1496 LeafName::Closure(leaf) => scope.push(leaf),
1497 LeafName::UnnamedType(leaf) => scope.push(leaf),
1498 }
1499 } else {
1500 scope
1501 };
1502
1503 let scope = if let Some(template_args) = name.get_template_args(ctx.subs) {
1520 let scope = scope.push(template_args);
1521 if ctx.show_return_type && !name.is_ctor_dtor_conversion(ctx.subs) {
1522 fun_ty.0[0].demangle(ctx, scope)?;
1523 write!(ctx, " ")?;
1524 }
1525
1526 scope
1527 } else {
1528 scope
1529 };
1530
1531 if ctx.show_params {
1532 ctx.push_inner(self);
1533 name.demangle(ctx, scope)?;
1534 if ctx.pop_inner_if(self) {
1535 self.demangle_as_inner(ctx, scope)?;
1536 }
1537 } else {
1538 name.demangle(ctx, scope)?;
1539 }
1540
1541 Ok(())
1542 }
1543 Encoding::Data(ref name) => name.demangle(ctx, scope),
1544 Encoding::Special(ref name) => name.demangle(ctx, scope),
1545 }
1546 }
1547}
1548
1549impl<'subs, W> DemangleAsInner<'subs, W> for Encoding
1550where
1551 W: 'subs + DemangleWrite,
1552{
1553 fn demangle_as_inner<'prev, 'ctx>(
1554 &'subs self,
1555 ctx: &'ctx mut DemangleContext<'subs, W>,
1556 scope: Option<ArgScopeStack<'prev, 'subs>>,
1557 ) -> fmt::Result {
1558 if let Encoding::Function(ref name, ref fun_ty) = *self {
1559 let (scope, function_args) =
1560 if let Some(template_args) = name.get_template_args(ctx.subs) {
1561 let scope = scope.push(template_args);
1562 let function_args = FunctionArgListAndReturnType::new(&fun_ty.0);
1563 (scope, function_args as &dyn DemangleAsInner<W>)
1564 } else {
1565 let function_args = FunctionArgList::new(&fun_ty.0);
1566 (scope, function_args as &dyn DemangleAsInner<W>)
1567 };
1568 function_args.demangle_as_inner(ctx, scope)
1569 } else {
1570 unreachable!("we only push Encoding::Function onto the inner stack");
1571 }
1572 }
1573}
1574
1575#[derive(Clone, Debug, PartialEq, Eq)]
1578pub struct CloneSuffix(CloneTypeIdentifier, Vec<isize>);
1579
1580impl Parse for CloneSuffix {
1581 fn parse<'a, 'b>(
1582 ctx: &'a ParseContext,
1583 subs: &'a mut SubstitutionTable,
1584 input: IndexStr<'b>,
1585 ) -> Result<(CloneSuffix, IndexStr<'b>)> {
1586 try_begin_parse!("CloneSuffix", ctx, input);
1587
1588 let tail = consume(b".", input)?;
1589 let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?;
1590
1591 let mut numbers = Vec::with_capacity(1);
1592 while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) {
1593 numbers.push(n);
1594 tail = t;
1595 }
1596
1597 let clone_suffix = CloneSuffix(identifier, numbers);
1598 Ok((clone_suffix, tail))
1599 }
1600}
1601
1602impl<'subs, W> Demangle<'subs, W> for CloneSuffix
1603where
1604 W: 'subs + DemangleWrite,
1605{
1606 fn demangle<'prev, 'ctx>(
1607 &'subs self,
1608 ctx: &'ctx mut DemangleContext<'subs, W>,
1609 scope: Option<ArgScopeStack<'prev, 'subs>>,
1610 ) -> fmt::Result {
1611 let ctx = try_begin_demangle!(self, ctx, scope);
1612 write!(ctx, " [clone")?;
1613 self.0.demangle(ctx, scope)?;
1614 for nonnegative in &self.1 {
1615 write!(ctx, ".{}", nonnegative)?;
1616 }
1617 write!(ctx, "]")?;
1618 Ok(())
1619 }
1620}
1621
1622#[derive(Clone, Debug, PartialEq, Eq)]
1624pub enum GlobalCtorDtor {
1625 Ctor(Box<MangledName>),
1627 Dtor(Box<MangledName>),
1629}
1630
1631impl Parse for GlobalCtorDtor {
1632 fn parse<'a, 'b>(
1633 ctx: &'a ParseContext,
1634 subs: &'a mut SubstitutionTable,
1635 input: IndexStr<'b>,
1636 ) -> Result<(GlobalCtorDtor, IndexStr<'b>)> {
1637 try_begin_parse!("GlobalCtorDtor", ctx, input);
1638
1639 let tail = match input.next_or(error::Error::UnexpectedEnd)? {
1640 (b'_', t) | (b'.', t) | (b'$', t) => t,
1641 _ => return Err(error::Error::UnexpectedText),
1642 };
1643
1644 match tail.next_or(error::Error::UnexpectedEnd)? {
1645 (b'I', tail) => {
1646 let tail = consume(b"_", tail)?;
1647 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1648 Ok((GlobalCtorDtor::Ctor(Box::new(name)), tail))
1649 }
1650 (b'D', tail) => {
1651 let tail = consume(b"_", tail)?;
1652 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
1653 Ok((GlobalCtorDtor::Dtor(Box::new(name)), tail))
1654 }
1655 _ => Err(error::Error::UnexpectedText),
1656 }
1657 }
1658}
1659
1660impl<'subs, W> Demangle<'subs, W> for GlobalCtorDtor
1661where
1662 W: 'subs + DemangleWrite,
1663{
1664 fn demangle<'prev, 'ctx>(
1665 &'subs self,
1666 ctx: &'ctx mut DemangleContext<'subs, W>,
1667 scope: Option<ArgScopeStack<'prev, 'subs>>,
1668 ) -> fmt::Result {
1669 let ctx = try_begin_demangle!(self, ctx, scope);
1670 inner_barrier!(ctx);
1671
1672 let saved_show_params = ctx.show_params;
1673 ctx.show_params = true;
1674 let ret = match *self {
1675 GlobalCtorDtor::Ctor(ref name) => {
1676 write!(ctx, "global constructors keyed to ")?;
1677 name.demangle(ctx, scope)
1678 }
1679 GlobalCtorDtor::Dtor(ref name) => {
1680 write!(ctx, "global destructors keyed to ")?;
1681 name.demangle(ctx, scope)
1682 }
1683 };
1684 ctx.show_params = saved_show_params;
1685 ret
1686 }
1687}
1688
1689#[derive(Clone, Debug, PartialEq, Eq)]
1698pub enum Name {
1699 Nested(NestedName),
1701
1702 Unscoped(UnscopedName),
1704
1705 UnscopedTemplate(UnscopedTemplateNameHandle, TemplateArgs),
1707
1708 Local(LocalName),
1710}
1711
1712impl Parse for Name {
1713 fn parse<'a, 'b>(
1714 ctx: &'a ParseContext,
1715 subs: &'a mut SubstitutionTable,
1716 input: IndexStr<'b>,
1717 ) -> Result<(Name, IndexStr<'b>)> {
1718 try_begin_parse!("Name", ctx, input);
1719
1720 if let Ok((name, tail)) = try_recurse!(NestedName::parse(ctx, subs, input)) {
1721 return Ok((Name::Nested(name), tail));
1722 }
1723
1724 if let Ok((name, tail)) = try_recurse!(UnscopedName::parse(ctx, subs, input)) {
1725 if tail.peek() == Some(b'I') {
1726 let name = UnscopedTemplateName(name);
1727 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1728 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1729
1730 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1731 return Ok((Name::UnscopedTemplate(handle, args), tail));
1732 } else {
1733 return Ok((Name::Unscoped(name), tail));
1734 }
1735 }
1736
1737 if let Ok((name, tail)) = try_recurse!(UnscopedTemplateNameHandle::parse(ctx, subs, input))
1738 {
1739 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
1740 return Ok((Name::UnscopedTemplate(name, args), tail));
1741 }
1742
1743 let (name, tail) = LocalName::parse(ctx, subs, input)?;
1744 Ok((Name::Local(name), tail))
1745 }
1746}
1747
1748impl<'subs, W> Demangle<'subs, W> for Name
1749where
1750 W: 'subs + DemangleWrite,
1751{
1752 fn demangle<'prev, 'ctx>(
1753 &'subs self,
1754 ctx: &'ctx mut DemangleContext<'subs, W>,
1755 scope: Option<ArgScopeStack<'prev, 'subs>>,
1756 ) -> fmt::Result {
1757 let ctx = try_begin_demangle!(self, ctx, scope);
1758
1759 match *self {
1760 Name::Nested(ref nested) => nested.demangle(ctx, scope),
1761 Name::Unscoped(ref unscoped) => unscoped.demangle(ctx, scope),
1762 Name::UnscopedTemplate(ref template, ref args) => {
1763 template.demangle(ctx, scope.push(args))?;
1764 args.demangle(ctx, scope)
1765 }
1766 Name::Local(ref local) => local.demangle(ctx, scope),
1767 }
1768 }
1769}
1770
1771impl GetTemplateArgs for Name {
1772 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
1773 match *self {
1774 Name::UnscopedTemplate(_, ref args) => Some(args),
1775 Name::Nested(ref nested) => nested.get_template_args(subs),
1776 Name::Local(ref local) => local.get_template_args(subs),
1777 Name::Unscoped(_) => None,
1778 }
1779 }
1780}
1781
1782impl<'a> GetLeafName<'a> for Name {
1783 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1784 match *self {
1785 Name::UnscopedTemplate(ref templ, _) => templ.get_leaf_name(subs),
1786 Name::Nested(ref nested) => nested.get_leaf_name(subs),
1787 Name::Unscoped(ref unscoped) => unscoped.get_leaf_name(subs),
1788 Name::Local(ref local) => local.get_leaf_name(subs),
1789 }
1790 }
1791}
1792
1793impl IsCtorDtorConversion for Name {
1794 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1795 match *self {
1796 Name::Unscoped(ref unscoped) => unscoped.is_ctor_dtor_conversion(subs),
1797 Name::Nested(ref nested) => nested.is_ctor_dtor_conversion(subs),
1798 Name::Local(_) | Name::UnscopedTemplate(..) => false,
1799 }
1800 }
1801}
1802
1803#[derive(Clone, Debug, PartialEq, Eq)]
1810pub enum UnscopedName {
1811 Unqualified(UnqualifiedName),
1813
1814 Std(UnqualifiedName),
1816}
1817
1818impl Parse for UnscopedName {
1819 fn parse<'a, 'b>(
1820 ctx: &'a ParseContext,
1821 subs: &'a mut SubstitutionTable,
1822 input: IndexStr<'b>,
1823 ) -> Result<(UnscopedName, IndexStr<'b>)> {
1824 try_begin_parse!("UnscopedName", ctx, input);
1825
1826 if let Ok(tail) = consume(b"St", input) {
1827 let (name, tail) = UnqualifiedName::parse(ctx, subs, tail)?;
1828 return Ok((UnscopedName::Std(name), tail));
1829 }
1830
1831 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
1832 Ok((UnscopedName::Unqualified(name), tail))
1833 }
1834}
1835
1836impl<'subs, W> Demangle<'subs, W> for UnscopedName
1837where
1838 W: 'subs + DemangleWrite,
1839{
1840 fn demangle<'prev, 'ctx>(
1841 &'subs self,
1842 ctx: &'ctx mut DemangleContext<'subs, W>,
1843 scope: Option<ArgScopeStack<'prev, 'subs>>,
1844 ) -> fmt::Result {
1845 let ctx = try_begin_demangle!(self, ctx, scope);
1846
1847 match *self {
1848 UnscopedName::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
1849 UnscopedName::Std(ref std) => {
1850 write!(ctx, "std::")?;
1851 std.demangle(ctx, scope)
1852 }
1853 }
1854 }
1855}
1856
1857impl<'a> GetLeafName<'a> for UnscopedName {
1858 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1859 match *self {
1860 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1861 name.get_leaf_name(subs)
1862 }
1863 }
1864 }
1865}
1866
1867impl IsCtorDtorConversion for UnscopedName {
1868 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
1869 match *self {
1870 UnscopedName::Unqualified(ref name) | UnscopedName::Std(ref name) => {
1871 name.is_ctor_dtor_conversion(subs)
1872 }
1873 }
1874 }
1875}
1876
1877#[derive(Clone, Debug, PartialEq, Eq)]
1884pub struct UnscopedTemplateName(UnscopedName);
1885
1886define_handle! {
1887 pub enum UnscopedTemplateNameHandle {
1889 extra NonSubstitution(NonSubstitution),
1892 }
1893}
1894
1895impl Parse for UnscopedTemplateNameHandle {
1896 fn parse<'a, 'b>(
1897 ctx: &'a ParseContext,
1898 subs: &'a mut SubstitutionTable,
1899 input: IndexStr<'b>,
1900 ) -> Result<(UnscopedTemplateNameHandle, IndexStr<'b>)> {
1901 try_begin_parse!("UnscopedTemplateNameHandle", ctx, input);
1902
1903 if let Ok((name, tail)) = try_recurse!(UnscopedName::parse(ctx, subs, input)) {
1904 let name = UnscopedTemplateName(name);
1905 let idx = subs.insert(Substitutable::UnscopedTemplateName(name));
1906 let handle = UnscopedTemplateNameHandle::BackReference(idx);
1907 return Ok((handle, tail));
1908 }
1909
1910 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
1911
1912 match sub {
1913 Substitution::WellKnown(component) => {
1914 Ok((UnscopedTemplateNameHandle::WellKnown(component), tail))
1915 }
1916 Substitution::BackReference(idx) => {
1917 Ok((UnscopedTemplateNameHandle::BackReference(idx), tail))
1920 }
1921 }
1922 }
1923}
1924
1925impl<'subs, W> Demangle<'subs, W> for UnscopedTemplateName
1926where
1927 W: 'subs + DemangleWrite,
1928{
1929 fn demangle<'prev, 'ctx>(
1930 &'subs self,
1931 ctx: &'ctx mut DemangleContext<'subs, W>,
1932 scope: Option<ArgScopeStack<'prev, 'subs>>,
1933 ) -> fmt::Result {
1934 let ctx = try_begin_demangle!(self, ctx, scope);
1935
1936 self.0.demangle(ctx, scope)
1937 }
1938}
1939
1940impl<'a> GetLeafName<'a> for UnscopedTemplateName {
1941 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
1942 self.0.get_leaf_name(subs)
1943 }
1944}
1945
1946#[derive(Clone, Debug, PartialEq, Eq)]
1955pub enum NestedName {
1956 Unqualified(
1958 CvQualifiers,
1959 Option<RefQualifier>,
1960 Option<PrefixHandle>,
1961 UnqualifiedName,
1962 ),
1963
1964 Template(CvQualifiers, Option<RefQualifier>, PrefixHandle),
1966
1967 UnqualifiedExplicitObject(
1969 Option<PrefixHandle>,
1970 UnqualifiedName,
1971 ExplicitObjectParameter,
1972 ),
1973
1974 TemplateExplicitObject(PrefixHandle, ExplicitObjectParameter),
1976}
1977
1978impl Parse for NestedName {
1979 fn parse<'a, 'b>(
1980 ctx: &'a ParseContext,
1981 subs: &'a mut SubstitutionTable,
1982 input: IndexStr<'b>,
1983 ) -> Result<(NestedName, IndexStr<'b>)> {
1984 try_begin_parse!("NestedName", ctx, input);
1985
1986 let tail = consume(b"N", input)?;
1987
1988 let (cv_qualifiers, ref_qualifier, explicit_obj_param, tail) = match tail.peek() {
1989 Some(b'H') => {
1990 let (explicit_obj_param, tail) = ExplicitObjectParameter::parse(ctx, subs, tail)?;
1991 (Default::default(), None, Some(explicit_obj_param), tail)
1992 }
1993 _ => {
1994 let (cv_qualifiers, tail) =
1995 if let Ok((q, tail)) = try_recurse!(CvQualifiers::parse(ctx, subs, tail)) {
1996 (q, tail)
1997 } else {
1998 (Default::default(), tail)
1999 };
2000
2001 let (ref_qualifier, tail) =
2002 if let Ok((r, tail)) = try_recurse!(RefQualifier::parse(ctx, subs, tail)) {
2003 (Some(r), tail)
2004 } else {
2005 (None, tail)
2006 };
2007
2008 (cv_qualifiers, ref_qualifier, None, tail)
2009 }
2010 };
2011
2012 let (prefix, tail) = PrefixHandle::parse(ctx, subs, tail)?;
2013 let tail = consume(b"E", tail)?;
2014
2015 let substitutable = match prefix {
2016 PrefixHandle::BackReference(idx) => subs.get(idx),
2017 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => subs.get_non_substitution(idx),
2018 PrefixHandle::WellKnown(_) => None,
2019 };
2020
2021 match (substitutable, explicit_obj_param) {
2022 (Some(&Substitutable::Prefix(Prefix::Unqualified(ref name))), None) => Ok((
2023 NestedName::Unqualified(cv_qualifiers, ref_qualifier, None, name.clone()),
2024 tail,
2025 )),
2026 (Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))), None) => Ok((
2027 NestedName::Unqualified(
2028 cv_qualifiers,
2029 ref_qualifier,
2030 Some(prefix.clone()),
2031 name.clone(),
2032 ),
2033 tail,
2034 )),
2035 (Some(&Substitutable::Prefix(Prefix::Template(..))), None) => Ok((
2036 NestedName::Template(cv_qualifiers, ref_qualifier, prefix),
2037 tail,
2038 )),
2039 (Some(&Substitutable::Prefix(Prefix::Unqualified(ref name))), Some(param)) => Ok((
2040 NestedName::UnqualifiedExplicitObject(None, name.clone(), param),
2041 tail,
2042 )),
2043 (Some(&Substitutable::Prefix(Prefix::Nested(ref prefix, ref name))), Some(param)) => {
2044 Ok((
2045 NestedName::UnqualifiedExplicitObject(
2046 Some(prefix.clone()),
2047 name.clone(),
2048 param,
2049 ),
2050 tail,
2051 ))
2052 }
2053 (Some(&Substitutable::Prefix(Prefix::Template(..))), Some(param)) => {
2054 Ok((NestedName::TemplateExplicitObject(prefix, param), tail))
2055 }
2056 _ => Err(error::Error::UnexpectedText),
2057 }
2058 }
2059}
2060
2061impl NestedName {
2062 pub fn cv_qualifiers(&self) -> Option<&CvQualifiers> {
2064 match *self {
2065 NestedName::Unqualified(ref q, ..) | NestedName::Template(ref q, ..) => Some(q),
2066 _ => None,
2067 }
2068 }
2069
2070 pub fn ref_qualifier(&self) -> Option<&RefQualifier> {
2072 match *self {
2073 NestedName::Unqualified(_, Some(ref r), ..)
2074 | NestedName::Template(_, Some(ref r), ..) => Some(r),
2075 _ => None,
2076 }
2077 }
2078
2079 fn prefix(&self) -> Option<&PrefixHandle> {
2083 match *self {
2084 NestedName::Unqualified(_, _, ref p, _)
2085 | NestedName::UnqualifiedExplicitObject(ref p, ..) => p.as_ref(),
2086 NestedName::Template(_, _, ref p) | NestedName::TemplateExplicitObject(ref p, _) => {
2087 Some(p)
2088 }
2089 }
2090 }
2091
2092 pub fn has_explicit_obj_param(&self) -> bool {
2094 match *self {
2095 NestedName::UnqualifiedExplicitObject(_, _, ref _e)
2096 | NestedName::TemplateExplicitObject(_, ref _e) => true,
2097 _ => false,
2098 }
2099 }
2100}
2101
2102impl<'subs, W> Demangle<'subs, W> for NestedName
2103where
2104 W: 'subs + DemangleWrite,
2105{
2106 fn demangle<'prev, 'ctx>(
2107 &'subs self,
2108 ctx: &'ctx mut DemangleContext<'subs, W>,
2109 scope: Option<ArgScopeStack<'prev, 'subs>>,
2110 ) -> fmt::Result {
2111 let ctx = try_begin_demangle!(self, ctx, scope);
2112
2113 match *self {
2114 NestedName::Unqualified(_, _, ref p, ref name)
2115 | NestedName::UnqualifiedExplicitObject(ref p, ref name, _) => {
2116 ctx.push_demangle_node(DemangleNodeType::NestedName);
2117 if let Some(p) = p.as_ref() {
2118 p.demangle(ctx, scope)?;
2119 ctx.write_str("::")?;
2120 }
2121 name.demangle(ctx, scope)?;
2122 ctx.pop_demangle_node();
2123 }
2124 NestedName::Template(_, _, ref p) | NestedName::TemplateExplicitObject(ref p, _) => {
2125 ctx.is_template_prefix_in_nested_name = true;
2126 p.demangle(ctx, scope)?;
2127 ctx.is_template_prefix_in_nested_name = false;
2128 }
2129 }
2130
2131 if self.has_explicit_obj_param() {
2132 ctx.is_explicit_obj_param = true;
2133 }
2134
2135 if let Some(inner) = ctx.pop_inner() {
2136 inner.demangle_as_inner(ctx, scope)?;
2137 }
2138
2139 if let Some(cv_qualifiers) = self.cv_qualifiers() {
2140 if cv_qualifiers != &CvQualifiers::default() && ctx.show_params {
2141 cv_qualifiers.demangle(ctx, scope)?;
2142 }
2143 }
2144
2145 if let Some(ref refs) = self.ref_qualifier() {
2146 ctx.ensure_space()?;
2147 refs.demangle(ctx, scope)?;
2148 }
2149
2150 Ok(())
2151 }
2152}
2153
2154impl GetTemplateArgs for NestedName {
2155 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2156 match *self {
2157 NestedName::Template(_, _, ref prefix)
2158 | NestedName::TemplateExplicitObject(ref prefix, _) => prefix.get_template_args(subs),
2159 _ => None,
2160 }
2161 }
2162}
2163
2164impl<'a> GetLeafName<'a> for NestedName {
2165 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2166 match *self {
2167 NestedName::Unqualified(_, _, ref prefix, ref name)
2168 | NestedName::UnqualifiedExplicitObject(ref prefix, ref name, _) => name
2169 .get_leaf_name(subs)
2170 .or_else(|| prefix.as_ref().and_then(|p| p.get_leaf_name(subs))),
2171 NestedName::Template(_, _, ref prefix)
2172 | NestedName::TemplateExplicitObject(ref prefix, _) => prefix.get_leaf_name(subs),
2173 }
2174 }
2175}
2176
2177impl IsCtorDtorConversion for NestedName {
2178 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2179 self.prefix()
2180 .map(|p| p.is_ctor_dtor_conversion(subs))
2181 .unwrap_or(false)
2182 }
2183}
2184
2185#[derive(Clone, Debug, PartialEq, Eq)]
2202pub enum Prefix {
2203 Unqualified(UnqualifiedName),
2205
2206 Nested(PrefixHandle, UnqualifiedName),
2208
2209 Template(PrefixHandle, TemplateArgs),
2211
2212 TemplateParam(TemplateParam),
2214
2215 Decltype(Decltype),
2217
2218 DataMember(PrefixHandle, DataMemberPrefix),
2220}
2221
2222impl GetTemplateArgs for Prefix {
2223 fn get_template_args<'a>(&'a self, _: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2224 match *self {
2225 Prefix::Template(_, ref args) => Some(args),
2226 Prefix::Unqualified(_)
2227 | Prefix::Nested(_, _)
2228 | Prefix::TemplateParam(_)
2229 | Prefix::Decltype(_)
2230 | Prefix::DataMember(_, _) => None,
2231 }
2232 }
2233}
2234
2235define_handle! {
2236 pub enum PrefixHandle {
2238 extra NonSubstitution(NonSubstitution),
2242 }
2243}
2244
2245impl Parse for PrefixHandle {
2246 fn parse<'a, 'b>(
2247 ctx: &'a ParseContext,
2248 subs: &'a mut SubstitutionTable,
2249 input: IndexStr<'b>,
2250 ) -> Result<(PrefixHandle, IndexStr<'b>)> {
2251 try_begin_parse!("PrefixHandle", ctx, input);
2252
2253 #[inline]
2254 fn save(
2255 subs: &mut SubstitutionTable,
2256 prefix: Prefix,
2257 tail_tail: IndexStr<'_>,
2258 ) -> PrefixHandle {
2259 if let Some(b'E') = tail_tail.peek() {
2260 let idx = subs.insert_non_substitution(Substitutable::Prefix(prefix));
2266 PrefixHandle::NonSubstitution(NonSubstitution(idx))
2267 } else {
2268 let idx = subs.insert(Substitutable::Prefix(prefix));
2269 PrefixHandle::BackReference(idx)
2270 }
2271 }
2272
2273 let mut tail = input;
2274 let mut current = None;
2275
2276 loop {
2277 try_begin_parse!("PrefixHandle iteration", ctx, tail);
2278
2279 match tail.peek() {
2280 Some(b'E') | None => {
2281 if let Some(handle) = current {
2282 return Ok((handle, tail));
2283 } else {
2284 return Err(error::Error::UnexpectedEnd);
2285 }
2286 }
2287 Some(b'S') => {
2288 let (sub, tail_tail) = Substitution::parse(ctx, subs, tail)?;
2290 current = Some(match sub {
2291 Substitution::WellKnown(component) => PrefixHandle::WellKnown(component),
2292 Substitution::BackReference(idx) => {
2293 PrefixHandle::BackReference(idx)
2296 }
2297 });
2298 tail = tail_tail;
2299 }
2300 Some(b'T') => {
2301 let (param, tail_tail) = TemplateParam::parse(ctx, subs, tail)?;
2303 current = Some(save(subs, Prefix::TemplateParam(param), tail_tail));
2304 tail = tail_tail;
2305 }
2306 Some(b'D') => {
2307 if let Ok((decltype, tail_tail)) =
2315 try_recurse!(Decltype::parse(ctx, subs, tail))
2316 {
2317 current = Some(save(subs, Prefix::Decltype(decltype), tail_tail));
2318 tail = tail_tail;
2319 } else {
2320 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2321 let prefix = match current {
2322 None => Prefix::Unqualified(name),
2323 Some(handle) => Prefix::Nested(handle, name),
2324 };
2325 current = Some(save(subs, prefix, tail_tail));
2326 tail = tail_tail;
2327 }
2328 }
2329 Some(b'I')
2330 if current.is_some() && current.as_ref().unwrap().is_template_prefix() =>
2331 {
2332 let (args, tail_tail) = TemplateArgs::parse(ctx, subs, tail)?;
2334 let prefix = Prefix::Template(current.unwrap(), args);
2335 current = Some(save(subs, prefix, tail_tail));
2336 tail = tail_tail;
2337 }
2338 Some(c) if current.is_some() && UnqualifiedName::starts_with(c, &tail) => {
2339 debug_assert!(UnqualifiedName::starts_with(c, &tail));
2347
2348 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2349 if tail_tail.peek() == Some(b'M') {
2350 let UnqualifiedName::Source(name, _) = name else {
2353 return Err(error::Error::UnexpectedText);
2354 };
2355 let prefix = Prefix::DataMember(current.unwrap(), DataMemberPrefix(name));
2356 current = Some(save(subs, prefix, tail_tail));
2357 tail = consume(b"M", tail_tail).unwrap();
2358 } else {
2359 let prefix = match current {
2360 None => Prefix::Unqualified(name),
2361 Some(handle) => Prefix::Nested(handle, name),
2362 };
2363 current = Some(save(subs, prefix, tail_tail));
2364 tail = tail_tail;
2365 }
2366 }
2367 Some(c) if UnqualifiedName::starts_with(c, &tail) => {
2368 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2370 let prefix = match current {
2371 None => Prefix::Unqualified(name),
2372 Some(handle) => Prefix::Nested(handle, name),
2373 };
2374 current = Some(save(subs, prefix, tail_tail));
2375 tail = tail_tail;
2376 }
2377 Some(_) => {
2378 if let Some(handle) = current {
2379 return Ok((handle, tail));
2380 } else if tail.is_empty() {
2381 return Err(error::Error::UnexpectedEnd);
2382 } else {
2383 return Err(error::Error::UnexpectedText);
2384 }
2385 }
2386 }
2387 }
2388 }
2389}
2390
2391impl<'a> GetLeafName<'a> for Prefix {
2392 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2393 match *self {
2394 Prefix::Nested(ref prefix, ref name) => name
2395 .get_leaf_name(subs)
2396 .or_else(|| prefix.get_leaf_name(subs)),
2397 Prefix::Unqualified(ref name) => name.get_leaf_name(subs),
2398 Prefix::Template(ref prefix, _) => prefix.get_leaf_name(subs),
2399 Prefix::DataMember(_, ref name) => name.get_leaf_name(subs),
2400 Prefix::TemplateParam(_) | Prefix::Decltype(_) => None,
2401 }
2402 }
2403}
2404
2405impl GetTemplateArgs for PrefixHandle {
2406 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2409 match *self {
2410 PrefixHandle::BackReference(idx) => {
2411 if let Some(&Substitutable::Prefix(ref p)) = subs.get(idx) {
2412 p.get_template_args(subs)
2413 } else {
2414 None
2415 }
2416 }
2417 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2418 if let Some(&Substitutable::Prefix(ref p)) = subs.get_non_substitution(idx) {
2419 p.get_template_args(subs)
2420 } else {
2421 None
2422 }
2423 }
2424 _ => None,
2425 }
2426 }
2427}
2428
2429impl<'subs, W> Demangle<'subs, W> for Prefix
2430where
2431 W: 'subs + DemangleWrite,
2432{
2433 fn demangle<'prev, 'ctx>(
2434 &'subs self,
2435 ctx: &'ctx mut DemangleContext<'subs, W>,
2436 scope: Option<ArgScopeStack<'prev, 'subs>>,
2437 ) -> fmt::Result {
2438 let ctx = try_begin_demangle!(self, ctx, scope);
2439 if ctx.is_template_prefix {
2440 ctx.push_demangle_node(DemangleNodeType::TemplatePrefix);
2441 ctx.is_template_prefix = false;
2442 } else if ctx.is_template_prefix_in_nested_name {
2443 ctx.push_demangle_node(DemangleNodeType::NestedName);
2444 ctx.is_template_prefix_in_nested_name = false;
2445 } else {
2446 ctx.push_demangle_node(DemangleNodeType::Prefix);
2447 }
2448
2449 let ret = match *self {
2450 Prefix::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
2451 Prefix::Nested(ref prefix, ref unqualified) => {
2452 prefix.demangle(ctx, scope)?;
2453 write!(ctx, "::")?;
2454 unqualified.demangle(ctx, scope)
2455 }
2456 Prefix::Template(ref prefix, ref args) => {
2457 ctx.is_template_prefix = true;
2458 prefix.demangle(ctx, scope)?;
2459 ctx.is_template_prefix = false;
2460 args.demangle(ctx, scope)
2461 }
2462 Prefix::TemplateParam(ref param) => param.demangle(ctx, scope),
2463 Prefix::Decltype(ref dt) => dt.demangle(ctx, scope),
2464 Prefix::DataMember(ref prefix, ref member) => {
2465 prefix.demangle(ctx, scope)?;
2466 write!(ctx, "::")?;
2467 member.demangle(ctx, scope)
2468 }
2469 };
2470 ctx.pop_demangle_node();
2471 ret
2472 }
2473}
2474
2475impl IsCtorDtorConversion for Prefix {
2476 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2477 match *self {
2478 Prefix::Unqualified(ref unqualified) | Prefix::Nested(_, ref unqualified) => {
2479 unqualified.is_ctor_dtor_conversion(subs)
2480 }
2481 Prefix::Template(ref prefix, _) => prefix.is_ctor_dtor_conversion(subs),
2482 _ => false,
2483 }
2484 }
2485}
2486
2487impl IsCtorDtorConversion for PrefixHandle {
2488 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2489 match *self {
2490 PrefixHandle::BackReference(idx) => {
2491 if let Some(sub) = subs.get(idx) {
2492 sub.is_ctor_dtor_conversion(subs)
2493 } else {
2494 false
2495 }
2496 }
2497 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2498 if let Some(sub) = subs.get_non_substitution(idx) {
2499 sub.is_ctor_dtor_conversion(subs)
2500 } else {
2501 false
2502 }
2503 }
2504 PrefixHandle::WellKnown(_) => false,
2505 }
2506 }
2507}
2508
2509impl PrefixHandle {
2510 fn is_template_prefix(&self) -> bool {
2513 match *self {
2514 PrefixHandle::BackReference(_) | PrefixHandle::WellKnown(_) => true,
2515 PrefixHandle::NonSubstitution(_) => false,
2516 }
2517 }
2518}
2519
2520#[derive(Clone, Debug, PartialEq, Eq)]
2535pub enum UnqualifiedName {
2536 Operator(OperatorName, AbiTags),
2538 CtorDtor(CtorDtorName, AbiTags),
2540 Source(SourceName, AbiTags),
2542 LocalSourceName(SourceName, Option<Discriminator>, AbiTags),
2544 UnnamedType(UnnamedTypeName, AbiTags),
2546 ClosureType(ClosureTypeName, AbiTags),
2548}
2549
2550impl Parse for UnqualifiedName {
2551 fn parse<'a, 'b>(
2552 ctx: &'a ParseContext,
2553 subs: &'a mut SubstitutionTable,
2554 input: IndexStr<'b>,
2555 ) -> Result<(UnqualifiedName, IndexStr<'b>)> {
2556 try_begin_parse!("UnqualifiedName", ctx, input);
2557
2558 if let Ok((op, tail)) = try_recurse!(OperatorName::parse(ctx, subs, input)) {
2559 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2560 return Ok((UnqualifiedName::Operator(op, abi_tags), tail));
2561 }
2562
2563 if let Ok((ctor_dtor, tail)) = try_recurse!(CtorDtorName::parse(ctx, subs, input)) {
2564 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2565 return Ok((UnqualifiedName::CtorDtor(ctor_dtor, abi_tags), tail));
2566 }
2567
2568 if let Ok(tail) = consume(b"L", input) {
2569 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2570 let (discr, tail) =
2571 if let Ok((d, t)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
2572 (Some(d), t)
2573 } else {
2574 (None, tail)
2575 };
2576 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2577 return Ok((
2578 UnqualifiedName::LocalSourceName(name, discr, abi_tags),
2579 tail,
2580 ));
2581 }
2582
2583 if let Ok((source, tail)) = try_recurse!(SourceName::parse(ctx, subs, input)) {
2584 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2585 return Ok((UnqualifiedName::Source(source, abi_tags), tail));
2586 }
2587
2588 if let Ok((closure, tail)) = try_recurse!(ClosureTypeName::parse(ctx, subs, input)) {
2589 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2590 return Ok((UnqualifiedName::ClosureType(closure, abi_tags), tail));
2591 }
2592
2593 let (unnamed, tail) = UnnamedTypeName::parse(ctx, subs, input)?;
2594 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2595 Ok((UnqualifiedName::UnnamedType(unnamed, abi_tags), tail))
2596 }
2597}
2598
2599impl<'subs, W> Demangle<'subs, W> for UnqualifiedName
2600where
2601 W: 'subs + DemangleWrite,
2602{
2603 fn demangle<'prev, 'ctx>(
2604 &'subs self,
2605 ctx: &'ctx mut DemangleContext<'subs, W>,
2606 scope: Option<ArgScopeStack<'prev, 'subs>>,
2607 ) -> fmt::Result {
2608 let ctx = try_begin_demangle!(self, ctx, scope);
2609
2610 ctx.push_demangle_node(DemangleNodeType::UnqualifiedName);
2611 let ret = match *self {
2612 UnqualifiedName::Operator(ref op_name, ref abi_tags) => {
2613 write!(ctx, "operator")?;
2614 op_name.demangle(ctx, scope)?;
2615 abi_tags.demangle(ctx, scope)
2616 }
2617 UnqualifiedName::CtorDtor(ref ctor_dtor, ref abi_tags) => {
2618 ctor_dtor.demangle(ctx, scope)?;
2619 abi_tags.demangle(ctx, scope)
2620 }
2621 UnqualifiedName::Source(ref name, ref abi_tags)
2622 | UnqualifiedName::LocalSourceName(ref name, _, ref abi_tags) => {
2623 name.demangle(ctx, scope)?;
2624 abi_tags.demangle(ctx, scope)
2625 }
2626 UnqualifiedName::UnnamedType(ref unnamed, ref abi_tags) => {
2627 unnamed.demangle(ctx, scope)?;
2628 abi_tags.demangle(ctx, scope)
2629 }
2630 UnqualifiedName::ClosureType(ref closure, ref abi_tags) => {
2631 closure.demangle(ctx, scope)?;
2632 abi_tags.demangle(ctx, scope)
2633 }
2634 };
2635 ctx.pop_demangle_node();
2636 ret
2637 }
2638}
2639
2640impl<'a> GetLeafName<'a> for UnqualifiedName {
2641 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2642 match *self {
2643 UnqualifiedName::Operator(..) | UnqualifiedName::CtorDtor(..) => None,
2644 UnqualifiedName::UnnamedType(ref name, _) => Some(LeafName::UnnamedType(name)),
2645 UnqualifiedName::ClosureType(ref closure, _) => closure.get_leaf_name(subs),
2646 UnqualifiedName::Source(ref name, _)
2647 | UnqualifiedName::LocalSourceName(ref name, ..) => Some(LeafName::SourceName(name)),
2648 }
2649 }
2650}
2651
2652impl IsCtorDtorConversion for UnqualifiedName {
2653 fn is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool {
2654 match *self {
2655 UnqualifiedName::CtorDtor(..)
2656 | UnqualifiedName::Operator(OperatorName::Conversion(_), _) => true,
2657 UnqualifiedName::Operator(..)
2658 | UnqualifiedName::Source(..)
2659 | UnqualifiedName::LocalSourceName(..)
2660 | UnqualifiedName::UnnamedType(..)
2661 | UnqualifiedName::ClosureType(..) => false,
2662 }
2663 }
2664}
2665
2666impl UnqualifiedName {
2667 #[inline]
2668 fn starts_with(byte: u8, input: &IndexStr) -> bool {
2669 byte == b'L'
2670 || OperatorName::starts_with(byte)
2671 || CtorDtorName::starts_with(byte)
2672 || SourceName::starts_with(byte)
2673 || UnnamedTypeName::starts_with(byte)
2674 || ClosureTypeName::starts_with(byte, input)
2675 }
2676}
2677
2678#[derive(Clone, Debug, PartialEq, Eq)]
2684pub struct SourceName(Identifier);
2685
2686impl Parse for SourceName {
2687 fn parse<'a, 'b>(
2688 ctx: &'a ParseContext,
2689 subs: &'a mut SubstitutionTable,
2690 input: IndexStr<'b>,
2691 ) -> Result<(SourceName, IndexStr<'b>)> {
2692 try_begin_parse!("SourceName", ctx, input);
2693
2694 let (source_name_len, input) = parse_number(10, false, input)?;
2695 debug_assert!(source_name_len >= 0);
2696 if source_name_len == 0 {
2697 return Err(error::Error::UnexpectedText);
2698 }
2699
2700 let (head, tail) = match input.try_split_at(source_name_len as _) {
2701 Some((head, tail)) => (head, tail),
2702 None => return Err(error::Error::UnexpectedEnd),
2703 };
2704
2705 let (identifier, empty) = Identifier::parse(ctx, subs, head)?;
2706 if !empty.is_empty() {
2707 return Err(error::Error::UnexpectedText);
2708 }
2709
2710 let source_name = SourceName(identifier);
2711 Ok((source_name, tail))
2712 }
2713}
2714
2715impl<'subs> ArgScope<'subs, 'subs> for SourceName {
2716 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
2717 Ok(LeafName::SourceName(self))
2718 }
2719
2720 fn get_template_arg(
2721 &'subs self,
2722 _: usize,
2723 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
2724 Err(error::Error::BadTemplateArgReference)
2725 }
2726
2727 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
2728 Err(error::Error::BadFunctionArgReference)
2729 }
2730}
2731
2732impl SourceName {
2733 #[inline]
2734 fn starts_with(byte: u8) -> bool {
2735 byte == b'0' || (b'0' <= byte && byte <= b'9')
2736 }
2737}
2738
2739impl<'subs, W> Demangle<'subs, W> for SourceName
2740where
2741 W: 'subs + DemangleWrite,
2742{
2743 #[inline]
2744 fn demangle<'prev, 'ctx>(
2745 &'subs self,
2746 ctx: &'ctx mut DemangleContext<'subs, W>,
2747 scope: Option<ArgScopeStack<'prev, 'subs>>,
2748 ) -> fmt::Result {
2749 let ctx = try_begin_demangle!(self, ctx, scope);
2750
2751 self.0.demangle(ctx, scope)
2752 }
2753}
2754
2755#[derive(Clone, Debug, Default, PartialEq, Eq)]
2766pub struct AbiTags(Vec<AbiTag>);
2767
2768impl Parse for AbiTags {
2769 fn parse<'a, 'b>(
2770 ctx: &'a ParseContext,
2771 subs: &'a mut SubstitutionTable,
2772 input: IndexStr<'b>,
2773 ) -> Result<(AbiTags, IndexStr<'b>)> {
2774 try_begin_parse!("AbiTags", ctx, input);
2775
2776 let (tags, tail) = zero_or_more::<AbiTag>(ctx, subs, input)?;
2777 Ok((AbiTags(tags), tail))
2778 }
2779}
2780
2781impl<'subs, W> Demangle<'subs, W> for AbiTags
2782where
2783 W: 'subs + DemangleWrite,
2784{
2785 fn demangle<'prev, 'ctx>(
2786 &'subs self,
2787 ctx: &'ctx mut DemangleContext<'subs, W>,
2788 scope: Option<ArgScopeStack<'prev, 'subs>>,
2789 ) -> fmt::Result {
2790 let ctx = try_begin_demangle!(self, ctx, scope);
2791
2792 for tag in &self.0 {
2793 tag.demangle(ctx, scope)?;
2794 }
2795 Ok(())
2796 }
2797}
2798
2799#[derive(Clone, Debug, PartialEq, Eq)]
2805pub struct AbiTag(SourceName);
2806
2807impl Parse for AbiTag {
2808 fn parse<'a, 'b>(
2809 ctx: &'a ParseContext,
2810 subs: &'a mut SubstitutionTable,
2811 input: IndexStr<'b>,
2812 ) -> Result<(AbiTag, IndexStr<'b>)> {
2813 try_begin_parse!("AbiTag", ctx, input);
2814
2815 let tail = consume(b"B", input)?;
2816 let (source_name, tail) = SourceName::parse(ctx, subs, tail)?;
2817 Ok((AbiTag(source_name), tail))
2818 }
2819}
2820
2821impl<'subs, W> Demangle<'subs, W> for AbiTag
2822where
2823 W: 'subs + DemangleWrite,
2824{
2825 fn demangle<'prev, 'ctx>(
2826 &'subs self,
2827 ctx: &'ctx mut DemangleContext<'subs, W>,
2828 scope: Option<ArgScopeStack<'prev, 'subs>>,
2829 ) -> fmt::Result {
2830 let ctx = try_begin_demangle!(self, ctx, scope);
2831
2832 write!(ctx, "[abi:")?;
2833 self.0.demangle(ctx, scope)?;
2834 write!(ctx, "]")
2835 }
2836}
2837
2838#[derive(Clone, Debug, PartialEq, Eq)]
2851pub struct Identifier {
2852 start: usize,
2853 end: usize,
2854}
2855
2856impl Parse for Identifier {
2857 fn parse<'a, 'b>(
2858 ctx: &'a ParseContext,
2859 _subs: &'a mut SubstitutionTable,
2860 input: IndexStr<'b>,
2861 ) -> Result<(Identifier, IndexStr<'b>)> {
2862 try_begin_parse!("Identifier", ctx, input);
2863
2864 if input.is_empty() {
2865 return Err(error::Error::UnexpectedEnd);
2866 }
2867
2868 let end = input
2869 .as_ref()
2870 .iter()
2871 .map(|&c| c as char)
2872 .take_while(|&c| c == '$' || c == '_' || c == '.' || c.is_digit(36))
2873 .count();
2874
2875 if end == 0 {
2876 return Err(error::Error::UnexpectedText);
2877 }
2878
2879 let tail = input.range_from(end..);
2880
2881 let identifier = Identifier {
2882 start: input.index(),
2883 end: tail.index(),
2884 };
2885
2886 Ok((identifier, tail))
2887 }
2888}
2889
2890impl<'subs, W> Demangle<'subs, W> for Identifier
2891where
2892 W: 'subs + DemangleWrite,
2893{
2894 #[inline]
2895 fn demangle<'prev, 'ctx>(
2896 &'subs self,
2897 ctx: &'ctx mut DemangleContext<'subs, W>,
2898 scope: Option<ArgScopeStack<'prev, 'subs>>,
2899 ) -> fmt::Result {
2900 let ctx = try_begin_demangle!(self, ctx, scope);
2901
2902 let ident = &ctx.input[self.start..self.end];
2903
2904 let anon_namespace_prefix = b"_GLOBAL_";
2906 if ident.starts_with(anon_namespace_prefix)
2907 && ident.len() >= anon_namespace_prefix.len() + 2
2908 {
2909 let first = ident[anon_namespace_prefix.len()];
2910 let second = ident[anon_namespace_prefix.len() + 1];
2911
2912 match (first, second) {
2913 (b'.', b'N') | (b'_', b'N') | (b'$', b'N') => {
2914 write!(ctx, "(anonymous namespace)")?;
2915 return Ok(());
2916 }
2917 _ => {
2918 }
2920 }
2921 }
2922
2923 let source_name = String::from_utf8_lossy(ident);
2924 ctx.set_source_name(self.start, self.end);
2925 write!(ctx, "{}", source_name)?;
2926 Ok(())
2927 }
2928}
2929
2930#[derive(Clone, Debug, PartialEq, Eq)]
2936pub struct CloneTypeIdentifier {
2937 start: usize,
2938 end: usize,
2939}
2940
2941impl Parse for CloneTypeIdentifier {
2942 fn parse<'a, 'b>(
2943 ctx: &'a ParseContext,
2944 _subs: &'a mut SubstitutionTable,
2945 input: IndexStr<'b>,
2946 ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
2947 try_begin_parse!("CloneTypeIdentifier", ctx, input);
2948
2949 if input.is_empty() {
2950 return Err(error::Error::UnexpectedEnd);
2951 }
2952
2953 let end = input
2954 .as_ref()
2955 .iter()
2956 .map(|&c| c as char)
2957 .take_while(|&c| c == '$' || c == '_' || c.is_digit(36))
2958 .count();
2959
2960 if end == 0 {
2961 return Err(error::Error::UnexpectedText);
2962 }
2963
2964 let tail = input.range_from(end..);
2965
2966 let identifier = CloneTypeIdentifier {
2967 start: input.index(),
2968 end: tail.index(),
2969 };
2970
2971 Ok((identifier, tail))
2972 }
2973}
2974
2975impl<'subs, W> Demangle<'subs, W> for CloneTypeIdentifier
2976where
2977 W: 'subs + DemangleWrite,
2978{
2979 #[inline]
2980 fn demangle<'prev, 'ctx>(
2981 &'subs self,
2982 ctx: &'ctx mut DemangleContext<'subs, W>,
2983 scope: Option<ArgScopeStack<'prev, 'subs>>,
2984 ) -> fmt::Result {
2985 let ctx = try_begin_demangle!(self, ctx, scope);
2986
2987 let ident = &ctx.input[self.start..self.end];
2988
2989 let source_name = String::from_utf8_lossy(ident);
2990 ctx.set_source_name(self.start, self.end);
2991 write!(ctx, " .{}", source_name)?;
2992 Ok(())
2993 }
2994}
2995
2996type Number = isize;
3002
3003impl Parse for Number {
3004 fn parse<'a, 'b>(
3005 ctx: &'a ParseContext,
3006 _subs: &'a mut SubstitutionTable,
3007 input: IndexStr<'b>,
3008 ) -> Result<(isize, IndexStr<'b>)> {
3009 try_begin_parse!("Number", ctx, input);
3010 parse_number(10, true, input)
3011 }
3012}
3013
3014#[derive(Clone, Debug, PartialEq, Eq)]
3020pub struct SeqId(usize);
3021
3022impl Parse for SeqId {
3023 fn parse<'a, 'b>(
3024 ctx: &'a ParseContext,
3025 _subs: &'a mut SubstitutionTable,
3026 input: IndexStr<'b>,
3027 ) -> Result<(SeqId, IndexStr<'b>)> {
3028 try_begin_parse!("SeqId", ctx, input);
3029
3030 parse_number(36, false, input).map(|(num, tail)| (SeqId(num as _), tail))
3031 }
3032}
3033
3034#[derive(Clone, Debug, PartialEq, Eq)]
3043pub enum OperatorName {
3044 Simple(SimpleOperatorName),
3046
3047 Cast(TypeHandle),
3049
3050 Conversion(TypeHandle),
3052
3053 Literal(SourceName),
3055
3056 VendorExtension(u8, SourceName),
3058}
3059
3060impl OperatorName {
3061 fn starts_with(byte: u8) -> bool {
3062 byte == b'c' || byte == b'l' || byte == b'v' || SimpleOperatorName::starts_with(byte)
3063 }
3064
3065 fn arity(&self) -> u8 {
3066 match self {
3067 &OperatorName::Cast(_) | &OperatorName::Conversion(_) | &OperatorName::Literal(_) => 1,
3068 &OperatorName::Simple(ref s) => s.arity(),
3069 &OperatorName::VendorExtension(arity, _) => arity,
3070 }
3071 }
3072
3073 fn parse_from_expr<'a, 'b>(
3074 ctx: &'a ParseContext,
3075 subs: &'a mut SubstitutionTable,
3076 input: IndexStr<'b>,
3077 ) -> Result<(Expression, IndexStr<'b>)> {
3078 let (operator, tail) = OperatorName::parse_internal(ctx, subs, input, true)?;
3079
3080 let arity = operator.arity();
3081 if arity == 1 {
3082 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3083 let expr = Expression::Unary(operator, Box::new(first));
3084 Ok((expr, tail))
3085 } else if arity == 2 {
3086 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3087 let (second, tail) = Expression::parse(ctx, subs, tail)?;
3088 let expr = Expression::Binary(operator, Box::new(first), Box::new(second));
3089 Ok((expr, tail))
3090 } else if arity == 3 {
3091 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3092 let (second, tail) = Expression::parse(ctx, subs, tail)?;
3093 let (third, tail) = Expression::parse(ctx, subs, tail)?;
3094 let expr =
3095 Expression::Ternary(operator, Box::new(first), Box::new(second), Box::new(third));
3096 Ok((expr, tail))
3097 } else {
3098 Err(error::Error::UnexpectedText)
3099 }
3100 }
3101
3102 fn parse_internal<'a, 'b>(
3103 ctx: &'a ParseContext,
3104 subs: &'a mut SubstitutionTable,
3105 input: IndexStr<'b>,
3106 from_expr: bool,
3107 ) -> Result<(OperatorName, IndexStr<'b>)> {
3108 try_begin_parse!("OperatorName", ctx, input);
3109
3110 if let Ok((simple, tail)) = try_recurse!(SimpleOperatorName::parse(ctx, subs, input)) {
3111 return Ok((OperatorName::Simple(simple), tail));
3112 }
3113
3114 if let Ok(tail) = consume(b"cv", input) {
3115 let previously_in_conversion = ctx.set_in_conversion(!from_expr);
3118 let parse_result = TypeHandle::parse(ctx, subs, tail);
3119 ctx.set_in_conversion(previously_in_conversion);
3120 let (ty, tail) = parse_result?;
3121 if from_expr {
3122 return Ok((OperatorName::Cast(ty), tail));
3123 } else {
3124 return Ok((OperatorName::Conversion(ty), tail));
3125 }
3126 }
3127
3128 if let Ok(tail) = consume(b"li", input) {
3129 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3130 return Ok((OperatorName::Literal(name), tail));
3131 }
3132
3133 let tail = consume(b"v", input)?;
3134 let (arity, tail) = match tail.peek() {
3135 Some(c) if b'0' <= c && c <= b'9' => (c - b'0', tail.range_from(1..)),
3136 None => return Err(error::Error::UnexpectedEnd),
3137 _ => return Err(error::Error::UnexpectedText),
3138 };
3139 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3140 Ok((OperatorName::VendorExtension(arity, name), tail))
3141 }
3142}
3143
3144impl Parse for OperatorName {
3145 fn parse<'a, 'b>(
3146 ctx: &'a ParseContext,
3147 subs: &'a mut SubstitutionTable,
3148 input: IndexStr<'b>,
3149 ) -> Result<(OperatorName, IndexStr<'b>)> {
3150 OperatorName::parse_internal(ctx, subs, input, false)
3151 }
3152}
3153
3154impl<'subs, W> Demangle<'subs, W> for OperatorName
3155where
3156 W: 'subs + DemangleWrite,
3157{
3158 fn demangle<'prev, 'ctx>(
3159 &'subs self,
3160 ctx: &'ctx mut DemangleContext<'subs, W>,
3161 scope: Option<ArgScopeStack<'prev, 'subs>>,
3162 ) -> fmt::Result {
3163 let ctx = try_begin_demangle!(self, ctx, scope);
3164
3165 match *self {
3166 OperatorName::Simple(ref simple) => {
3167 match *simple {
3168 SimpleOperatorName::New
3169 | SimpleOperatorName::NewArray
3170 | SimpleOperatorName::Delete
3171 | SimpleOperatorName::DeleteArray => {
3172 ctx.ensure_space()?;
3173 }
3174 _ => {}
3175 }
3176 simple.demangle(ctx, scope)
3177 }
3178 OperatorName::Cast(ref ty) | OperatorName::Conversion(ref ty) => {
3179 ctx.ensure_space()?;
3180
3181 let scope = ty
3185 .get_template_args(ctx.subs)
3186 .map_or(scope, |args| scope.push(args));
3187
3188 ty.demangle(ctx, scope)?;
3189 Ok(())
3190 }
3191 OperatorName::Literal(ref name) => {
3192 name.demangle(ctx, scope)?;
3193 write!(ctx, "::operator \"\"")?;
3194 Ok(())
3195 }
3196 OperatorName::VendorExtension(arity, ref name) => {
3197 name.demangle(ctx, scope)?;
3199 write!(ctx, "::operator {}", arity)?;
3200 Ok(())
3201 }
3202 }
3203 }
3204}
3205
3206define_vocabulary! {
3207 #[derive(Clone, Debug, PartialEq, Eq)]
3209 pub enum SimpleOperatorName {
3210 New (b"nw", "new", 3),
3211 NewArray (b"na", "new[]", 3),
3212 Delete (b"dl", "delete", 1),
3213 DeleteArray (b"da", "delete[]", 1),
3214 UnaryPlus (b"ps", "+", 1),
3215 Neg (b"ng", "-", 1),
3216 AddressOf (b"ad", "&", 1),
3217 Deref (b"de", "*", 1),
3218 BitNot (b"co", "~", 1),
3219 Add (b"pl", "+", 2),
3220 Sub (b"mi", "-", 2),
3221 Mul (b"ml", "*", 2),
3222 Div (b"dv", "/", 2),
3223 Rem (b"rm", "%", 2),
3224 BitAnd (b"an", "&", 2),
3225 BitOr (b"or", "|", 2),
3226 BitXor (b"eo", "^", 2),
3227 Assign (b"aS", "=", 2),
3228 AddAssign (b"pL", "+=", 2),
3229 SubAssign (b"mI", "-=", 2),
3230 MulAssign (b"mL", "*=", 2),
3231 DivAssign (b"dV", "/=", 2),
3232 RemAssign (b"rM", "%=", 2),
3233 BitAndAssign (b"aN", "&=", 2),
3234 BitOrAssign (b"oR", "|=", 2),
3235 BitXorAssign (b"eO", "^=", 2),
3236 Shl (b"ls", "<<", 2),
3237 Shr (b"rs", ">>", 2),
3238 ShlAssign (b"lS", "<<=", 2),
3239 ShrAssign (b"rS", ">>=", 2),
3240 Eq (b"eq", "==", 2),
3241 Ne (b"ne", "!=", 2),
3242 Less (b"lt", "<", 2),
3243 Greater (b"gt", ">", 2),
3244 LessEq (b"le", "<=", 2),
3245 GreaterEq (b"ge", ">=", 2),
3246 Not (b"nt", "!", 1),
3247 LogicalAnd (b"aa", "&&", 2),
3248 LogicalOr (b"oo", "||", 2),
3249 PostInc (b"pp", "++", 1), PostDec (b"mm", "--", 1), Comma (b"cm", ",", 2),
3252 DerefMemberPtr (b"pm", "->*", 2),
3253 DerefMember (b"pt", "->", 2),
3254 Call (b"cl", "()", 2),
3255 Index (b"ix", "[]", 2),
3256 Question (b"qu", "?:", 3),
3257 Spaceship (b"ss", "<=>", 2)
3258 }
3259
3260 impl SimpleOperatorName {
3261 fn arity(&self) -> u8;
3263 }
3264}
3265
3266#[derive(Clone, Debug, PartialEq, Eq)]
3273pub enum CallOffset {
3274 NonVirtual(NvOffset),
3276 Virtual(VOffset),
3278}
3279
3280impl Parse for CallOffset {
3281 fn parse<'a, 'b>(
3282 ctx: &'a ParseContext,
3283 subs: &'a mut SubstitutionTable,
3284 input: IndexStr<'b>,
3285 ) -> Result<(CallOffset, IndexStr<'b>)> {
3286 try_begin_parse!("CallOffset", ctx, input);
3287
3288 if input.is_empty() {
3289 return Err(error::Error::UnexpectedEnd);
3290 }
3291
3292 if let Ok(tail) = consume(b"h", input) {
3293 let (offset, tail) = NvOffset::parse(ctx, subs, tail)?;
3294 let tail = consume(b"_", tail)?;
3295 return Ok((CallOffset::NonVirtual(offset), tail));
3296 }
3297
3298 if let Ok(tail) = consume(b"v", input) {
3299 let (offset, tail) = VOffset::parse(ctx, subs, tail)?;
3300 let tail = consume(b"_", tail)?;
3301 return Ok((CallOffset::Virtual(offset), tail));
3302 }
3303
3304 Err(error::Error::UnexpectedText)
3305 }
3306}
3307
3308impl<'subs, W> Demangle<'subs, W> for CallOffset
3309where
3310 W: 'subs + DemangleWrite,
3311{
3312 fn demangle<'prev, 'ctx>(
3313 &'subs self,
3314 ctx: &'ctx mut DemangleContext<'subs, W>,
3315 scope: Option<ArgScopeStack<'prev, 'subs>>,
3316 ) -> fmt::Result {
3317 let ctx = try_begin_demangle!(self, ctx, scope);
3318
3319 match *self {
3320 CallOffset::NonVirtual(NvOffset(offset)) => {
3321 write!(ctx, "{{offset({})}}", offset)?;
3322 }
3323 CallOffset::Virtual(VOffset(vbase, vcall)) => {
3324 write!(ctx, "{{virtual offset({}, {})}}", vbase, vcall)?;
3325 }
3326 }
3327 Ok(())
3328 }
3329}
3330
3331#[derive(Clone, Debug, PartialEq, Eq)]
3337pub struct NvOffset(isize);
3338
3339impl Parse for NvOffset {
3340 fn parse<'a, 'b>(
3341 ctx: &'a ParseContext,
3342 subs: &'a mut SubstitutionTable,
3343 input: IndexStr<'b>,
3344 ) -> Result<(NvOffset, IndexStr<'b>)> {
3345 try_begin_parse!("NvOffset", ctx, input);
3346
3347 Number::parse(ctx, subs, input).map(|(num, tail)| (NvOffset(num), tail))
3348 }
3349}
3350
3351#[derive(Clone, Debug, PartialEq, Eq)]
3357pub struct VOffset(isize, isize);
3358
3359impl Parse for VOffset {
3360 fn parse<'a, 'b>(
3361 ctx: &'a ParseContext,
3362 subs: &'a mut SubstitutionTable,
3363 input: IndexStr<'b>,
3364 ) -> Result<(VOffset, IndexStr<'b>)> {
3365 try_begin_parse!("VOffset", ctx, input);
3366
3367 let (offset, tail) = Number::parse(ctx, subs, input)?;
3368 let tail = consume(b"_", tail)?;
3369 let (virtual_offset, tail) = Number::parse(ctx, subs, tail)?;
3370 Ok((VOffset(offset, virtual_offset), tail))
3371 }
3372}
3373
3374#[derive(Clone, Debug, PartialEq, Eq)]
3397pub enum CtorDtorName {
3398 CompleteConstructor(Option<TypeHandle>),
3400 BaseConstructor(Option<TypeHandle>),
3402 CompleteAllocatingConstructor(Option<TypeHandle>),
3404 MaybeInChargeConstructor(Option<TypeHandle>),
3406 DeletingDestructor,
3408 CompleteDestructor,
3410 BaseDestructor,
3412 MaybeInChargeDestructor,
3414}
3415
3416impl CtorDtorName {
3417 fn inheriting_mut(&mut self) -> &mut Option<TypeHandle> {
3418 match self {
3419 CtorDtorName::CompleteConstructor(ref mut inheriting)
3420 | CtorDtorName::BaseConstructor(ref mut inheriting)
3421 | CtorDtorName::CompleteAllocatingConstructor(ref mut inheriting)
3422 | CtorDtorName::MaybeInChargeConstructor(ref mut inheriting) => inheriting,
3423 CtorDtorName::DeletingDestructor
3424 | CtorDtorName::CompleteDestructor
3425 | CtorDtorName::BaseDestructor
3426 | CtorDtorName::MaybeInChargeDestructor => unreachable!(),
3427 }
3428 }
3429}
3430
3431impl Parse for CtorDtorName {
3432 fn parse<'a, 'b>(
3433 ctx: &'a ParseContext,
3434 subs: &'a mut SubstitutionTable,
3435 input: IndexStr<'b>,
3436 ) -> Result<(CtorDtorName, IndexStr<'b>)> {
3437 try_begin_parse!(stringify!(CtorDtorName), ctx, input);
3438
3439 match input.peek() {
3440 Some(b'C') => {
3441 let mut tail = consume(b"C", input)?;
3442 let inheriting = match tail.peek() {
3443 Some(b'I') => {
3444 tail = consume(b"I", tail)?;
3445 true
3446 }
3447 _ => false,
3448 };
3449
3450 let mut ctor_type: CtorDtorName = match tail
3451 .try_split_at(1)
3452 .as_ref()
3453 .map(|&(ref h, t)| (h.as_ref(), t))
3454 {
3455 None => Err(error::Error::UnexpectedEnd),
3456 Some((b"1", t)) => {
3457 tail = t;
3458 Ok(CtorDtorName::CompleteConstructor(None))
3459 }
3460 Some((b"2", t)) => {
3461 tail = t;
3462 Ok(CtorDtorName::BaseConstructor(None))
3463 }
3464 Some((b"3", t)) => {
3465 tail = t;
3466 Ok(CtorDtorName::CompleteAllocatingConstructor(None))
3467 }
3468 Some((b"4", t)) => {
3469 tail = t;
3470 Ok(CtorDtorName::MaybeInChargeConstructor(None))
3471 }
3472 _ => Err(error::Error::UnexpectedText),
3473 }?;
3474
3475 if inheriting {
3476 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3477 *ctor_type.inheriting_mut() = Some(ty);
3478 Ok((ctor_type, tail))
3479 } else {
3480 Ok((ctor_type, tail))
3481 }
3482 }
3483 Some(b'D') => {
3484 match input
3485 .try_split_at(2)
3486 .as_ref()
3487 .map(|&(ref h, t)| (h.as_ref(), t))
3488 {
3489 Some((b"D0", tail)) => Ok((CtorDtorName::DeletingDestructor, tail)),
3490 Some((b"D1", tail)) => Ok((CtorDtorName::CompleteDestructor, tail)),
3491 Some((b"D2", tail)) => Ok((CtorDtorName::BaseDestructor, tail)),
3492 Some((b"D4", tail)) => Ok((CtorDtorName::MaybeInChargeDestructor, tail)),
3493 _ => Err(error::Error::UnexpectedText),
3494 }
3495 }
3496 None => Err(error::Error::UnexpectedEnd),
3497 _ => Err(error::Error::UnexpectedText),
3498 }
3499 }
3500}
3501
3502impl<'subs, W> Demangle<'subs, W> for CtorDtorName
3503where
3504 W: 'subs + DemangleWrite,
3505{
3506 fn demangle<'prev, 'ctx>(
3507 &'subs self,
3508 ctx: &'ctx mut DemangleContext<'subs, W>,
3509 scope: Option<ArgScopeStack<'prev, 'subs>>,
3510 ) -> fmt::Result {
3511 let ctx = try_begin_demangle!(self, ctx, scope);
3512
3513 let leaf = scope.leaf_name().map_err(|e| {
3514 log!("Error getting leaf name: {}", e);
3515 fmt::Error
3516 })?;
3517
3518 match *self {
3519 CtorDtorName::CompleteConstructor(ref inheriting)
3520 | CtorDtorName::BaseConstructor(ref inheriting)
3521 | CtorDtorName::CompleteAllocatingConstructor(ref inheriting)
3522 | CtorDtorName::MaybeInChargeConstructor(ref inheriting) => match inheriting {
3523 Some(ty) => ty
3524 .get_leaf_name(ctx.subs)
3525 .ok_or_else(|| {
3526 log!("Error getting leaf name: {:?}", ty);
3527 fmt::Error
3528 })?
3529 .demangle_as_leaf(ctx),
3530 None => leaf.demangle_as_leaf(ctx),
3531 },
3532 CtorDtorName::DeletingDestructor
3533 | CtorDtorName::CompleteDestructor
3534 | CtorDtorName::BaseDestructor
3535 | CtorDtorName::MaybeInChargeDestructor => {
3536 write!(ctx, "~")?;
3537 leaf.demangle_as_leaf(ctx)
3538 }
3539 }
3540 }
3541}
3542
3543impl CtorDtorName {
3544 #[inline]
3545 fn starts_with(byte: u8) -> bool {
3546 byte == b'C' || byte == b'D'
3547 }
3548}
3549
3550#[derive(Clone, Debug, PartialEq, Eq)]
3573#[allow(clippy::large_enum_variant)]
3574pub enum Type {
3575 Function(FunctionType),
3577
3578 ClassEnum(ClassEnumType),
3580
3581 Array(ArrayType),
3583
3584 Vector(VectorType),
3586
3587 PointerToMember(PointerToMemberType),
3589
3590 TemplateParam(TemplateParam),
3592
3593 TemplateTemplate(TemplateTemplateParamHandle, TemplateArgs),
3595
3596 Decltype(Decltype),
3598
3599 Qualified(CvQualifiers, TypeHandle),
3601
3602 PointerTo(TypeHandle),
3604
3605 LvalueRef(TypeHandle),
3607
3608 RvalueRef(TypeHandle),
3610
3611 Complex(TypeHandle),
3613
3614 Imaginary(TypeHandle),
3616
3617 VendorExtension(SourceName, Option<TemplateArgs>, TypeHandle),
3619
3620 PackExpansion(TypeHandle),
3622}
3623
3624define_handle! {
3625 pub enum TypeHandle {
3627 extra Builtin(BuiltinType),
3629
3630 extra QualifiedBuiltin(QualifiedBuiltin),
3632 }
3633}
3634
3635impl TypeHandle {
3636 fn is_void(&self) -> bool {
3637 match *self {
3638 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Void)) => true,
3639 _ => false,
3640 }
3641 }
3642}
3643
3644impl Parse for TypeHandle {
3645 fn parse<'a, 'b>(
3646 ctx: &'a ParseContext,
3647 subs: &'a mut SubstitutionTable,
3648 input: IndexStr<'b>,
3649 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3650 try_begin_parse!("TypeHandle", ctx, input);
3651
3652 fn insert_and_return_handle<'a, 'b>(
3655 ty: Type,
3656 subs: &'a mut SubstitutionTable,
3657 tail: IndexStr<'b>,
3658 ) -> Result<(TypeHandle, IndexStr<'b>)> {
3659 let ty = Substitutable::Type(ty);
3660 let idx = subs.insert(ty);
3661 let handle = TypeHandle::BackReference(idx);
3662 Ok((handle, tail))
3663 }
3664
3665 if let Ok((builtin, tail)) = try_recurse!(BuiltinType::parse(ctx, subs, input)) {
3666 let handle = TypeHandle::Builtin(builtin);
3669 return Ok((handle, tail));
3670 }
3671
3672 if let Ok(tail) = consume(b"U", input) {
3679 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3680 let (args, tail) =
3681 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
3682 (Some(args), tail)
3683 } else {
3684 (None, tail)
3685 };
3686 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3687 let ty = Type::VendorExtension(name, args, ty);
3688 return insert_and_return_handle(ty, subs, tail);
3689 }
3690
3691 if let Ok((qualifiers, tail)) = try_recurse!(CvQualifiers::parse(ctx, subs, input)) {
3693 if tail.len() < input.len() {
3697 if !FunctionType::starts_with(&tail) {
3700 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3701 let ty = Type::Qualified(qualifiers, ty);
3702 return insert_and_return_handle(ty, subs, tail);
3703 }
3704 }
3705 }
3706
3707 if let Ok((ty, tail)) = try_recurse!(ClassEnumType::parse(ctx, subs, input)) {
3708 let ty = Type::ClassEnum(ty);
3709 return insert_and_return_handle(ty, subs, tail);
3710 }
3711
3712 if let Ok((sub, tail)) = try_recurse!(Substitution::parse(ctx, subs, input)) {
3713 if tail.peek() != Some(b'I') {
3719 match sub {
3720 Substitution::WellKnown(component) => {
3721 return Ok((TypeHandle::WellKnown(component), tail));
3722 }
3723 Substitution::BackReference(idx) => {
3724 return Ok((TypeHandle::BackReference(idx), tail));
3727 }
3728 }
3729 }
3730 }
3731
3732 if let Ok((funty, tail)) = try_recurse!(FunctionType::parse(ctx, subs, input)) {
3733 let ty = Type::Function(funty);
3734 return insert_and_return_handle(ty, subs, tail);
3735 }
3736
3737 if let Ok((ty, tail)) = try_recurse!(ArrayType::parse(ctx, subs, input)) {
3738 let ty = Type::Array(ty);
3739 return insert_and_return_handle(ty, subs, tail);
3740 }
3741
3742 if let Ok((ty, tail)) = try_recurse!(VectorType::parse(ctx, subs, input)) {
3743 let ty = Type::Vector(ty);
3744 return insert_and_return_handle(ty, subs, tail);
3745 }
3746
3747 if let Ok((ty, tail)) = try_recurse!(PointerToMemberType::parse(ctx, subs, input)) {
3748 let ty = Type::PointerToMember(ty);
3749 return insert_and_return_handle(ty, subs, tail);
3750 }
3751
3752 if let Ok((param, tail)) = try_recurse!(TemplateParam::parse(ctx, subs, input)) {
3753 if tail.peek() != Some(b'I') {
3757 let ty = Type::TemplateParam(param);
3758 return insert_and_return_handle(ty, subs, tail);
3759 } else if ctx.in_conversion() {
3760 let mut tmp_subs = subs.clone();
3773 if let Ok((_, new_tail)) =
3774 try_recurse!(TemplateArgs::parse(ctx, &mut tmp_subs, tail))
3775 {
3776 if new_tail.peek() != Some(b'I') {
3777 let ty = Type::TemplateParam(param);
3779 return insert_and_return_handle(ty, subs, tail);
3780 }
3781 }
3787 }
3788 }
3789
3790 if let Ok((ttp, tail)) = try_recurse!(TemplateTemplateParamHandle::parse(ctx, subs, input))
3791 {
3792 let (args, tail) = TemplateArgs::parse(ctx, subs, tail)?;
3793 let ty = Type::TemplateTemplate(ttp, args);
3794 return insert_and_return_handle(ty, subs, tail);
3795 }
3796
3797 if let Ok((param, tail)) = try_recurse!(Decltype::parse(ctx, subs, input)) {
3798 let ty = Type::Decltype(param);
3799 return insert_and_return_handle(ty, subs, tail);
3800 }
3801
3802 if let Ok(tail) = consume(b"P", input) {
3803 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3804 let ty = Type::PointerTo(ty);
3805 return insert_and_return_handle(ty, subs, tail);
3806 }
3807
3808 if let Ok(tail) = consume(b"R", input) {
3809 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3810 let ty = Type::LvalueRef(ty);
3811 return insert_and_return_handle(ty, subs, tail);
3812 }
3813
3814 if let Ok(tail) = consume(b"O", input) {
3815 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3816 let ty = Type::RvalueRef(ty);
3817 return insert_and_return_handle(ty, subs, tail);
3818 }
3819
3820 if let Ok(tail) = consume(b"C", input) {
3821 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3822 let ty = Type::Complex(ty);
3823 return insert_and_return_handle(ty, subs, tail);
3824 }
3825
3826 if let Ok(tail) = consume(b"G", input) {
3827 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3828 let ty = Type::Imaginary(ty);
3829 return insert_and_return_handle(ty, subs, tail);
3830 }
3831
3832 let tail = consume(b"Dp", input)?;
3833 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
3834 let ty = Type::PackExpansion(ty);
3835 insert_and_return_handle(ty, subs, tail)
3836 }
3837}
3838
3839impl GetTemplateArgs for TypeHandle {
3840 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
3841 subs.get_type(self)
3842 .and_then(|ty| ty.get_template_args(subs))
3843 }
3844}
3845
3846impl<'subs, W> Demangle<'subs, W> for Type
3847where
3848 W: 'subs + DemangleWrite,
3849{
3850 fn demangle<'prev, 'ctx>(
3851 &'subs self,
3852 ctx: &'ctx mut DemangleContext<'subs, W>,
3853 scope: Option<ArgScopeStack<'prev, 'subs>>,
3854 ) -> fmt::Result {
3855 let ctx = try_begin_demangle!(self, ctx, scope);
3856
3857 match *self {
3858 Type::Function(ref func_ty) => func_ty.demangle(ctx, scope),
3859 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.demangle(ctx, scope),
3860 Type::Array(ref array_ty) => array_ty.demangle(ctx, scope),
3861 Type::Vector(ref vector_ty) => vector_ty.demangle(ctx, scope),
3862 Type::PointerToMember(ref ptm) => ptm.demangle(ctx, scope),
3863 Type::TemplateParam(ref param) => param.demangle(ctx, scope),
3864 Type::TemplateTemplate(ref tt_param, ref args) => {
3865 tt_param.demangle(ctx, scope)?;
3866 args.demangle(ctx, scope)
3867 }
3868 Type::Decltype(ref dt) => dt.demangle(ctx, scope),
3869 Type::Qualified(_, ref ty) => {
3870 ctx.push_inner(self);
3871 ty.demangle(ctx, scope)?;
3872 if ctx.pop_inner_if(self) {
3873 self.demangle_as_inner(ctx, scope)?;
3874 }
3875 Ok(())
3876 }
3877 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
3878 ctx.push_inner(self);
3879 ty.demangle(ctx, scope)?;
3880 if ctx.pop_inner_if(self) {
3881 self.demangle_as_inner(ctx, scope)?;
3882 }
3883 Ok(())
3884 }
3885 Type::Complex(ref ty) => {
3886 ty.demangle(ctx, scope)?;
3887 write!(ctx, " complex")?;
3888 Ok(())
3889 }
3890 Type::Imaginary(ref ty) => {
3891 ty.demangle(ctx, scope)?;
3892 write!(ctx, " imaginary")?;
3893 Ok(())
3894 }
3895 Type::VendorExtension(ref name, ref template_args, ref ty) => {
3896 ty.demangle(ctx, scope)?;
3897 write!(ctx, " ")?;
3898 name.demangle(ctx, scope)?;
3899 if let Some(ref args) = *template_args {
3900 args.demangle(ctx, scope)?;
3901 }
3902 Ok(())
3903 }
3904 Type::PackExpansion(ref ty) => {
3905 ty.demangle(ctx, scope)?;
3906 if !ctx.is_template_argument_pack {
3907 write!(ctx, "...")?;
3908 }
3909 Ok(())
3910 }
3911 }
3912 }
3913}
3914
3915impl<'subs, W> DemangleAsInner<'subs, W> for Type
3916where
3917 W: 'subs + DemangleWrite,
3918{
3919 fn demangle_as_inner<'prev, 'ctx>(
3920 &'subs self,
3921 ctx: &'ctx mut DemangleContext<'subs, W>,
3922 scope: Option<ArgScopeStack<'prev, 'subs>>,
3923 ) -> fmt::Result {
3924 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
3925
3926 match *self {
3927 Type::Qualified(ref quals, _) => quals.demangle_as_inner(ctx, scope),
3928 Type::PointerTo(_) => write!(ctx, "*"),
3929 Type::RvalueRef(_) => {
3930 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3931 match v {
3932 Type::RvalueRef(_) => {
3935 ctx.inner.pop().unwrap();
3936 }
3937 Type::LvalueRef(_) => return Ok(()),
3941 _ => break,
3942 }
3943 }
3944 write!(ctx, "&&")
3945 }
3946 Type::LvalueRef(_) => {
3947 while let Some(v) = ctx.inner.last().and_then(|ty| ty.downcast_to_type()) {
3948 match v {
3949 Type::RvalueRef(_) => {
3953 ctx.inner.pop().unwrap();
3954 }
3955 Type::LvalueRef(_) => return Ok(()),
3959 _ => break,
3960 }
3961 }
3962 write!(ctx, "&")
3963 }
3964 ref otherwise => {
3965 unreachable!(
3966 "We shouldn't ever put any other types on the inner stack: {:?}",
3967 otherwise
3968 );
3969 }
3970 }
3971 }
3972
3973 fn downcast_to_type(&self) -> Option<&Type> {
3974 Some(self)
3975 }
3976
3977 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
3978 if let Type::Function(ref f) = *self {
3979 Some(f)
3980 } else {
3981 None
3982 }
3983 }
3984
3985 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
3986 if let Type::Array(ref arr) = *self {
3987 Some(arr)
3988 } else {
3989 None
3990 }
3991 }
3992
3993 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
3994 if let Type::PointerToMember(ref ptm) = *self {
3995 Some(ptm)
3996 } else {
3997 None
3998 }
3999 }
4000
4001 fn is_qualified(&self) -> bool {
4002 match *self {
4003 Type::Qualified(..) => true,
4004 _ => false,
4005 }
4006 }
4007}
4008
4009impl GetTemplateArgs for Type {
4010 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
4011 match *self {
4015 Type::VendorExtension(_, Some(ref args), _) | Type::TemplateTemplate(_, ref args) => {
4016 Some(args)
4017 }
4018 Type::PointerTo(ref ty) | Type::LvalueRef(ref ty) | Type::RvalueRef(ref ty) => {
4019 ty.get_template_args(subs)
4020 }
4021 _ => None,
4022 }
4023 }
4024}
4025
4026impl<'a> GetLeafName<'a> for Type {
4027 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4028 match *self {
4029 Type::ClassEnum(ref cls_enum_ty) => cls_enum_ty.get_leaf_name(subs),
4030 _ => None,
4031 }
4032 }
4033}
4034
4035#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
4041pub struct CvQualifiers {
4042 pub restrict: bool,
4044 pub volatile: bool,
4046 pub const_: bool,
4048}
4049
4050impl CvQualifiers {
4051 #[inline]
4052 fn is_empty(&self) -> bool {
4053 !self.restrict && !self.volatile && !self.const_
4054 }
4055}
4056
4057impl Parse for CvQualifiers {
4058 fn parse<'a, 'b>(
4059 ctx: &'a ParseContext,
4060 _subs: &'a mut SubstitutionTable,
4061 input: IndexStr<'b>,
4062 ) -> Result<(CvQualifiers, IndexStr<'b>)> {
4063 try_begin_parse!("CvQualifiers", ctx, input);
4064
4065 let (restrict, tail) = if let Ok(tail) = consume(b"r", input) {
4066 (true, tail)
4067 } else {
4068 (false, input)
4069 };
4070
4071 let (volatile, tail) = if let Ok(tail) = consume(b"V", tail) {
4072 (true, tail)
4073 } else {
4074 (false, tail)
4075 };
4076
4077 let (const_, tail) = if let Ok(tail) = consume(b"K", tail) {
4078 (true, tail)
4079 } else {
4080 (false, tail)
4081 };
4082
4083 let qualifiers = CvQualifiers {
4084 restrict: restrict,
4085 volatile: volatile,
4086 const_: const_,
4087 };
4088
4089 Ok((qualifiers, tail))
4090 }
4091}
4092
4093impl<'subs, W> Demangle<'subs, W> for CvQualifiers
4094where
4095 W: 'subs + DemangleWrite,
4096{
4097 fn demangle<'prev, 'ctx>(
4098 &'subs self,
4099 ctx: &'ctx mut DemangleContext<'subs, W>,
4100 scope: Option<ArgScopeStack<'prev, 'subs>>,
4101 ) -> fmt::Result {
4102 let ctx = try_begin_demangle!(self, ctx, scope);
4103
4104 if self.const_ {
4105 ctx.ensure_space()?;
4106 write!(ctx, "const")?;
4107 }
4108
4109 if self.volatile {
4110 ctx.ensure_space()?;
4111 write!(ctx, "volatile")?;
4112 }
4113
4114 if self.restrict {
4115 ctx.ensure_space()?;
4116 write!(ctx, "restrict")?;
4117 }
4118
4119 Ok(())
4120 }
4121}
4122
4123impl<'subs, W> DemangleAsInner<'subs, W> for CvQualifiers where W: 'subs + DemangleWrite {}
4124
4125define_vocabulary! {
4126 #[derive(Clone, Debug, PartialEq, Eq)]
4133 pub enum RefQualifier {
4134 LValueRef(b"R", "&"),
4135 RValueRef(b"O", "&&")
4136 }
4137}
4138
4139define_vocabulary! {
4140 #[derive(Clone, Debug, PartialEq, Eq)]
4142 pub enum ExplicitObjectParameter {
4143 ExplicitObjectParameter(b"H", "this")
4144 }
4145}
4146
4147define_vocabulary! {
4148 #[derive(Clone, Debug, PartialEq, Eq)]
4194 pub enum StandardBuiltinType {
4195 Void (b"v", "void"),
4196 Wchar (b"w", "wchar_t"),
4197 Bool (b"b", "bool"),
4198 Char (b"c", "char"),
4199 SignedChar (b"a", "signed char"),
4200 UnsignedChar (b"h", "unsigned char"),
4201 Short (b"s", "short"),
4202 UnsignedShort (b"t", "unsigned short"),
4203 Int (b"i", "int"),
4204 UnsignedInt (b"j", "unsigned int"),
4205 Long (b"l", "long"),
4206 UnsignedLong (b"m", "unsigned long"),
4207 LongLong (b"x", "long long"),
4208 UnsignedLongLong (b"y", "unsigned long long"),
4209 Int128 (b"n", "__int128"),
4210 Uint128 (b"o", "unsigned __int128"),
4211 Float (b"f", "float"),
4212 Double (b"d", "double"),
4213 LongDouble (b"e", "long double"),
4214 Float128 (b"g", "__float128"),
4215 Ellipsis (b"z", "..."),
4216 DecimalFloat64 (b"Dd", "decimal64"),
4217 DecimalFloat128 (b"De", "decimal128"),
4218 DecimalFloat32 (b"Df", "decimal32"),
4219 DecimalFloat16 (b"Dh", "half"),
4220 BFloat16 (b"DF16b", "std::bfloat16_t"),
4221 Char32 (b"Di", "char32_t"),
4222 Char16 (b"Ds", "char16_t"),
4223 Char8 (b"Du", "char8_t"),
4224 Auto (b"Da", "auto"),
4225 Decltype (b"Dc", "decltype(auto)"),
4226 Nullptr (b"Dn", "std::nullptr_t"),
4227 AccumShort (b"DAs", "short _Accum"),
4228 AccumUShort (b"DAt", "unsigned short _Accum"),
4229 Accum (b"DAi", "_Accum"),
4230 AccumUnsigned (b"DAj", "unsigned _Accum"),
4231 AccumLong (b"DAl", "long _Accum"),
4232 AccumULong (b"DAm", "unsigned long _Accum"),
4233 FractShort (b"DRs", "short _Fract"),
4234 FractUShort (b"DRt", "unsigned short _Fract"),
4235 Fract (b"DRi", "_Fract"),
4236 FractUnsigned (b"DRj", "unsigned _Fract"),
4237 FractLong (b"DRl", "long _Fract"),
4238 FractULong (b"DRm", "unsigned long _Fract"),
4239 SatAccumShort (b"DSDAs", "_Sat short _Accum"),
4240 SatAccumUShort (b"DSDAt", "_Sat unsigned short _Accum"),
4241 SatAccum (b"DSDAi", "_Sat _Accum"),
4242 SatAccumUnsigned (b"DSDAj", "_Sat unsigned _Accum"),
4243 SatAccumLong (b"DSDAl", "_Sat long _Accum"),
4244 SatAccumULong (b"DSDAm", "_Sat unsigned long _Accum"),
4245 SatFractShort (b"DSDRs", "_Sat short _Fract"),
4246 SatFractUShort (b"DSDRt", "_Sat unsigned short _Fract"),
4247 SatFract (b"DSDRi", "_Sat _Fract"),
4248 SatFractUnsigned (b"DSDRj", "_Sat unsigned _Fract"),
4249 SatFractLong (b"DSDRl", "_Sat long _Fract"),
4250 SatFractULong (b"DSDRm", "_Sat unsigned long _Fract")
4251 }
4252}
4253
4254#[derive(Clone, Debug, PartialEq, Eq)]
4261pub enum ParametricBuiltinType {
4262 FloatN(Number),
4264 FloatNx(Number),
4266 SignedBitInt(Number),
4268 UnsignedBitInt(Number),
4270 SignedBitIntExpression(Box<Expression>),
4272 UnsignedBitIntExpression(Box<Expression>),
4274}
4275
4276impl Parse for ParametricBuiltinType {
4277 fn parse<'a, 'b>(
4278 ctx: &'a ParseContext,
4279 subs: &'a mut SubstitutionTable,
4280 input: IndexStr<'b>,
4281 ) -> Result<(ParametricBuiltinType, IndexStr<'b>)> {
4282 try_begin_parse!("ParametricBuiltinType", ctx, input);
4283
4284 let input = consume(b"D", input)?;
4285 let (ch, input) = input.next_or(error::Error::UnexpectedEnd)?;
4286 let allow_expression = match ch {
4287 b'F' => false,
4288 b'B' | b'U' => true,
4289 _ => return Err(error::Error::UnexpectedText),
4290 };
4291 if input
4292 .next_or(error::Error::UnexpectedEnd)?
4293 .0
4294 .is_ascii_digit()
4295 {
4296 let (bit_size, input) = parse_number(10, false, input)?;
4297 if ch == b'F' {
4298 if let Ok(input) = consume(b"x", input) {
4299 return Ok((ParametricBuiltinType::FloatNx(bit_size), input));
4300 }
4301 }
4302 let input = consume(b"_", input)?;
4303 let t = match ch {
4304 b'F' => ParametricBuiltinType::FloatN(bit_size),
4305 b'B' => ParametricBuiltinType::SignedBitInt(bit_size),
4306 b'U' => ParametricBuiltinType::UnsignedBitInt(bit_size),
4307 _ => panic!("oh noes"),
4308 };
4309 Ok((t, input))
4310 } else if allow_expression {
4311 let (expr, input) = Expression::parse(ctx, subs, input)?;
4312 let expr = Box::new(expr);
4313 let t = match ch {
4314 b'B' => ParametricBuiltinType::SignedBitIntExpression(expr),
4315 b'U' => ParametricBuiltinType::UnsignedBitIntExpression(expr),
4316 _ => panic!("oh noes"),
4317 };
4318 Ok((t, input))
4319 } else {
4320 Err(error::Error::UnexpectedText)
4321 }
4322 }
4323}
4324
4325impl<'subs, W> Demangle<'subs, W> for ParametricBuiltinType
4326where
4327 W: 'subs + DemangleWrite,
4328{
4329 fn demangle<'prev, 'ctx>(
4330 &'subs self,
4331 ctx: &'ctx mut DemangleContext<'subs, W>,
4332 scope: Option<ArgScopeStack<'prev, 'subs>>,
4333 ) -> fmt::Result {
4334 let ctx = try_begin_demangle!(self, ctx, scope);
4335
4336 match *self {
4337 Self::FloatN(n) => write!(ctx, "_Float{}", n),
4338 Self::FloatNx(n) => write!(ctx, "_Float{}x", n),
4339 Self::SignedBitInt(n) => write!(ctx, "signed _BitInt({})", n),
4340 Self::UnsignedBitInt(n) => write!(ctx, "unsigned _BitInt({})", n),
4341 Self::SignedBitIntExpression(ref expr) => {
4342 write!(ctx, "signed _BitInt(")?;
4343 expr.demangle(ctx, scope)?;
4344 write!(ctx, ")")
4345 }
4346 Self::UnsignedBitIntExpression(ref expr) => {
4347 write!(ctx, "unsigned _BitInt(")?;
4348 expr.demangle(ctx, scope)?;
4349 write!(ctx, ")")
4350 }
4351 }
4352 }
4353}
4354
4355#[derive(Clone, Debug, PartialEq, Eq)]
4357pub enum BuiltinType {
4358 Standard(StandardBuiltinType),
4360
4361 Parametric(ParametricBuiltinType),
4363
4364 Extension(SourceName),
4370}
4371
4372impl Parse for BuiltinType {
4373 fn parse<'a, 'b>(
4374 ctx: &'a ParseContext,
4375 subs: &'a mut SubstitutionTable,
4376 input: IndexStr<'b>,
4377 ) -> Result<(BuiltinType, IndexStr<'b>)> {
4378 try_begin_parse!("BuiltinType", ctx, input);
4379
4380 if let Ok((ty, tail)) = try_recurse!(StandardBuiltinType::parse(ctx, subs, input)) {
4381 return Ok((BuiltinType::Standard(ty), tail));
4382 }
4383
4384 if let Ok(tail) = consume(b"u", input) {
4385 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
4386 Ok((BuiltinType::Extension(name), tail))
4387 } else {
4388 match try_recurse!(ParametricBuiltinType::parse(ctx, subs, input)) {
4389 Ok((ty, tail)) => Ok((BuiltinType::Parametric(ty), tail)),
4390 Err(e) => Err(e),
4391 }
4392 }
4393 }
4394}
4395
4396impl<'subs, W> Demangle<'subs, W> for BuiltinType
4397where
4398 W: 'subs + DemangleWrite,
4399{
4400 fn demangle<'prev, 'ctx>(
4401 &'subs self,
4402 ctx: &'ctx mut DemangleContext<'subs, W>,
4403 scope: Option<ArgScopeStack<'prev, 'subs>>,
4404 ) -> fmt::Result {
4405 let ctx = try_begin_demangle!(self, ctx, scope);
4406
4407 match *self {
4408 BuiltinType::Standard(ref ty) => ty.demangle(ctx, scope),
4409 BuiltinType::Parametric(ref ty) => ty.demangle(ctx, scope),
4410 BuiltinType::Extension(ref name) => name.demangle(ctx, scope),
4411 }
4412 }
4413}
4414
4415impl<'a> GetLeafName<'a> for BuiltinType {
4416 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4417 None
4418 }
4419}
4420
4421#[derive(Clone, Debug, PartialEq, Eq)]
4426pub struct QualifiedBuiltin(CvQualifiers, BuiltinType);
4427
4428impl<'subs, W> Demangle<'subs, W> for QualifiedBuiltin
4429where
4430 W: 'subs + DemangleWrite,
4431{
4432 fn demangle<'prev, 'ctx>(
4433 &'subs self,
4434 ctx: &'ctx mut DemangleContext<'subs, W>,
4435 scope: Option<ArgScopeStack<'prev, 'subs>>,
4436 ) -> fmt::Result {
4437 let ctx = try_begin_demangle!(self, ctx, scope);
4438
4439 ctx.push_inner(&self.0);
4440 self.1.demangle(ctx, scope)?;
4441 if ctx.pop_inner_if(&self.0) {
4442 self.0.demangle_as_inner(ctx, scope)?;
4443 }
4444 Ok(())
4445 }
4446}
4447
4448impl<'a> GetLeafName<'a> for QualifiedBuiltin {
4449 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4450 None
4451 }
4452}
4453
4454#[derive(Clone, Debug, PartialEq, Eq)]
4460pub enum ExceptionSpec {
4461 NoExcept,
4463 Computed(Expression),
4465 }
4468
4469impl Parse for ExceptionSpec {
4470 fn parse<'a, 'b>(
4471 ctx: &'a ParseContext,
4472 subs: &'a mut SubstitutionTable,
4473 input: IndexStr<'b>,
4474 ) -> Result<(ExceptionSpec, IndexStr<'b>)> {
4475 try_begin_parse!("ExceptionSpec", ctx, input);
4476
4477 if let Ok(tail) = consume(b"Do", input) {
4478 return Ok((ExceptionSpec::NoExcept, tail));
4479 }
4480
4481 let tail = consume(b"DO", input)?;
4482 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4483 let tail = consume(b"E", tail)?;
4484 Ok((ExceptionSpec::Computed(expr), tail))
4485 }
4486}
4487
4488impl<'subs, W> Demangle<'subs, W> for ExceptionSpec
4489where
4490 W: 'subs + DemangleWrite,
4491{
4492 fn demangle<'prev, 'ctx>(
4493 &'subs self,
4494 ctx: &'ctx mut DemangleContext<'subs, W>,
4495 scope: Option<ArgScopeStack<'prev, 'subs>>,
4496 ) -> fmt::Result {
4497 let ctx = try_begin_demangle!(self, ctx, scope);
4498
4499 match *self {
4500 ExceptionSpec::NoExcept => write!(ctx, "noexcept"),
4501 ExceptionSpec::Computed(ref expr) => {
4502 write!(ctx, "noexcept(")?;
4503 expr.demangle(ctx, scope)?;
4504 write!(ctx, ")")
4505 }
4506 }
4507 }
4508}
4509
4510#[derive(Clone, Debug, PartialEq, Eq)]
4516pub struct FunctionType {
4517 cv_qualifiers: CvQualifiers,
4518 exception_spec: Option<ExceptionSpec>,
4519 transaction_safe: bool,
4520 extern_c: bool,
4521 bare: BareFunctionType,
4522 ref_qualifier: Option<RefQualifier>,
4523}
4524
4525impl Parse for FunctionType {
4526 fn parse<'a, 'b>(
4527 ctx: &'a ParseContext,
4528 subs: &'a mut SubstitutionTable,
4529 input: IndexStr<'b>,
4530 ) -> Result<(FunctionType, IndexStr<'b>)> {
4531 try_begin_parse!("FunctionType", ctx, input);
4532
4533 let (cv_qualifiers, tail) = if let Ok((cv_qualifiers, tail)) =
4534 try_recurse!(CvQualifiers::parse(ctx, subs, input))
4535 {
4536 (cv_qualifiers, tail)
4537 } else {
4538 (Default::default(), input)
4539 };
4540
4541 let (exception_spec, tail) = if let Ok((exception_spec, tail)) =
4542 try_recurse!(ExceptionSpec::parse(ctx, subs, tail))
4543 {
4544 (Some(exception_spec), tail)
4545 } else {
4546 (None, tail)
4547 };
4548
4549 let (transaction_safe, tail) = if let Ok(tail) = consume(b"Dx", tail) {
4550 (true, tail)
4551 } else {
4552 (false, tail)
4553 };
4554
4555 let tail = consume(b"F", tail)?;
4556
4557 let (extern_c, tail) = if let Ok(tail) = consume(b"Y", tail) {
4558 (true, tail)
4559 } else {
4560 (false, tail)
4561 };
4562
4563 let (bare, tail) = BareFunctionType::parse(ctx, subs, tail)?;
4564
4565 let (ref_qualifier, tail) =
4566 if let Ok((ref_qualifier, tail)) = try_recurse!(RefQualifier::parse(ctx, subs, tail)) {
4567 (Some(ref_qualifier), tail)
4568 } else {
4569 (None, tail)
4570 };
4571
4572 let tail = consume(b"E", tail)?;
4573
4574 let func_ty = FunctionType {
4575 cv_qualifiers: cv_qualifiers,
4576 exception_spec: exception_spec,
4577 transaction_safe: transaction_safe,
4578 extern_c: extern_c,
4579 bare: bare,
4580 ref_qualifier: ref_qualifier,
4581 };
4582 Ok((func_ty, tail))
4583 }
4584}
4585
4586impl<'subs, W> Demangle<'subs, W> for FunctionType
4587where
4588 W: 'subs + DemangleWrite,
4589{
4590 fn demangle<'prev, 'ctx>(
4591 &'subs self,
4592 ctx: &'ctx mut DemangleContext<'subs, W>,
4593 scope: Option<ArgScopeStack<'prev, 'subs>>,
4594 ) -> fmt::Result {
4595 let ctx = try_begin_demangle!(self, ctx, scope);
4596
4597 ctx.push_inner(self);
4598 self.bare.demangle(ctx, scope)?;
4599 if ctx.pop_inner_if(self) {
4600 self.demangle_as_inner(ctx, scope)?;
4601 }
4602 if let Some(ref es) = self.exception_spec {
4603 ctx.ensure_space()?;
4605 es.demangle(ctx, scope)?;
4606 }
4607 Ok(())
4608 }
4609}
4610
4611impl<'subs, W> DemangleAsInner<'subs, W> for FunctionType
4612where
4613 W: 'subs + DemangleWrite,
4614{
4615 fn demangle_as_inner<'prev, 'ctx>(
4616 &'subs self,
4617 ctx: &'ctx mut DemangleContext<'subs, W>,
4618 scope: Option<ArgScopeStack<'prev, 'subs>>,
4619 ) -> fmt::Result {
4620 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4621
4622 if !self.cv_qualifiers.is_empty() {
4623 self.cv_qualifiers.demangle(ctx, scope)?;
4624 }
4625
4626 if let Some(ref rq) = self.ref_qualifier {
4627 ctx.ensure_space()?;
4629 rq.demangle(ctx, scope)?;
4630 }
4631
4632 Ok(())
4633 }
4634
4635 fn downcast_to_function_type(&self) -> Option<&FunctionType> {
4636 Some(self)
4637 }
4638}
4639
4640impl FunctionType {
4641 #[inline]
4642 fn starts_with(input: &IndexStr) -> bool {
4643 input.peek() == Some(b'F')
4644 || (input.peek() == Some(b'D')
4645 && (matches!(
4646 input.peek_second(),
4647 Some(b'o') | Some(b'O') | Some(b'x') | Some(b'w')
4648 )))
4649 }
4650}
4651
4652#[derive(Clone, Debug, PartialEq, Eq)]
4659pub struct BareFunctionType(Vec<TypeHandle>);
4660
4661impl BareFunctionType {
4662 fn ret(&self) -> &TypeHandle {
4663 &self.0[0]
4664 }
4665
4666 fn args(&self) -> &FunctionArgListAndReturnType {
4667 FunctionArgListAndReturnType::new(&self.0)
4668 }
4669}
4670
4671impl Parse for BareFunctionType {
4672 fn parse<'a, 'b>(
4673 ctx: &'a ParseContext,
4674 subs: &'a mut SubstitutionTable,
4675 input: IndexStr<'b>,
4676 ) -> Result<(BareFunctionType, IndexStr<'b>)> {
4677 try_begin_parse!("BareFunctionType", ctx, input);
4678
4679 let (types, tail) = one_or_more::<TypeHandle>(ctx, subs, input)?;
4680 Ok((BareFunctionType(types), tail))
4681 }
4682}
4683
4684impl<'subs, W> Demangle<'subs, W> for BareFunctionType
4685where
4686 W: 'subs + DemangleWrite,
4687{
4688 fn demangle<'prev, 'ctx>(
4689 &'subs self,
4690 ctx: &'ctx mut DemangleContext<'subs, W>,
4691 scope: Option<ArgScopeStack<'prev, 'subs>>,
4692 ) -> fmt::Result {
4693 let ctx = try_begin_demangle!(self, ctx, scope);
4694
4695 ctx.push_inner(self);
4696
4697 self.ret().demangle(ctx, scope)?;
4698
4699 if ctx.pop_inner_if(self) {
4700 ctx.ensure_space()?;
4701 self.demangle_as_inner(ctx, scope)?;
4702 }
4703
4704 Ok(())
4705 }
4706}
4707
4708impl<'subs, W> DemangleAsInner<'subs, W> for BareFunctionType
4709where
4710 W: 'subs + DemangleWrite,
4711{
4712 fn demangle_as_inner<'prev, 'ctx>(
4713 &'subs self,
4714 ctx: &'ctx mut DemangleContext<'subs, W>,
4715 scope: Option<ArgScopeStack<'prev, 'subs>>,
4716 ) -> fmt::Result {
4717 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
4718 self.args().demangle_as_inner(ctx, scope)?;
4719 Ok(())
4720 }
4721}
4722
4723#[derive(Clone, Debug, PartialEq, Eq)]
4730pub enum Decltype {
4731 IdExpression(Expression),
4733
4734 Expression(Expression),
4736}
4737
4738impl Parse for Decltype {
4739 fn parse<'a, 'b>(
4740 ctx: &'a ParseContext,
4741 subs: &'a mut SubstitutionTable,
4742 input: IndexStr<'b>,
4743 ) -> Result<(Decltype, IndexStr<'b>)> {
4744 try_begin_parse!("Decltype", ctx, input);
4745
4746 let tail = consume(b"D", input)?;
4747
4748 if let Ok(tail) = consume(b"t", tail) {
4749 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4750 let tail = consume(b"E", tail)?;
4751 return Ok((Decltype::IdExpression(expr), tail));
4752 }
4753
4754 let tail = consume(b"T", tail)?;
4755 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
4756 let tail = consume(b"E", tail)?;
4757 Ok((Decltype::Expression(expr), tail))
4758 }
4759}
4760
4761impl<'subs, W> Demangle<'subs, W> for Decltype
4762where
4763 W: 'subs + DemangleWrite,
4764{
4765 fn demangle<'prev, 'ctx>(
4766 &'subs self,
4767 ctx: &'ctx mut DemangleContext<'subs, W>,
4768 scope: Option<ArgScopeStack<'prev, 'subs>>,
4769 ) -> fmt::Result {
4770 let ctx = try_begin_demangle!(self, ctx, scope);
4771
4772 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
4773 let ret = match *self {
4774 Decltype::Expression(ref expr) | Decltype::IdExpression(ref expr) => {
4775 write!(ctx, "decltype (")?;
4776 expr.demangle(ctx, scope)?;
4777 write!(ctx, ")")?;
4778 Ok(())
4779 }
4780 };
4781 ctx.pop_demangle_node();
4782 ret
4783 }
4784}
4785
4786#[derive(Clone, Debug, PartialEq, Eq)]
4795pub enum ClassEnumType {
4796 Named(Name),
4799
4800 ElaboratedStruct(Name),
4802
4803 ElaboratedUnion(Name),
4805
4806 ElaboratedEnum(Name),
4808}
4809
4810impl Parse for ClassEnumType {
4811 fn parse<'a, 'b>(
4812 ctx: &'a ParseContext,
4813 subs: &'a mut SubstitutionTable,
4814 input: IndexStr<'b>,
4815 ) -> Result<(ClassEnumType, IndexStr<'b>)> {
4816 try_begin_parse!("ClassEnumType", ctx, input);
4817
4818 if let Ok((name, tail)) = try_recurse!(Name::parse(ctx, subs, input)) {
4819 return Ok((ClassEnumType::Named(name), tail));
4820 }
4821
4822 let tail = consume(b"T", input)?;
4823
4824 if let Ok(tail) = consume(b"s", tail) {
4825 let (name, tail) = Name::parse(ctx, subs, tail)?;
4826 return Ok((ClassEnumType::ElaboratedStruct(name), tail));
4827 }
4828
4829 if let Ok(tail) = consume(b"u", tail) {
4830 let (name, tail) = Name::parse(ctx, subs, tail)?;
4831 return Ok((ClassEnumType::ElaboratedUnion(name), tail));
4832 }
4833
4834 let tail = consume(b"e", tail)?;
4835 let (name, tail) = Name::parse(ctx, subs, tail)?;
4836 Ok((ClassEnumType::ElaboratedEnum(name), tail))
4837 }
4838}
4839
4840impl<'subs, W> Demangle<'subs, W> for ClassEnumType
4841where
4842 W: 'subs + DemangleWrite,
4843{
4844 fn demangle<'prev, 'ctx>(
4845 &'subs self,
4846 ctx: &'ctx mut DemangleContext<'subs, W>,
4847 scope: Option<ArgScopeStack<'prev, 'subs>>,
4848 ) -> fmt::Result {
4849 let ctx = try_begin_demangle!(self, ctx, scope);
4850
4851 match *self {
4852 ClassEnumType::Named(ref name) => name.demangle(ctx, scope),
4853 ClassEnumType::ElaboratedStruct(ref name) => {
4854 write!(ctx, "class ")?;
4855 name.demangle(ctx, scope)
4856 }
4857 ClassEnumType::ElaboratedUnion(ref name) => {
4858 write!(ctx, "union ")?;
4859 name.demangle(ctx, scope)
4860 }
4861 ClassEnumType::ElaboratedEnum(ref name) => {
4862 write!(ctx, "enum ")?;
4863 name.demangle(ctx, scope)
4864 }
4865 }
4866 }
4867}
4868
4869impl<'a> GetLeafName<'a> for ClassEnumType {
4870 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
4871 match *self {
4872 ClassEnumType::Named(ref name)
4873 | ClassEnumType::ElaboratedStruct(ref name)
4874 | ClassEnumType::ElaboratedUnion(ref name)
4875 | ClassEnumType::ElaboratedEnum(ref name) => name.get_leaf_name(subs),
4876 }
4877 }
4878}
4879
4880#[derive(Clone, Debug, PartialEq, Eq)]
4889pub struct UnnamedTypeName(Option<usize>);
4890
4891impl Parse for UnnamedTypeName {
4892 fn parse<'a, 'b>(
4893 ctx: &'a ParseContext,
4894 _subs: &'a mut SubstitutionTable,
4895 input: IndexStr<'b>,
4896 ) -> Result<(UnnamedTypeName, IndexStr<'b>)> {
4897 try_begin_parse!("UnnamedTypeName", ctx, input);
4898
4899 let input = consume(b"Ut", input)?;
4900 let (number, input) = match parse_number(10, false, input) {
4901 Ok((number, input)) => (Some(number as _), input),
4902 Err(_) => (None, input),
4903 };
4904 let input = consume(b"_", input)?;
4905 Ok((UnnamedTypeName(number), input))
4906 }
4907}
4908
4909impl UnnamedTypeName {
4910 #[inline]
4911 fn starts_with(byte: u8) -> bool {
4912 byte == b'U'
4913 }
4914}
4915
4916impl<'subs, W> Demangle<'subs, W> for UnnamedTypeName
4917where
4918 W: 'subs + DemangleWrite,
4919{
4920 fn demangle<'prev, 'ctx>(
4921 &'subs self,
4922 ctx: &'ctx mut DemangleContext<'subs, W>,
4923 scope: Option<ArgScopeStack<'prev, 'subs>>,
4924 ) -> fmt::Result {
4925 let ctx = try_begin_demangle!(self, ctx, scope);
4926
4927 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4928 Ok(())
4929 }
4930}
4931
4932impl<'subs, W> DemangleAsLeaf<'subs, W> for UnnamedTypeName
4933where
4934 W: 'subs + DemangleWrite,
4935{
4936 fn demangle_as_leaf<'me, 'ctx>(
4937 &'me self,
4938 ctx: &'ctx mut DemangleContext<'subs, W>,
4939 ) -> fmt::Result {
4940 let ctx = try_begin_demangle!(self, ctx, None);
4941 if let Some(source_name) = ctx.source_name {
4942 write!(ctx, "{}", source_name)?;
4943 } else {
4944 write!(ctx, "{{unnamed type#{}}}", self.0.map_or(1, |n| n + 1))?;
4945 }
4946 Ok(())
4947 }
4948}
4949
4950impl<'subs> ArgScope<'subs, 'subs> for UnnamedTypeName {
4951 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
4952 Ok(LeafName::UnnamedType(self))
4953 }
4954
4955 fn get_template_arg(
4956 &'subs self,
4957 _: usize,
4958 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
4959 Err(error::Error::BadTemplateArgReference)
4960 }
4961
4962 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
4963 Err(error::Error::BadFunctionArgReference)
4964 }
4965}
4966
4967#[derive(Clone, Debug, PartialEq, Eq)]
4974pub enum ArrayType {
4975 DimensionNumber(usize, TypeHandle),
4977
4978 DimensionExpression(Expression, TypeHandle),
4980
4981 NoDimension(TypeHandle),
4983}
4984
4985impl Parse for ArrayType {
4986 fn parse<'a, 'b>(
4987 ctx: &'a ParseContext,
4988 subs: &'a mut SubstitutionTable,
4989 input: IndexStr<'b>,
4990 ) -> Result<(ArrayType, IndexStr<'b>)> {
4991 try_begin_parse!("ArrayType", ctx, input);
4992
4993 let tail = consume(b"A", input)?;
4994
4995 if let Ok((num, tail)) = parse_number(10, false, tail) {
4996 debug_assert!(num >= 0);
4997 let tail = consume(b"_", tail)?;
4998 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
4999 return Ok((ArrayType::DimensionNumber(num as _, ty), tail));
5000 }
5001
5002 if let Ok((expr, tail)) = try_recurse!(Expression::parse(ctx, subs, tail)) {
5003 let tail = consume(b"_", tail)?;
5004 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5005 return Ok((ArrayType::DimensionExpression(expr, ty), tail));
5006 }
5007
5008 let tail = consume(b"_", tail)?;
5009 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5010 Ok((ArrayType::NoDimension(ty), tail))
5011 }
5012}
5013
5014impl<'subs, W> Demangle<'subs, W> for ArrayType
5015where
5016 W: 'subs + DemangleWrite,
5017{
5018 fn demangle<'prev, 'ctx>(
5019 &'subs self,
5020 ctx: &'ctx mut DemangleContext<'subs, W>,
5021 scope: Option<ArgScopeStack<'prev, 'subs>>,
5022 ) -> fmt::Result {
5023 let ctx = try_begin_demangle!(self, ctx, scope);
5024
5025 ctx.push_inner(self);
5026
5027 match *self {
5028 ArrayType::DimensionNumber(_, ref ty)
5029 | ArrayType::DimensionExpression(_, ref ty)
5030 | ArrayType::NoDimension(ref ty) => {
5031 ty.demangle(ctx, scope)?;
5032 }
5033 }
5034
5035 if ctx.pop_inner_if(self) {
5036 self.demangle_as_inner(ctx, scope)?;
5037 }
5038
5039 Ok(())
5040 }
5041}
5042
5043impl<'subs, W> DemangleAsInner<'subs, W> for ArrayType
5044where
5045 W: 'subs + DemangleWrite,
5046{
5047 fn demangle_as_inner<'prev, 'ctx>(
5048 &'subs self,
5049 ctx: &'ctx mut DemangleContext<'subs, W>,
5050 scope: Option<ArgScopeStack<'prev, 'subs>>,
5051 ) -> fmt::Result {
5052 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
5053
5054 let mut needs_space = true;
5056
5057 while let Some(inner) = ctx.pop_inner() {
5058 let inner_is_array = match inner.downcast_to_type() {
5062 Some(&Type::Qualified(_, ref ty)) => ctx.subs.get_type(ty).map_or(false, |ty| {
5063 DemangleAsInner::<W>::downcast_to_array_type(ty).is_some()
5064 }),
5065 _ => {
5066 if inner.downcast_to_array_type().is_some() {
5067 needs_space = false;
5068 true
5069 } else {
5070 false
5071 }
5072 }
5073 };
5074
5075 if inner_is_array {
5076 inner.demangle_as_inner(ctx, scope)?;
5077 } else {
5078 ctx.ensure_space()?;
5079
5080 if inner.is_qualified() {
5082 inner.demangle_as_inner(ctx, scope)?;
5083 ctx.ensure_space()?;
5084 write!(ctx, "(")?;
5085 } else {
5086 write!(ctx, "(")?;
5087 inner.demangle_as_inner(ctx, scope)?;
5088 }
5089
5090 ctx.demangle_inners(scope)?;
5091 write!(ctx, ")")?;
5092 }
5093 }
5094
5095 if needs_space {
5096 ctx.ensure_space()?;
5097 }
5098
5099 match *self {
5100 ArrayType::DimensionNumber(n, _) => {
5101 write!(ctx, "[{}]", n)?;
5102 }
5103 ArrayType::DimensionExpression(ref expr, _) => {
5104 write!(ctx, "[")?;
5105 expr.demangle(ctx, scope)?;
5106 write!(ctx, "]")?;
5107 }
5108 ArrayType::NoDimension(_) => {
5109 write!(ctx, "[]")?;
5110 }
5111 }
5112
5113 Ok(())
5114 }
5115
5116 fn downcast_to_array_type(&self) -> Option<&ArrayType> {
5117 Some(self)
5118 }
5119}
5120
5121#[derive(Clone, Debug, PartialEq, Eq)]
5128pub enum VectorType {
5129 DimensionNumber(usize, TypeHandle),
5131
5132 DimensionExpression(Expression, TypeHandle),
5134}
5135
5136impl Parse for VectorType {
5137 fn parse<'a, 'b>(
5138 ctx: &'a ParseContext,
5139 subs: &'a mut SubstitutionTable,
5140 input: IndexStr<'b>,
5141 ) -> Result<(VectorType, IndexStr<'b>)> {
5142 try_begin_parse!("VectorType", ctx, input);
5143
5144 let tail = consume(b"Dv", input)?;
5145
5146 if let Ok((num, tail)) = parse_number(10, false, tail) {
5147 debug_assert!(num >= 0);
5148 let tail = consume(b"_", tail)?;
5149 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5150 return Ok((VectorType::DimensionNumber(num as _, ty), tail));
5151 }
5152
5153 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5154 let tail = consume(b"_", tail)?;
5155 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5156 Ok((VectorType::DimensionExpression(expr, ty), tail))
5157 }
5158}
5159
5160impl<'subs, W> Demangle<'subs, W> for VectorType
5161where
5162 W: 'subs + DemangleWrite,
5163{
5164 fn demangle<'prev, 'ctx>(
5165 &'subs self,
5166 ctx: &'ctx mut DemangleContext<'subs, W>,
5167 scope: Option<ArgScopeStack<'prev, 'subs>>,
5168 ) -> fmt::Result {
5169 let ctx = try_begin_demangle!(self, ctx, scope);
5170
5171 ctx.push_inner(self);
5172
5173 match *self {
5174 VectorType::DimensionNumber(_, ref ty) | VectorType::DimensionExpression(_, ref ty) => {
5175 ty.demangle(ctx, scope)?;
5176 }
5177 }
5178
5179 if ctx.pop_inner_if(self) {
5180 self.demangle_as_inner(ctx, scope)?;
5181 }
5182
5183 Ok(())
5184 }
5185}
5186
5187impl<'subs, W> DemangleAsInner<'subs, W> for VectorType
5188where
5189 W: 'subs + DemangleWrite,
5190{
5191 fn demangle_as_inner<'prev, 'ctx>(
5192 &'subs self,
5193 ctx: &'ctx mut DemangleContext<'subs, W>,
5194 scope: Option<ArgScopeStack<'prev, 'subs>>,
5195 ) -> fmt::Result {
5196 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
5197
5198 match *self {
5199 VectorType::DimensionNumber(n, _) => {
5200 write!(ctx, " __vector({})", n)?;
5201 }
5202 VectorType::DimensionExpression(ref expr, _) => {
5203 write!(ctx, " __vector(")?;
5204 expr.demangle(ctx, scope)?;
5205 write!(ctx, ")")?;
5206 }
5207 }
5208
5209 Ok(())
5210 }
5211}
5212
5213#[derive(Clone, Debug, PartialEq, Eq)]
5219pub struct PointerToMemberType(TypeHandle, TypeHandle);
5220
5221impl Parse for PointerToMemberType {
5222 fn parse<'a, 'b>(
5223 ctx: &'a ParseContext,
5224 subs: &'a mut SubstitutionTable,
5225 input: IndexStr<'b>,
5226 ) -> Result<(PointerToMemberType, IndexStr<'b>)> {
5227 try_begin_parse!("PointerToMemberType", ctx, input);
5228
5229 let tail = consume(b"M", input)?;
5230 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
5231 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
5232 Ok((PointerToMemberType(ty1, ty2), tail))
5233 }
5234}
5235
5236impl<'subs, W> Demangle<'subs, W> for PointerToMemberType
5237where
5238 W: 'subs + DemangleWrite,
5239{
5240 fn demangle<'prev, 'ctx>(
5241 &'subs self,
5242 ctx: &'ctx mut DemangleContext<'subs, W>,
5243 scope: Option<ArgScopeStack<'prev, 'subs>>,
5244 ) -> fmt::Result {
5245 let ctx = try_begin_demangle!(self, ctx, scope);
5246
5247 ctx.push_inner(self);
5248 self.1.demangle(ctx, scope)?;
5249 if ctx.pop_inner_if(self) {
5250 self.demangle_as_inner(ctx, scope)?;
5251 }
5252 Ok(())
5253 }
5254}
5255
5256impl<'subs, W> DemangleAsInner<'subs, W> for PointerToMemberType
5257where
5258 W: 'subs + DemangleWrite,
5259{
5260 fn demangle_as_inner<'prev, 'ctx>(
5261 &'subs self,
5262 ctx: &'ctx mut DemangleContext<'subs, W>,
5263 scope: Option<ArgScopeStack<'prev, 'subs>>,
5264 ) -> fmt::Result {
5265 let ctx = try_begin_demangle_as_inner!(self, ctx, scope);
5266
5267 if ctx.last_char_written != Some('(') {
5268 ctx.ensure_space()?;
5269 }
5270
5271 self.0.demangle(ctx, scope)?;
5272 write!(ctx, "::*")?;
5273 Ok(())
5274 }
5275
5276 fn downcast_to_pointer_to_member(&self) -> Option<&PointerToMemberType> {
5277 Some(self)
5278 }
5279}
5280
5281#[derive(Clone, Debug, PartialEq, Eq)]
5288pub struct TemplateParam(usize);
5289
5290impl Parse for TemplateParam {
5291 fn parse<'a, 'b>(
5292 ctx: &'a ParseContext,
5293 _subs: &'a mut SubstitutionTable,
5294 input: IndexStr<'b>,
5295 ) -> Result<(TemplateParam, IndexStr<'b>)> {
5296 try_begin_parse!("TemplateParam", ctx, input);
5297
5298 let input = consume(b"T", input)?;
5299 let (number, input) = match parse_number(10, false, input) {
5300 Ok((number, input)) => ((number + 1) as _, input),
5301 Err(_) => (0, input),
5302 };
5303 let input = consume(b"_", input)?;
5304 Ok((TemplateParam(number), input))
5305 }
5306}
5307
5308impl<'subs, W> Demangle<'subs, W> for TemplateParam
5309where
5310 W: 'subs + DemangleWrite,
5311{
5312 fn demangle<'prev, 'ctx>(
5313 &'subs self,
5314 ctx: &'ctx mut DemangleContext<'subs, W>,
5315 scope: Option<ArgScopeStack<'prev, 'subs>>,
5316 ) -> fmt::Result {
5317 let ctx = try_begin_demangle!(self, ctx, scope);
5318
5319 ctx.push_demangle_node(DemangleNodeType::TemplateParam);
5320 let ret = if ctx.is_lambda_arg {
5321 write!(ctx, "auto:{}", self.0 + 1)
5323 } else {
5324 let arg = self.resolve(scope)?;
5325 arg.demangle(ctx, scope)
5326 };
5327 ctx.pop_demangle_node();
5328 ret
5329 }
5330}
5331
5332impl TemplateParam {
5333 fn resolve<'subs, 'prev>(
5334 &'subs self,
5335 scope: Option<ArgScopeStack<'prev, 'subs>>,
5336 ) -> ::core::result::Result<&'subs TemplateArg, fmt::Error> {
5337 scope
5338 .get_template_arg(self.0)
5339 .map_err(|e| {
5340 log!("Error obtaining template argument: {}", e);
5341 fmt::Error
5342 })
5343 .map(|v| v.0)
5344 }
5345}
5346
5347impl<'a> Hash for &'a TemplateParam {
5348 fn hash<H>(&self, state: &mut H)
5349 where
5350 H: Hasher,
5351 {
5352 let self_ref: &TemplateParam = *self;
5353 let self_ptr = self_ref as *const TemplateParam;
5354 self_ptr.hash(state);
5355 }
5356}
5357
5358#[derive(Clone, Debug, PartialEq, Eq)]
5365pub struct TemplateTemplateParam(TemplateParam);
5366
5367define_handle! {
5368 pub enum TemplateTemplateParamHandle
5370}
5371
5372impl Parse for TemplateTemplateParamHandle {
5373 fn parse<'a, 'b>(
5374 ctx: &'a ParseContext,
5375 subs: &'a mut SubstitutionTable,
5376 input: IndexStr<'b>,
5377 ) -> Result<(TemplateTemplateParamHandle, IndexStr<'b>)> {
5378 try_begin_parse!("TemplateTemplateParamHandle", ctx, input);
5379
5380 if let Ok((sub, tail)) = try_recurse!(Substitution::parse(ctx, subs, input)) {
5381 match sub {
5382 Substitution::WellKnown(component) => {
5383 return Ok((TemplateTemplateParamHandle::WellKnown(component), tail));
5384 }
5385 Substitution::BackReference(idx) => {
5386 return Ok((TemplateTemplateParamHandle::BackReference(idx), tail));
5390 }
5391 }
5392 }
5393
5394 let (param, tail) = TemplateParam::parse(ctx, subs, input)?;
5395 let ttp = TemplateTemplateParam(param);
5396 let ttp = Substitutable::TemplateTemplateParam(ttp);
5397 let idx = subs.insert(ttp);
5398 let handle = TemplateTemplateParamHandle::BackReference(idx);
5399 Ok((handle, tail))
5400 }
5401}
5402
5403impl<'subs, W> Demangle<'subs, W> for TemplateTemplateParam
5404where
5405 W: 'subs + DemangleWrite,
5406{
5407 #[inline]
5408 fn demangle<'prev, 'ctx>(
5409 &'subs self,
5410 ctx: &'ctx mut DemangleContext<'subs, W>,
5411 scope: Option<ArgScopeStack<'prev, 'subs>>,
5412 ) -> fmt::Result {
5413 let ctx = try_begin_demangle!(self, ctx, scope);
5414
5415 self.0.demangle(ctx, scope)
5416 }
5417}
5418
5419#[derive(Clone, Debug, PartialEq, Eq)]
5432pub struct FunctionParam(usize, CvQualifiers, Option<usize>);
5433
5434impl Parse for FunctionParam {
5435 fn parse<'a, 'b>(
5436 ctx: &'a ParseContext,
5437 subs: &'a mut SubstitutionTable,
5438 input: IndexStr<'b>,
5439 ) -> Result<(FunctionParam, IndexStr<'b>)> {
5440 try_begin_parse!("FunctionParam", ctx, input);
5441
5442 let tail = consume(b"f", input)?;
5443 if tail.is_empty() {
5444 return Err(error::Error::UnexpectedEnd);
5445 }
5446
5447 let (scope, tail) = if let Ok(tail) = consume(b"L", tail) {
5448 parse_number(10, false, tail)?
5449 } else {
5450 (0, tail)
5451 };
5452
5453 let tail = consume(b"p", tail)?;
5454
5455 let (qualifiers, tail) = CvQualifiers::parse(ctx, subs, tail)?;
5456
5457 let (param, tail) = if tail.peek() == Some(b'T') {
5458 (None, consume(b"T", tail)?)
5459 } else if let Ok((num, tail)) = parse_number(10, false, tail) {
5460 (Some(num as usize + 1), consume(b"_", tail)?)
5461 } else {
5462 (Some(0), consume(b"_", tail)?)
5463 };
5464
5465 Ok((FunctionParam(scope as _, qualifiers, param), tail))
5466 }
5467}
5468
5469impl<'subs, W> Demangle<'subs, W> for FunctionParam
5470where
5471 W: 'subs + DemangleWrite,
5472{
5473 fn demangle<'prev, 'ctx>(
5474 &'subs self,
5475 ctx: &'ctx mut DemangleContext<'subs, W>,
5476 scope: Option<ArgScopeStack<'prev, 'subs>>,
5477 ) -> fmt::Result {
5478 let ctx = try_begin_demangle!(self, ctx, scope);
5479
5480 match self.2 {
5481 None => write!(ctx, "this"),
5482 Some(i) => write!(ctx, "{{parm#{}}}", i + 1),
5483 }
5484 }
5485}
5486
5487#[derive(Clone, Debug, PartialEq, Eq)]
5493pub struct TemplateArgs(Vec<TemplateArg>);
5494
5495impl Parse for TemplateArgs {
5496 fn parse<'a, 'b>(
5497 ctx: &'a ParseContext,
5498 subs: &'a mut SubstitutionTable,
5499 input: IndexStr<'b>,
5500 ) -> Result<(TemplateArgs, IndexStr<'b>)> {
5501 try_begin_parse!("TemplateArgs", ctx, input);
5502
5503 let tail = consume(b"I", input)?;
5504
5505 let (args, tail) = one_or_more::<TemplateArg>(ctx, subs, tail)?;
5506 let tail = consume(b"E", tail)?;
5507 Ok((TemplateArgs(args), tail))
5508 }
5509}
5510
5511impl<'subs, W> Demangle<'subs, W> for TemplateArgs
5512where
5513 W: 'subs + DemangleWrite,
5514{
5515 fn demangle<'prev, 'ctx>(
5516 &'subs self,
5517 ctx: &'ctx mut DemangleContext<'subs, W>,
5518 mut scope: Option<ArgScopeStack<'prev, 'subs>>,
5519 ) -> fmt::Result {
5520 let ctx = try_begin_demangle!(self, ctx, scope);
5521 inner_barrier!(ctx);
5522
5523 if ctx.last_char_written == Some('<') {
5524 write!(ctx, " ")?;
5525 }
5526 write!(ctx, "<")?;
5527 ctx.push_demangle_node(DemangleNodeType::TemplateArgs);
5528 let mut need_comma = false;
5529 for arg_index in 0..self.0.len() {
5530 if need_comma {
5531 write!(ctx, ", ")?;
5532 }
5533 if let Some(ref mut scope) = scope {
5534 scope.in_arg = Some((arg_index, self));
5535 }
5536 self.0[arg_index].demangle(ctx, scope)?;
5537 need_comma = true;
5538 }
5539
5540 if ctx.last_char_written == Some('>') {
5543 write!(ctx, " ")?;
5544 }
5545 ctx.pop_demangle_node();
5546 write!(ctx, ">")?;
5547 Ok(())
5548 }
5549}
5550
5551impl<'subs> ArgScope<'subs, 'subs> for TemplateArgs {
5552 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
5553 Err(error::Error::BadLeafNameReference)
5554 }
5555
5556 fn get_template_arg(
5557 &'subs self,
5558 idx: usize,
5559 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
5560 self.0
5561 .get(idx)
5562 .ok_or(error::Error::BadTemplateArgReference)
5563 .map(|v| (v, self))
5564 }
5565
5566 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
5567 Err(error::Error::BadFunctionArgReference)
5568 }
5569}
5570
5571#[derive(Clone, Debug, PartialEq, Eq)]
5580pub enum TemplateArg {
5581 Type(TypeHandle),
5583
5584 Expression(Expression),
5586
5587 SimpleExpression(ExprPrimary),
5589
5590 ArgPack(Vec<TemplateArg>),
5592}
5593
5594impl Parse for TemplateArg {
5595 fn parse<'a, 'b>(
5596 ctx: &'a ParseContext,
5597 subs: &'a mut SubstitutionTable,
5598 input: IndexStr<'b>,
5599 ) -> Result<(TemplateArg, IndexStr<'b>)> {
5600 try_begin_parse!("TemplateArg", ctx, input);
5601
5602 if let Ok(tail) = consume(b"X", input) {
5603 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5604 let tail = consume(b"E", tail)?;
5605 return Ok((TemplateArg::Expression(expr), tail));
5606 }
5607
5608 if let Ok((expr, tail)) = try_recurse!(ExprPrimary::parse(ctx, subs, input)) {
5609 return Ok((TemplateArg::SimpleExpression(expr), tail));
5610 }
5611
5612 if let Ok((ty, tail)) = try_recurse!(TypeHandle::parse(ctx, subs, input)) {
5613 return Ok((TemplateArg::Type(ty), tail));
5614 }
5615
5616 let tail = if input.peek() == Some(b'J') {
5617 consume(b"J", input)?
5618 } else {
5619 consume(b"I", input)?
5620 };
5621
5622 let (args, tail) = if tail.peek() == Some(b'E') {
5623 (vec![], tail)
5624 } else {
5625 zero_or_more::<TemplateArg>(ctx, subs, tail)?
5626 };
5627 let tail = consume(b"E", tail)?;
5628 Ok((TemplateArg::ArgPack(args), tail))
5629 }
5630}
5631
5632impl<'subs, W> Demangle<'subs, W> for TemplateArg
5633where
5634 W: 'subs + DemangleWrite,
5635{
5636 fn demangle<'prev, 'ctx>(
5637 &'subs self,
5638 ctx: &'ctx mut DemangleContext<'subs, W>,
5639 scope: Option<ArgScopeStack<'prev, 'subs>>,
5640 ) -> fmt::Result {
5641 let ctx = try_begin_demangle!(self, ctx, scope);
5642
5643 match *self {
5644 TemplateArg::Type(ref ty) => ty.demangle(ctx, scope),
5645 TemplateArg::Expression(ref expr) => expr.demangle(ctx, scope),
5646 TemplateArg::SimpleExpression(ref expr) => expr.demangle(ctx, scope),
5647 TemplateArg::ArgPack(ref args) => {
5648 ctx.is_template_argument_pack = true;
5649 let mut need_comma = false;
5650 for arg in &args[..] {
5651 if need_comma {
5652 write!(ctx, ", ")?;
5653 }
5654 arg.demangle(ctx, scope)?;
5655 need_comma = true;
5656 }
5657 Ok(())
5658 }
5659 }
5660 }
5661}
5662
5663#[derive(Clone, Debug, PartialEq, Eq)]
5669pub struct MemberName(Name);
5670
5671impl Parse for MemberName {
5672 fn parse<'a, 'b>(
5673 ctx: &'a ParseContext,
5674 subs: &'a mut SubstitutionTable,
5675 input: IndexStr<'b>,
5676 ) -> Result<(MemberName, IndexStr<'b>)> {
5677 try_begin_parse!("MemberName", ctx, input);
5678
5679 let (name, tail) = UnqualifiedName::parse(ctx, subs, input)?;
5680 let name = UnscopedName::Unqualified(name);
5681 if let Ok((template, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
5682 let name = UnscopedTemplateName(name);
5683 let idx = subs.insert_non_substitution(Substitutable::UnscopedTemplateName(name));
5685 let handle = UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(idx));
5686 Ok((MemberName(Name::UnscopedTemplate(handle, template)), tail))
5687 } else {
5688 Ok((MemberName(Name::Unscoped(name)), tail))
5689 }
5690 }
5691}
5692
5693impl<'subs, W> Demangle<'subs, W> for MemberName
5694where
5695 W: 'subs + DemangleWrite,
5696{
5697 fn demangle<'prev, 'ctx>(
5698 &'subs self,
5699 ctx: &'ctx mut DemangleContext<'subs, W>,
5700 scope: Option<ArgScopeStack<'prev, 'subs>>,
5701 ) -> fmt::Result {
5702 let ctx = try_begin_demangle!(self, ctx, scope);
5703
5704 let needs_parens = self.0.get_template_args(ctx.subs).is_some();
5705 if needs_parens {
5706 write!(ctx, "(")?;
5707 }
5708
5709 self.0.demangle(ctx, scope)?;
5710
5711 if needs_parens {
5712 write!(ctx, ")")?;
5713 }
5714
5715 Ok(())
5716 }
5717}
5718
5719#[derive(Clone, Debug, PartialEq, Eq)]
5767pub enum Expression {
5768 Unary(OperatorName, Box<Expression>),
5770
5771 Binary(OperatorName, Box<Expression>, Box<Expression>),
5773
5774 Ternary(
5776 OperatorName,
5777 Box<Expression>,
5778 Box<Expression>,
5779 Box<Expression>,
5780 ),
5781
5782 PrefixInc(Box<Expression>),
5784
5785 PrefixDec(Box<Expression>),
5787
5788 Call(Box<Expression>, Vec<Expression>),
5790
5791 ConversionOne(TypeHandle, Box<Expression>),
5793
5794 ConversionMany(TypeHandle, Vec<Expression>),
5796
5797 ConversionBraced(TypeHandle, Vec<Expression>),
5799
5800 BracedInitList(Box<Expression>),
5802
5803 New(Vec<Expression>, TypeHandle, Option<Initializer>),
5805
5806 GlobalNew(Vec<Expression>, TypeHandle, Option<Initializer>),
5808
5809 NewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5811
5812 GlobalNewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5814
5815 Delete(Box<Expression>),
5817
5818 GlobalDelete(Box<Expression>),
5820
5821 DeleteArray(Box<Expression>),
5823
5824 GlobalDeleteArray(Box<Expression>),
5826
5827 DynamicCast(TypeHandle, Box<Expression>),
5829
5830 StaticCast(TypeHandle, Box<Expression>),
5832
5833 ConstCast(TypeHandle, Box<Expression>),
5835
5836 ReinterpretCast(TypeHandle, Box<Expression>),
5838
5839 TypeidType(TypeHandle),
5841
5842 TypeidExpr(Box<Expression>),
5844
5845 SizeofType(TypeHandle),
5847
5848 SizeofExpr(Box<Expression>),
5850
5851 AlignofType(TypeHandle),
5853
5854 AlignofExpr(Box<Expression>),
5856
5857 Noexcept(Box<Expression>),
5859
5860 Subobject(SubobjectExpr),
5862
5863 TemplateParam(TemplateParam),
5865
5866 FunctionParam(FunctionParam),
5868
5869 Member(Box<Expression>, MemberName),
5871
5872 DerefMember(Box<Expression>, MemberName),
5874
5875 PointerToMember(Box<Expression>, Box<Expression>),
5877
5878 SizeofTemplatePack(TemplateParam),
5880
5881 SizeofFunctionPack(FunctionParam),
5883
5884 SizeofCapturedTemplatePack(Vec<TemplateArg>),
5887
5888 PackExpansion(Box<Expression>),
5890
5891 Throw(Box<Expression>),
5893
5894 Rethrow,
5896
5897 UnresolvedName(UnresolvedName),
5900
5901 Primary(ExprPrimary),
5903}
5904
5905impl Parse for Expression {
5906 fn parse<'a, 'b>(
5907 ctx: &'a ParseContext,
5908 subs: &'a mut SubstitutionTable,
5909 input: IndexStr<'b>,
5910 ) -> Result<(Expression, IndexStr<'b>)> {
5911 try_begin_parse!("Expression", ctx, input);
5912
5913 if let Ok(tail) = consume(b"pp_", input) {
5914 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5915 let expr = Expression::PrefixInc(Box::new(expr));
5916 return Ok((expr, tail));
5917 }
5918
5919 if let Ok(tail) = consume(b"mm_", input) {
5920 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5921 let expr = Expression::PrefixDec(Box::new(expr));
5922 return Ok((expr, tail));
5923 }
5924
5925 if let Some((head, tail)) = input.try_split_at(2) {
5926 match head.as_ref() {
5927 b"cl" => {
5928 let (func, tail) = Expression::parse(ctx, subs, tail)?;
5929 let (args, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5930 let tail = consume(b"E", tail)?;
5931 let expr = Expression::Call(Box::new(func), args);
5932 return Ok((expr, tail));
5933 }
5934 b"cv" => {
5935 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5936 if let Ok(tail) = consume(b"_", tail) {
5937 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5938 let tail = consume(b"E", tail)?;
5939 let expr = Expression::ConversionMany(ty, exprs);
5940 return Ok((expr, tail));
5941 } else {
5942 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5943 let expr = Expression::ConversionOne(ty, Box::new(expr));
5944 return Ok((expr, tail));
5945 }
5946 }
5947 b"tl" => {
5948 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5949 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5950 let expr = Expression::ConversionBraced(ty, exprs);
5951 let tail = consume(b"E", tail)?;
5952 return Ok((expr, tail));
5953 }
5954 b"il" => {
5955 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5956 let tail = consume(b"E", tail)?;
5957 let expr = Expression::BracedInitList(Box::new(expr));
5958 return Ok((expr, tail));
5959 }
5960 b"dc" => {
5961 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5962 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5963 let expr = Expression::DynamicCast(ty, Box::new(expr));
5964 return Ok((expr, tail));
5965 }
5966 b"sc" => {
5967 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5968 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5969 let expr = Expression::StaticCast(ty, Box::new(expr));
5970 return Ok((expr, tail));
5971 }
5972 b"cc" => {
5973 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5974 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5975 let expr = Expression::ConstCast(ty, Box::new(expr));
5976 return Ok((expr, tail));
5977 }
5978 b"rc" => {
5979 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5980 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5981 let expr = Expression::ReinterpretCast(ty, Box::new(expr));
5982 return Ok((expr, tail));
5983 }
5984 b"ti" => {
5985 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5986 let expr = Expression::TypeidType(ty);
5987 return Ok((expr, tail));
5988 }
5989 b"te" => {
5990 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5991 let expr = Expression::TypeidExpr(Box::new(expr));
5992 return Ok((expr, tail));
5993 }
5994 b"st" => {
5995 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5996 let expr = Expression::SizeofType(ty);
5997 return Ok((expr, tail));
5998 }
5999 b"sz" => {
6000 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6001 let expr = Expression::SizeofExpr(Box::new(expr));
6002 return Ok((expr, tail));
6003 }
6004 b"at" => {
6005 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6006 let expr = Expression::AlignofType(ty);
6007 return Ok((expr, tail));
6008 }
6009 b"az" => {
6010 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6011 let expr = Expression::AlignofExpr(Box::new(expr));
6012 return Ok((expr, tail));
6013 }
6014 b"nx" => {
6015 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6016 let expr = Expression::Noexcept(Box::new(expr));
6017 return Ok((expr, tail));
6018 }
6019 b"so" => {
6020 let (expr, tail) = SubobjectExpr::parse(ctx, subs, tail)?;
6021 let expr = Expression::Subobject(expr);
6022 return Ok((expr, tail));
6023 }
6024 b"dt" => {
6025 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6026 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
6027 let expr = Expression::Member(Box::new(expr), name);
6028 return Ok((expr, tail));
6029 }
6030 b"pt" => {
6031 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6032 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
6033 let expr = Expression::DerefMember(Box::new(expr), name);
6034 return Ok((expr, tail));
6035 }
6036 b"ds" => {
6037 let (first, tail) = Expression::parse(ctx, subs, tail)?;
6038 let (second, tail) = Expression::parse(ctx, subs, tail)?;
6039 let expr = Expression::PointerToMember(Box::new(first), Box::new(second));
6040 return Ok((expr, tail));
6041 }
6042 b"sZ" => {
6043 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, tail) {
6044 let expr = Expression::SizeofTemplatePack(param);
6045 return Ok((expr, tail));
6046 }
6047
6048 let (param, tail) = FunctionParam::parse(ctx, subs, tail)?;
6049 let expr = Expression::SizeofFunctionPack(param);
6050 return Ok((expr, tail));
6051 }
6052 b"sP" => {
6053 let (args, tail) = zero_or_more::<TemplateArg>(ctx, subs, tail)?;
6054 let expr = Expression::SizeofCapturedTemplatePack(args);
6055 let tail = consume(b"E", tail)?;
6056 return Ok((expr, tail));
6057 }
6058 b"sp" => {
6059 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6060 let expr = Expression::PackExpansion(Box::new(expr));
6061 return Ok((expr, tail));
6062 }
6063 b"tw" => {
6064 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6065 let expr = Expression::Throw(Box::new(expr));
6066 return Ok((expr, tail));
6067 }
6068 b"tr" => {
6069 let expr = Expression::Rethrow;
6070 return Ok((expr, tail));
6071 }
6072 b"gs" => {
6073 if let Ok((expr, tail)) = try_recurse!(can_be_global(true, ctx, subs, tail)) {
6074 return Ok((expr, tail));
6075 }
6076 }
6077 _ => {}
6078 }
6079 }
6080
6081 if let Ok((expr, tail)) = try_recurse!(can_be_global(false, ctx, subs, input)) {
6082 return Ok((expr, tail));
6083 }
6084
6085 if let Ok((param, tail)) = try_recurse!(TemplateParam::parse(ctx, subs, input)) {
6086 let expr = Expression::TemplateParam(param);
6087 return Ok((expr, tail));
6088 }
6089
6090 if let Ok((param, tail)) = try_recurse!(FunctionParam::parse(ctx, subs, input)) {
6091 let expr = Expression::FunctionParam(param);
6092 return Ok((expr, tail));
6093 }
6094
6095 if let Ok((name, tail)) = try_recurse!(UnresolvedName::parse(ctx, subs, input)) {
6096 let expr = Expression::UnresolvedName(name);
6097 return Ok((expr, tail));
6098 }
6099
6100 if let Ok((prim, tail)) = try_recurse!(ExprPrimary::parse(ctx, subs, input)) {
6101 let expr = Expression::Primary(prim);
6102 return Ok((expr, tail));
6103 }
6104
6105 let (expr, tail) = OperatorName::parse_from_expr(ctx, subs, input)?;
6110 return Ok((expr, tail));
6111
6112 fn can_be_global<'a, 'b>(
6117 is_global: bool,
6118 ctx: &'a ParseContext,
6119 subs: &'a mut SubstitutionTable,
6120 input: IndexStr<'b>,
6121 ) -> Result<(Expression, IndexStr<'b>)> {
6122 match input.try_split_at(2) {
6123 None => Err(error::Error::UnexpectedEnd),
6124 Some((head, tail)) => match head.as_ref() {
6125 b"nw" => {
6126 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6127 let tail = consume(b"_", tail)?;
6128 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6129 if let Ok(tail) = consume(b"E", tail) {
6130 let expr = if is_global {
6131 Expression::GlobalNew(exprs, ty, None)
6132 } else {
6133 Expression::New(exprs, ty, None)
6134 };
6135 Ok((expr, tail))
6136 } else {
6137 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
6138 let expr = if is_global {
6139 Expression::GlobalNew(exprs, ty, Some(init))
6140 } else {
6141 Expression::New(exprs, ty, Some(init))
6142 };
6143 Ok((expr, tail))
6144 }
6145 }
6146 b"na" => {
6147 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6148 let tail = consume(b"_", tail)?;
6149 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6150 if let Ok(tail) = consume(b"E", tail) {
6151 let expr = if is_global {
6152 Expression::GlobalNewArray(exprs, ty, None)
6153 } else {
6154 Expression::NewArray(exprs, ty, None)
6155 };
6156 Ok((expr, tail))
6157 } else {
6158 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
6159 let expr = if is_global {
6160 Expression::GlobalNewArray(exprs, ty, Some(init))
6161 } else {
6162 Expression::NewArray(exprs, ty, Some(init))
6163 };
6164 Ok((expr, tail))
6165 }
6166 }
6167 b"dl" => {
6168 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6169 let expr = if is_global {
6170 Expression::GlobalDelete(Box::new(expr))
6171 } else {
6172 Expression::Delete(Box::new(expr))
6173 };
6174 Ok((expr, tail))
6175 }
6176 b"da" => {
6177 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6178 let expr = if is_global {
6179 Expression::GlobalDeleteArray(Box::new(expr))
6180 } else {
6181 Expression::DeleteArray(Box::new(expr))
6182 };
6183 Ok((expr, tail))
6184 }
6185 _ => Err(error::Error::UnexpectedText),
6186 },
6187 }
6188 }
6189 }
6190}
6191
6192impl<'subs, W> Demangle<'subs, W> for Expression
6193where
6194 W: 'subs + DemangleWrite,
6195{
6196 fn demangle<'prev, 'ctx>(
6197 &'subs self,
6198 ctx: &'ctx mut DemangleContext<'subs, W>,
6199 scope: Option<ArgScopeStack<'prev, 'subs>>,
6200 ) -> fmt::Result {
6201 let ctx = try_begin_demangle!(self, ctx, scope);
6202
6203 match *self {
6204 Expression::Unary(OperatorName::Simple(ref op), ref expr)
6205 if *op == SimpleOperatorName::PostInc || *op == SimpleOperatorName::PostDec =>
6206 {
6207 expr.demangle_as_subexpr(ctx, scope)?;
6208 op.demangle(ctx, scope)
6209 }
6210 Expression::Unary(ref op, ref expr) => {
6211 op.demangle(ctx, scope)?;
6212 expr.demangle_as_subexpr(ctx, scope)
6213 }
6214 Expression::Binary(
6217 OperatorName::Simple(SimpleOperatorName::Greater),
6218 ref lhs,
6219 ref rhs,
6220 ) => {
6221 write!(ctx, "((")?;
6222 lhs.demangle(ctx, scope)?;
6223 write!(ctx, ")>(")?;
6224 rhs.demangle(ctx, scope)?;
6225 write!(ctx, "))")
6226 }
6227 Expression::Binary(ref op, ref lhs, ref rhs) => {
6228 lhs.demangle_as_subexpr(ctx, scope)?;
6229 op.demangle(ctx, scope)?;
6230 rhs.demangle_as_subexpr(ctx, scope)
6231 }
6232 Expression::Ternary(
6233 OperatorName::Simple(SimpleOperatorName::Question),
6234 ref condition,
6235 ref consequent,
6236 ref alternative,
6237 ) => {
6238 condition.demangle_as_subexpr(ctx, scope)?;
6239 write!(ctx, "?")?;
6240 consequent.demangle_as_subexpr(ctx, scope)?;
6241 write!(ctx, " : ")?;
6242 alternative.demangle_as_subexpr(ctx, scope)
6243 }
6244 Expression::Ternary(ref op, ref e1, ref e2, ref e3) => {
6245 op.demangle(ctx, scope)?;
6250 write!(ctx, "(")?;
6251 e1.demangle(ctx, scope)?;
6252 write!(ctx, ", ")?;
6253 e2.demangle(ctx, scope)?;
6254 write!(ctx, ", ")?;
6255 e3.demangle(ctx, scope)?;
6256 write!(ctx, ")")?;
6257 Ok(())
6258 }
6259 Expression::PrefixInc(ref expr) => {
6260 write!(ctx, "++")?;
6261 expr.demangle(ctx, scope)
6262 }
6263 Expression::PrefixDec(ref expr) => {
6264 write!(ctx, "--")?;
6265 expr.demangle(ctx, scope)
6266 }
6267 Expression::Call(ref functor_expr, ref args) => {
6268 functor_expr.demangle_as_subexpr(ctx, scope)?;
6269 write!(ctx, "(")?;
6270 let mut need_comma = false;
6271 for arg in args {
6272 if need_comma {
6273 write!(ctx, ", ")?;
6274 }
6275 arg.demangle(ctx, scope)?;
6276 need_comma = true;
6277 }
6278 write!(ctx, ")")?;
6279 Ok(())
6280 }
6281 Expression::ConversionOne(ref ty, ref expr) => {
6282 write!(ctx, "(")?;
6283 ty.demangle(ctx, scope)?;
6284 write!(ctx, ")(")?;
6285 expr.demangle(ctx, scope)?;
6286 write!(ctx, ")")?;
6287 Ok(())
6288 }
6289 Expression::ConversionMany(ref ty, ref exprs) => {
6290 ty.demangle(ctx, scope)?;
6291 write!(ctx, "(")?;
6292 let mut need_comma = false;
6293 for expr in exprs {
6294 if need_comma {
6295 write!(ctx, ", ")?;
6296 }
6297 expr.demangle(ctx, scope)?;
6298 need_comma = true;
6299 }
6300 write!(ctx, ")")?;
6301 Ok(())
6302 }
6303 Expression::ConversionBraced(ref ty, ref exprs) => {
6304 ty.demangle(ctx, scope)?;
6305 write!(ctx, "{{")?;
6306 let mut need_comma = false;
6307 for expr in exprs {
6308 if need_comma {
6309 write!(ctx, ", ")?;
6310 }
6311 expr.demangle(ctx, scope)?;
6312 need_comma = true;
6313 }
6314 write!(ctx, "}}")?;
6315 Ok(())
6316 }
6317 Expression::BracedInitList(ref expr) => {
6318 write!(ctx, "{{")?;
6319 expr.demangle(ctx, scope)?;
6320 write!(ctx, "}}")?;
6321 Ok(())
6322 }
6323 Expression::New(ref exprs, ref ty, ref init) => {
6325 write!(ctx, "new (")?;
6326 let mut need_comma = false;
6327 for expr in exprs {
6328 if need_comma {
6329 write!(ctx, ", ")?;
6330 }
6331 expr.demangle(ctx, scope)?;
6332 need_comma = true;
6333 }
6334 write!(ctx, ") ")?;
6335 ty.demangle(ctx, scope)?;
6336 if let Some(ref init) = *init {
6337 init.demangle(ctx, scope)?;
6338 }
6339 Ok(())
6340 }
6341 Expression::GlobalNew(ref exprs, ref ty, ref init) => {
6342 write!(ctx, "::new (")?;
6343 let mut need_comma = false;
6344 for expr in exprs {
6345 if need_comma {
6346 write!(ctx, ", ")?;
6347 }
6348 expr.demangle(ctx, scope)?;
6349 need_comma = true;
6350 }
6351 write!(ctx, ") ")?;
6352 ty.demangle(ctx, scope)?;
6353 if let Some(ref init) = *init {
6354 init.demangle(ctx, scope)?;
6355 }
6356 Ok(())
6357 }
6358 Expression::NewArray(ref exprs, ref ty, ref init) => {
6359 write!(ctx, "new[] (")?;
6360 let mut need_comma = false;
6361 for expr in exprs {
6362 if need_comma {
6363 write!(ctx, ", ")?;
6364 }
6365 expr.demangle(ctx, scope)?;
6366 need_comma = true;
6367 }
6368 write!(ctx, ") ")?;
6369 ty.demangle(ctx, scope)?;
6370 if let Some(ref init) = *init {
6371 init.demangle(ctx, scope)?;
6372 }
6373 Ok(())
6374 }
6375 Expression::GlobalNewArray(ref exprs, ref ty, ref init) => {
6376 write!(ctx, "::new[] (")?;
6377 let mut need_comma = false;
6378 for expr in exprs {
6379 if need_comma {
6380 write!(ctx, ", ")?;
6381 }
6382 expr.demangle(ctx, scope)?;
6383 need_comma = true;
6384 }
6385 write!(ctx, ") ")?;
6386 ty.demangle(ctx, scope)?;
6387 if let Some(ref init) = *init {
6388 init.demangle(ctx, scope)?;
6389 }
6390 Ok(())
6391 }
6392 Expression::Delete(ref expr) => {
6393 write!(ctx, "delete ")?;
6394 expr.demangle(ctx, scope)
6395 }
6396 Expression::GlobalDelete(ref expr) => {
6397 write!(ctx, "::delete ")?;
6398 expr.demangle(ctx, scope)
6399 }
6400 Expression::DeleteArray(ref expr) => {
6401 write!(ctx, "delete[] ")?;
6402 expr.demangle(ctx, scope)
6403 }
6404 Expression::GlobalDeleteArray(ref expr) => {
6405 write!(ctx, "::delete[] ")?;
6406 expr.demangle(ctx, scope)
6407 }
6408 Expression::DynamicCast(ref ty, ref expr) => {
6410 write!(ctx, "dynamic_cast<")?;
6411 ty.demangle(ctx, scope)?;
6412 write!(ctx, ">(")?;
6413 expr.demangle(ctx, scope)?;
6414 write!(ctx, ")")?;
6415 Ok(())
6416 }
6417 Expression::StaticCast(ref ty, ref expr) => {
6418 write!(ctx, "static_cast<")?;
6419 ty.demangle(ctx, scope)?;
6420 write!(ctx, ">(")?;
6421 expr.demangle(ctx, scope)?;
6422 write!(ctx, ")")?;
6423 Ok(())
6424 }
6425 Expression::ConstCast(ref ty, ref expr) => {
6426 write!(ctx, "const_cast<")?;
6427 ty.demangle(ctx, scope)?;
6428 write!(ctx, ">(")?;
6429 expr.demangle(ctx, scope)?;
6430 write!(ctx, ")")?;
6431 Ok(())
6432 }
6433 Expression::ReinterpretCast(ref ty, ref expr) => {
6434 write!(ctx, "reinterpret_cast<")?;
6435 ty.demangle(ctx, scope)?;
6436 write!(ctx, ">(")?;
6437 expr.demangle(ctx, scope)?;
6438 write!(ctx, ")")?;
6439 Ok(())
6440 }
6441 Expression::TypeidType(ref ty) => {
6442 write!(ctx, "typeid (")?;
6443 ty.demangle(ctx, scope)?;
6444 write!(ctx, ")")?;
6445 Ok(())
6446 }
6447 Expression::TypeidExpr(ref expr) => {
6448 write!(ctx, "typeid (")?;
6449 expr.demangle(ctx, scope)?;
6450 write!(ctx, ")")?;
6451 Ok(())
6452 }
6453 Expression::SizeofType(ref ty) => {
6454 write!(ctx, "sizeof (")?;
6455 ty.demangle(ctx, scope)?;
6456 write!(ctx, ")")?;
6457 Ok(())
6458 }
6459 Expression::SizeofExpr(ref expr) => {
6460 write!(ctx, "sizeof (")?;
6461 expr.demangle(ctx, scope)?;
6462 write!(ctx, ")")?;
6463 Ok(())
6464 }
6465 Expression::AlignofType(ref ty) => {
6466 write!(ctx, "alignof (")?;
6467 ty.demangle(ctx, scope)?;
6468 write!(ctx, ")")?;
6469 Ok(())
6470 }
6471 Expression::AlignofExpr(ref expr) => {
6472 write!(ctx, "alignof (")?;
6473 expr.demangle(ctx, scope)?;
6474 write!(ctx, ")")?;
6475 Ok(())
6476 }
6477 Expression::Noexcept(ref expr) => {
6478 write!(ctx, "noexcept (")?;
6479 expr.demangle(ctx, scope)?;
6480 write!(ctx, ")")?;
6481 Ok(())
6482 }
6483 Expression::Subobject(ref expr) => expr.demangle(ctx, scope),
6484 Expression::TemplateParam(ref param) => param.demangle(ctx, scope),
6485 Expression::FunctionParam(ref param) => param.demangle(ctx, scope),
6486 Expression::Member(ref expr, ref name) => {
6487 expr.demangle_as_subexpr(ctx, scope)?;
6488 write!(ctx, ".")?;
6489 name.demangle(ctx, scope)
6490 }
6491 Expression::DerefMember(ref expr, ref name) => {
6492 expr.demangle(ctx, scope)?;
6493 write!(ctx, "->")?;
6494 name.demangle(ctx, scope)
6495 }
6496 Expression::PointerToMember(ref e1, ref e2) => {
6497 e1.demangle(ctx, scope)?;
6498 write!(ctx, ".*")?;
6499 e2.demangle(ctx, scope)
6500 }
6501 Expression::SizeofTemplatePack(ref param) => {
6502 write!(ctx, "sizeof...(")?;
6503 param.demangle(ctx, scope)?;
6504 write!(ctx, ")")?;
6505 Ok(())
6506 }
6507 Expression::SizeofFunctionPack(ref param) => {
6508 write!(ctx, "sizeof...(")?;
6509 param.demangle(ctx, scope)?;
6510 write!(ctx, ")")?;
6511 Ok(())
6512 }
6513 Expression::SizeofCapturedTemplatePack(ref args) => {
6514 write!(ctx, "sizeof...(")?;
6515 let mut need_comma = false;
6516 for arg in args {
6517 if need_comma {
6518 write!(ctx, ", ")?;
6519 }
6520 arg.demangle(ctx, scope)?;
6521 need_comma = true;
6522 }
6523 write!(ctx, ")")?;
6524 Ok(())
6525 }
6526 Expression::PackExpansion(ref pack) => {
6527 pack.demangle_as_subexpr(ctx, scope)?;
6528 write!(ctx, "...")?;
6529 Ok(())
6530 }
6531 Expression::Throw(ref expr) => {
6532 write!(ctx, "throw ")?;
6533 expr.demangle(ctx, scope)
6534 }
6535 Expression::Rethrow => {
6536 write!(ctx, "throw")?;
6537 Ok(())
6538 }
6539 Expression::UnresolvedName(ref name) => name.demangle(ctx, scope),
6540 Expression::Primary(ref expr) => expr.demangle(ctx, scope),
6541 }
6542 }
6543}
6544
6545impl Expression {
6546 fn demangle_as_subexpr<'subs, 'prev, 'ctx, W>(
6547 &'subs self,
6548 ctx: &'ctx mut DemangleContext<'subs, W>,
6549 scope: Option<ArgScopeStack<'prev, 'subs>>,
6550 ) -> fmt::Result
6551 where
6552 W: 'subs + DemangleWrite,
6553 {
6554 let needs_parens = match *self {
6555 Expression::FunctionParam(_) | Expression::Primary(ExprPrimary::External(_)) => false,
6556 _ => true,
6557 };
6558
6559 if needs_parens {
6560 write!(ctx, "(")?;
6561 }
6562
6563 self.demangle(ctx, scope)?;
6564
6565 if needs_parens {
6566 write!(ctx, ")")?;
6567 }
6568
6569 Ok(())
6570 }
6571}
6572
6573#[derive(Clone, Debug, PartialEq, Eq)]
6586pub enum UnresolvedName {
6587 Name(BaseUnresolvedName),
6589
6590 Global(BaseUnresolvedName),
6592
6593 Nested1(
6595 UnresolvedTypeHandle,
6596 Vec<UnresolvedQualifierLevel>,
6597 BaseUnresolvedName,
6598 ),
6599
6600 Nested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6602
6603 GlobalNested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6605}
6606
6607impl Parse for UnresolvedName {
6608 fn parse<'a, 'b>(
6609 ctx: &'a ParseContext,
6610 subs: &'a mut SubstitutionTable,
6611 input: IndexStr<'b>,
6612 ) -> Result<(UnresolvedName, IndexStr<'b>)> {
6613 try_begin_parse!("UnresolvedName", ctx, input);
6614
6615 if let Ok(tail) = consume(b"gs", input) {
6616 if let Ok((name, tail)) = try_recurse!(BaseUnresolvedName::parse(ctx, subs, tail)) {
6617 return Ok((UnresolvedName::Global(name), tail));
6618 }
6619
6620 let tail = consume(b"sr", tail)?;
6621 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6622 let tail = consume(b"E", tail)?;
6623 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6624 return Ok((UnresolvedName::GlobalNested2(levels, name), tail));
6625 }
6626
6627 if let Ok((name, tail)) = try_recurse!(BaseUnresolvedName::parse(ctx, subs, input)) {
6628 return Ok((UnresolvedName::Name(name), tail));
6629 }
6630
6631 let tail = consume(b"sr", input)?;
6632
6633 if tail.peek() == Some(b'N') {
6634 let tail = consume(b"N", tail).unwrap();
6635 let (ty, tail) = UnresolvedTypeHandle::parse(ctx, subs, tail)?;
6636 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6637 let tail = consume(b"E", tail)?;
6638 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6639 return Ok((UnresolvedName::Nested1(ty, levels, name), tail));
6640 }
6641
6642 if let Ok((ty, tail)) = try_recurse!(UnresolvedTypeHandle::parse(ctx, subs, tail)) {
6643 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6644 return Ok((UnresolvedName::Nested1(ty, vec![], name), tail));
6645 }
6646
6647 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6648 let tail = consume(b"E", tail)?;
6649 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6650 Ok((UnresolvedName::Nested2(levels, name), tail))
6651 }
6652}
6653
6654impl<'subs, W> Demangle<'subs, W> for UnresolvedName
6655where
6656 W: 'subs + DemangleWrite,
6657{
6658 fn demangle<'prev, 'ctx>(
6659 &'subs self,
6660 ctx: &'ctx mut DemangleContext<'subs, W>,
6661 scope: Option<ArgScopeStack<'prev, 'subs>>,
6662 ) -> fmt::Result {
6663 let ctx = try_begin_demangle!(self, ctx, scope);
6664
6665 match *self {
6666 UnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6667 UnresolvedName::Global(ref name) => {
6668 write!(ctx, "::")?;
6669 name.demangle(ctx, scope)
6670 }
6671 UnresolvedName::Nested1(ref ty, ref levels, ref name) => {
6672 ty.demangle(ctx, scope)?;
6673 write!(ctx, "::")?;
6674 for lvl in &levels[..] {
6675 lvl.demangle(ctx, scope)?;
6676 write!(ctx, "::")?;
6677 }
6678 name.demangle(ctx, scope)
6679 }
6680 UnresolvedName::Nested2(ref levels, ref name) => {
6681 for lvl in &levels[..] {
6682 lvl.demangle(ctx, scope)?;
6683 write!(ctx, "::")?;
6684 }
6685 name.demangle(ctx, scope)
6686 }
6687 UnresolvedName::GlobalNested2(ref levels, ref name) => {
6689 write!(ctx, "::")?;
6690 for lvl in &levels[..] {
6691 lvl.demangle(ctx, scope)?;
6692 write!(ctx, "::")?;
6693 }
6694 name.demangle(ctx, scope)
6695 }
6696 }
6697 }
6698}
6699
6700#[derive(Clone, Debug, PartialEq, Eq)]
6708pub enum UnresolvedType {
6709 Template(TemplateParam, Option<TemplateArgs>),
6711
6712 Decltype(Decltype),
6714}
6715
6716define_handle! {
6717 pub enum UnresolvedTypeHandle
6719}
6720
6721impl Parse for UnresolvedTypeHandle {
6722 fn parse<'a, 'b>(
6723 ctx: &'a ParseContext,
6724 subs: &'a mut SubstitutionTable,
6725 input: IndexStr<'b>,
6726 ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)> {
6727 try_begin_parse!("UnresolvedTypeHandle", ctx, input);
6728
6729 if let Ok((param, tail)) = try_recurse!(TemplateParam::parse(ctx, subs, input)) {
6730 let (args, tail) =
6731 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6732 (Some(args), tail)
6733 } else {
6734 (None, tail)
6735 };
6736 let ty = UnresolvedType::Template(param, args);
6737 let ty = Substitutable::UnresolvedType(ty);
6738 let idx = subs.insert(ty);
6739 let handle = UnresolvedTypeHandle::BackReference(idx);
6740 return Ok((handle, tail));
6741 }
6742
6743 if let Ok((decltype, tail)) = try_recurse!(Decltype::parse(ctx, subs, input)) {
6744 let ty = UnresolvedType::Decltype(decltype);
6745 let ty = Substitutable::UnresolvedType(ty);
6746 let idx = subs.insert(ty);
6747 let handle = UnresolvedTypeHandle::BackReference(idx);
6748 return Ok((handle, tail));
6749 }
6750
6751 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
6752 match sub {
6753 Substitution::WellKnown(component) => {
6754 Ok((UnresolvedTypeHandle::WellKnown(component), tail))
6755 }
6756 Substitution::BackReference(idx) => {
6757 Ok((UnresolvedTypeHandle::BackReference(idx), tail))
6760 }
6761 }
6762 }
6763}
6764
6765impl<'subs, W> Demangle<'subs, W> for UnresolvedType
6766where
6767 W: 'subs + DemangleWrite,
6768{
6769 fn demangle<'prev, 'ctx>(
6770 &'subs self,
6771 ctx: &'ctx mut DemangleContext<'subs, W>,
6772 scope: Option<ArgScopeStack<'prev, 'subs>>,
6773 ) -> fmt::Result {
6774 let ctx = try_begin_demangle!(self, ctx, scope);
6775
6776 match *self {
6777 UnresolvedType::Decltype(ref dt) => dt.demangle(ctx, scope),
6778 UnresolvedType::Template(ref param, ref args) => {
6779 if let Some(ref args) = *args {
6780 let scope = scope.push(args);
6781 param.demangle(ctx, scope)?;
6782 args.demangle(ctx, scope)?;
6783 } else {
6784 param.demangle(ctx, scope)?;
6785 }
6786 Ok(())
6787 }
6788 }
6789 }
6790}
6791
6792#[derive(Clone, Debug, PartialEq, Eq)]
6798pub struct UnresolvedQualifierLevel(SimpleId);
6799
6800impl Parse for UnresolvedQualifierLevel {
6801 fn parse<'a, 'b>(
6802 ctx: &'a ParseContext,
6803 subs: &'a mut SubstitutionTable,
6804 input: IndexStr<'b>,
6805 ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)> {
6806 try_begin_parse!("UnresolvedQualifierLevel", ctx, input);
6807
6808 let (id, tail) = SimpleId::parse(ctx, subs, input)?;
6809 Ok((UnresolvedQualifierLevel(id), tail))
6810 }
6811}
6812
6813impl<'subs, W> Demangle<'subs, W> for UnresolvedQualifierLevel
6814where
6815 W: 'subs + DemangleWrite,
6816{
6817 #[inline]
6818 fn demangle<'prev, 'ctx>(
6819 &'subs self,
6820 ctx: &'ctx mut DemangleContext<'subs, W>,
6821 scope: Option<ArgScopeStack<'prev, 'subs>>,
6822 ) -> fmt::Result {
6823 let ctx = try_begin_demangle!(self, ctx, scope);
6824
6825 self.0.demangle(ctx, scope)
6826 }
6827}
6828
6829#[derive(Clone, Debug, PartialEq, Eq)]
6835pub struct SimpleId(SourceName, Option<TemplateArgs>);
6836
6837impl Parse for SimpleId {
6838 fn parse<'a, 'b>(
6839 ctx: &'a ParseContext,
6840 subs: &'a mut SubstitutionTable,
6841 input: IndexStr<'b>,
6842 ) -> Result<(SimpleId, IndexStr<'b>)> {
6843 try_begin_parse!("SimpleId", ctx, input);
6844
6845 let (name, tail) = SourceName::parse(ctx, subs, input)?;
6846 let (args, tail) =
6847 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6848 (Some(args), tail)
6849 } else {
6850 (None, tail)
6851 };
6852 Ok((SimpleId(name, args), tail))
6853 }
6854}
6855
6856impl<'subs, W> Demangle<'subs, W> for SimpleId
6857where
6858 W: 'subs + DemangleWrite,
6859{
6860 fn demangle<'prev, 'ctx>(
6861 &'subs self,
6862 ctx: &'ctx mut DemangleContext<'subs, W>,
6863 scope: Option<ArgScopeStack<'prev, 'subs>>,
6864 ) -> fmt::Result {
6865 let ctx = try_begin_demangle!(self, ctx, scope);
6866
6867 self.0.demangle(ctx, scope)?;
6868 if let Some(ref args) = self.1 {
6869 args.demangle(ctx, scope)?;
6870 }
6871 Ok(())
6872 }
6873}
6874
6875#[derive(Clone, Debug, PartialEq, Eq)]
6885pub enum BaseUnresolvedName {
6886 Name(SimpleId),
6888
6889 Operator(OperatorName, Option<TemplateArgs>),
6891
6892 Destructor(DestructorName),
6894}
6895
6896impl Parse for BaseUnresolvedName {
6897 fn parse<'a, 'b>(
6898 ctx: &'a ParseContext,
6899 subs: &'a mut SubstitutionTable,
6900 input: IndexStr<'b>,
6901 ) -> Result<(BaseUnresolvedName, IndexStr<'b>)> {
6902 try_begin_parse!("BaseUnresolvedName", ctx, input);
6903
6904 if let Ok((name, tail)) = try_recurse!(SimpleId::parse(ctx, subs, input)) {
6905 return Ok((BaseUnresolvedName::Name(name), tail));
6906 }
6907
6908 if let Ok(tail) = consume(b"on", input) {
6909 let (opname, tail) = OperatorName::parse(ctx, subs, tail)?;
6910 let (args, tail) =
6911 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6912 (Some(args), tail)
6913 } else {
6914 (None, tail)
6915 };
6916 return Ok((BaseUnresolvedName::Operator(opname, args), tail));
6917 }
6918
6919 let tail = consume(b"dn", input)?;
6920 let (name, tail) = DestructorName::parse(ctx, subs, tail)?;
6921 Ok((BaseUnresolvedName::Destructor(name), tail))
6922 }
6923}
6924
6925impl<'subs, W> Demangle<'subs, W> for BaseUnresolvedName
6926where
6927 W: 'subs + DemangleWrite,
6928{
6929 fn demangle<'prev, 'ctx>(
6930 &'subs self,
6931 ctx: &'ctx mut DemangleContext<'subs, W>,
6932 scope: Option<ArgScopeStack<'prev, 'subs>>,
6933 ) -> fmt::Result {
6934 let ctx = try_begin_demangle!(self, ctx, scope);
6935
6936 match *self {
6937 BaseUnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6938 BaseUnresolvedName::Destructor(ref dtor) => dtor.demangle(ctx, scope),
6939 BaseUnresolvedName::Operator(ref op, ref args) => {
6940 op.demangle(ctx, scope)?;
6941 if let Some(ref args) = *args {
6942 args.demangle(ctx, scope)?;
6943 }
6944 Ok(())
6945 }
6946 }
6947 }
6948}
6949
6950#[derive(Clone, Debug, PartialEq, Eq)]
6957pub enum DestructorName {
6958 Unresolved(UnresolvedTypeHandle),
6960
6961 Name(SimpleId),
6963}
6964
6965impl Parse for DestructorName {
6966 fn parse<'a, 'b>(
6967 ctx: &'a ParseContext,
6968 subs: &'a mut SubstitutionTable,
6969 input: IndexStr<'b>,
6970 ) -> Result<(DestructorName, IndexStr<'b>)> {
6971 try_begin_parse!("DestructorName", ctx, input);
6972
6973 if let Ok((ty, tail)) = try_recurse!(UnresolvedTypeHandle::parse(ctx, subs, input)) {
6974 return Ok((DestructorName::Unresolved(ty), tail));
6975 }
6976
6977 let (name, tail) = SimpleId::parse(ctx, subs, input)?;
6978 Ok((DestructorName::Name(name), tail))
6979 }
6980}
6981
6982impl<'subs, W> Demangle<'subs, W> for DestructorName
6983where
6984 W: 'subs + DemangleWrite,
6985{
6986 fn demangle<'prev, 'ctx>(
6987 &'subs self,
6988 ctx: &'ctx mut DemangleContext<'subs, W>,
6989 scope: Option<ArgScopeStack<'prev, 'subs>>,
6990 ) -> fmt::Result {
6991 let ctx = try_begin_demangle!(self, ctx, scope);
6992
6993 write!(ctx, "~")?;
6994 match *self {
6995 DestructorName::Unresolved(ref ty) => ty.demangle(ctx, scope),
6996 DestructorName::Name(ref name) => name.demangle(ctx, scope),
6997 }
6998 }
6999}
7000
7001#[derive(Clone, Debug, PartialEq, Eq)]
7013pub enum ExprPrimary {
7014 Literal(TypeHandle, usize, usize),
7016
7017 External(MangledName),
7019}
7020
7021impl Parse for ExprPrimary {
7022 fn parse<'a, 'b>(
7023 ctx: &'a ParseContext,
7024 subs: &'a mut SubstitutionTable,
7025 input: IndexStr<'b>,
7026 ) -> Result<(ExprPrimary, IndexStr<'b>)> {
7027 try_begin_parse!("ExprPrimary", ctx, input);
7028
7029 let tail = consume(b"L", input)?;
7030
7031 if let Ok((ty, tail)) = try_recurse!(TypeHandle::parse(ctx, subs, tail)) {
7032 let start = tail.index();
7033 let num_bytes_in_literal = tail.as_ref().iter().take_while(|&&c| c != b'E').count();
7034 let tail = tail.range_from(num_bytes_in_literal..);
7035 let end = tail.index();
7036 let tail = consume(b"E", tail)?;
7037 let expr = ExprPrimary::Literal(ty, start, end);
7038 return Ok((expr, tail));
7039 }
7040
7041 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
7042 let tail = consume(b"E", tail)?;
7043 let expr = ExprPrimary::External(name);
7044 Ok((expr, tail))
7045 }
7046}
7047
7048impl<'subs, W> Demangle<'subs, W> for ExprPrimary
7049where
7050 W: 'subs + DemangleWrite,
7051{
7052 fn demangle<'prev, 'ctx>(
7053 &'subs self,
7054 ctx: &'ctx mut DemangleContext<'subs, W>,
7055 scope: Option<ArgScopeStack<'prev, 'subs>>,
7056 ) -> fmt::Result {
7057 let ctx = try_begin_demangle!(self, ctx, scope);
7058
7059 fn write_literal<W>(ctx: &mut DemangleContext<W>, start: usize, end: usize) -> fmt::Result
7060 where
7061 W: DemangleWrite,
7062 {
7063 debug_assert!(start <= end);
7064 let start = if start < end && ctx.input[start] == b'n' {
7065 write!(ctx, "-")?;
7066 start + 1
7067 } else {
7068 start
7069 };
7070 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
7071 log!("Error writing literal: {}", e);
7072 fmt::Error
7073 })?;
7074 ctx.write_str(s)
7075 }
7076
7077 match *self {
7078 ExprPrimary::External(ref name) => {
7079 let saved_show_params = ctx.show_params;
7080 ctx.show_params = true;
7081 let ret = name.demangle(ctx, scope);
7082 ctx.show_params = saved_show_params;
7083 ret
7084 }
7085 ExprPrimary::Literal(
7086 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool)),
7087 start,
7088 end,
7089 ) => match &ctx.input[start..end] {
7090 b"0" => write!(ctx, "false"),
7091 b"1" => write!(ctx, "true"),
7092 _ => {
7093 write!(ctx, "(bool)")?;
7094 write_literal(ctx, start, end)
7095 }
7096 },
7097 ExprPrimary::Literal(
7098 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Nullptr)),
7099 _,
7100 _,
7101 ) => write!(ctx, "nullptr"),
7102 ExprPrimary::Literal(
7103 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Double)),
7104 start,
7105 end,
7106 )
7107 | ExprPrimary::Literal(
7108 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Float)),
7109 start,
7110 end,
7111 ) => {
7112 if ctx.show_expression_literal_types {
7113 write!(ctx, "(")?;
7114 ty.demangle(ctx, scope)?;
7115 write!(ctx, ")")?;
7116 }
7117 let start = if start < end && ctx.input[start] == b'n' {
7118 write!(ctx, "-[")?;
7119 start + 1
7120 } else {
7121 write!(ctx, "[")?;
7122 start
7123 };
7124 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
7125 log!("Error writing literal: {}", e);
7126 fmt::Error
7127 })?;
7128 ctx.write_str(s)?;
7129 write!(ctx, "]")
7130 }
7131 ExprPrimary::Literal(
7132 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int)),
7133 start,
7134 end,
7135 ) => write_literal(ctx, start, end),
7136 ExprPrimary::Literal(ref ty, start, end) => {
7137 if ctx.show_expression_literal_types {
7138 write!(ctx, "(")?;
7139 ty.demangle(ctx, scope)?;
7140 write!(ctx, ")")?;
7141 }
7142 write_literal(ctx, start, end)
7143 }
7144 }
7145 }
7146}
7147
7148#[derive(Clone, Debug, PartialEq, Eq)]
7154pub struct Initializer(Vec<Expression>);
7155
7156impl Parse for Initializer {
7157 fn parse<'a, 'b>(
7158 ctx: &'a ParseContext,
7159 subs: &'a mut SubstitutionTable,
7160 input: IndexStr<'b>,
7161 ) -> Result<(Initializer, IndexStr<'b>)> {
7162 try_begin_parse!("Initializer", ctx, input);
7163
7164 let tail = consume(b"pi", input)?;
7165 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
7166 let tail = consume(b"E", tail)?;
7167 Ok((Initializer(exprs), tail))
7168 }
7169}
7170
7171impl<'subs, W> Demangle<'subs, W> for Initializer
7172where
7173 W: 'subs + DemangleWrite,
7174{
7175 fn demangle<'prev, 'ctx>(
7176 &'subs self,
7177 ctx: &'ctx mut DemangleContext<'subs, W>,
7178 scope: Option<ArgScopeStack<'prev, 'subs>>,
7179 ) -> fmt::Result {
7180 let ctx = try_begin_demangle!(self, ctx, scope);
7181
7182 write!(ctx, "(")?;
7183 let mut need_comma = false;
7184 for expr in &self.0 {
7185 if need_comma {
7186 write!(ctx, ", ")?;
7187 }
7188 expr.demangle(ctx, scope)?;
7189 need_comma = true;
7190 }
7191 write!(ctx, ")")?;
7192 Ok(())
7193 }
7194}
7195
7196#[derive(Clone, Debug, PartialEq, Eq)]
7204pub enum LocalName {
7205 Relative(Box<Encoding>, Option<Box<Name>>, Option<Discriminator>),
7208
7209 Default(Box<Encoding>, Option<usize>, Box<Name>),
7211}
7212
7213impl Parse for LocalName {
7214 fn parse<'a, 'b>(
7215 ctx: &'a ParseContext,
7216 subs: &'a mut SubstitutionTable,
7217 input: IndexStr<'b>,
7218 ) -> Result<(LocalName, IndexStr<'b>)> {
7219 try_begin_parse!("LocalName", ctx, input);
7220
7221 let tail = consume(b"Z", input)?;
7222 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
7223 let tail = consume(b"E", tail)?;
7224
7225 if let Ok(tail) = consume(b"s", tail) {
7226 let (disc, tail) =
7227 if let Ok((disc, tail)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
7228 (Some(disc), tail)
7229 } else {
7230 (None, tail)
7231 };
7232 return Ok((LocalName::Relative(Box::new(encoding), None, disc), tail));
7233 }
7234
7235 if let Ok(tail) = consume(b"d", tail) {
7236 let (param, tail) =
7237 if let Ok((num, tail)) = try_recurse!(Number::parse(ctx, subs, tail)) {
7238 (Some(num as _), tail)
7239 } else {
7240 (None, tail)
7241 };
7242 let tail = consume(b"_", tail)?;
7243 let (name, tail) = Name::parse(ctx, subs, tail)?;
7244 return Ok((
7245 LocalName::Default(Box::new(encoding), param, Box::new(name)),
7246 tail,
7247 ));
7248 }
7249
7250 let (name, tail) = Name::parse(ctx, subs, tail)?;
7251 let (disc, tail) =
7252 if let Ok((disc, tail)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
7253 (Some(disc), tail)
7254 } else {
7255 (None, tail)
7256 };
7257
7258 Ok((
7259 LocalName::Relative(Box::new(encoding), Some(Box::new(name)), disc),
7260 tail,
7261 ))
7262 }
7263}
7264
7265impl<'subs, W> Demangle<'subs, W> for LocalName
7266where
7267 W: 'subs + DemangleWrite,
7268{
7269 fn demangle<'prev, 'ctx>(
7270 &'subs self,
7271 ctx: &'ctx mut DemangleContext<'subs, W>,
7272 scope: Option<ArgScopeStack<'prev, 'subs>>,
7273 ) -> fmt::Result {
7274 let ctx = try_begin_demangle!(self, ctx, scope);
7275
7276 let saved_show_params = ctx.show_params;
7277 ctx.show_params = true;
7278 let ret = match *self {
7279 LocalName::Relative(ref encoding, Some(ref name), _) => {
7280 encoding.demangle(ctx, scope)?;
7281 write!(ctx, "::")?;
7282 name.demangle(ctx, scope)
7283 }
7284 LocalName::Relative(ref encoding, None, _) => {
7285 encoding.demangle(ctx, scope)?;
7287 write!(ctx, "::string literal")?;
7288 Ok(())
7289 }
7290 LocalName::Default(ref encoding, _, _) => encoding.demangle(ctx, scope),
7291 };
7292 ctx.show_params = saved_show_params;
7293 ret
7294 }
7295}
7296
7297impl GetTemplateArgs for LocalName {
7298 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
7299 match *self {
7300 LocalName::Relative(_, None, _) => None,
7301 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
7302 name.get_template_args(subs)
7303 }
7304 }
7305 }
7306}
7307
7308impl<'a> GetLeafName<'a> for LocalName {
7309 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7310 match *self {
7311 LocalName::Relative(_, None, _) => None,
7312 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
7313 name.get_leaf_name(subs)
7314 }
7315 }
7316 }
7317}
7318
7319#[derive(Clone, Debug, PartialEq, Eq)]
7326pub struct Discriminator(usize);
7327
7328impl Parse for Discriminator {
7329 fn parse<'a, 'b>(
7330 ctx: &'a ParseContext,
7331 _subs: &'a mut SubstitutionTable,
7332 input: IndexStr<'b>,
7333 ) -> Result<(Discriminator, IndexStr<'b>)> {
7334 try_begin_parse!("Discriminator", ctx, input);
7335
7336 let tail = consume(b"_", input)?;
7337
7338 if let Ok(tail) = consume(b"_", tail) {
7339 let (num, tail) = parse_number(10, false, tail)?;
7340 debug_assert!(num >= 0);
7341 if num < 10 {
7342 return Err(error::Error::UnexpectedText);
7343 }
7344 let tail = consume(b"_", tail)?;
7345 return Ok((Discriminator(num as _), tail));
7346 }
7347
7348 match tail.try_split_at(1) {
7349 None => Err(error::Error::UnexpectedEnd),
7350 Some((head, tail)) => match head.as_ref()[0] {
7351 b'0' => Ok((Discriminator(0), tail)),
7352 b'1' => Ok((Discriminator(1), tail)),
7353 b'2' => Ok((Discriminator(2), tail)),
7354 b'3' => Ok((Discriminator(3), tail)),
7355 b'4' => Ok((Discriminator(4), tail)),
7356 b'5' => Ok((Discriminator(5), tail)),
7357 b'6' => Ok((Discriminator(6), tail)),
7358 b'7' => Ok((Discriminator(7), tail)),
7359 b'8' => Ok((Discriminator(8), tail)),
7360 b'9' => Ok((Discriminator(9), tail)),
7361 _ => Err(error::Error::UnexpectedText),
7362 },
7363 }
7364 }
7365}
7366
7367#[derive(Clone, Debug, PartialEq, Eq)]
7373pub struct ClosureTypeName(LambdaSig, Option<usize>);
7374
7375impl Parse for ClosureTypeName {
7376 fn parse<'a, 'b>(
7377 ctx: &'a ParseContext,
7378 subs: &'a mut SubstitutionTable,
7379 input: IndexStr<'b>,
7380 ) -> Result<(ClosureTypeName, IndexStr<'b>)> {
7381 try_begin_parse!("ClosureTypeName", ctx, input);
7382
7383 let tail = consume(b"Ul", input)?;
7384 let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
7385 let tail = consume(b"E", tail)?;
7386 let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
7387 (Some(num as _), tail)
7388 } else {
7389 (None, tail)
7390 };
7391 let tail = consume(b"_", tail)?;
7392 Ok((ClosureTypeName(sig, num), tail))
7393 }
7394}
7395
7396impl<'subs, W> Demangle<'subs, W> for ClosureTypeName
7397where
7398 W: 'subs + DemangleWrite,
7399{
7400 fn demangle<'prev, 'ctx>(
7401 &'subs self,
7402 ctx: &'ctx mut DemangleContext<'subs, W>,
7403 scope: Option<ArgScopeStack<'prev, 'subs>>,
7404 ) -> fmt::Result {
7405 let ctx = try_begin_demangle!(self, ctx, scope);
7406
7407 write!(ctx, "{{lambda(")?;
7408 self.0.demangle(ctx, scope)?;
7409 write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
7410 Ok(())
7411 }
7412}
7413
7414impl<'subs> ArgScope<'subs, 'subs> for ClosureTypeName {
7415 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
7416 Ok(LeafName::Closure(self))
7417 }
7418
7419 fn get_template_arg(
7420 &'subs self,
7421 _: usize,
7422 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
7423 Err(error::Error::BadTemplateArgReference)
7424 }
7425
7426 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
7427 Err(error::Error::BadFunctionArgReference)
7428 }
7429}
7430
7431impl<'a> GetLeafName<'a> for ClosureTypeName {
7432 #[inline]
7433 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7434 Some(LeafName::Closure(self))
7435 }
7436}
7437
7438impl ClosureTypeName {
7439 #[inline]
7440 fn starts_with(byte: u8, input: &IndexStr) -> bool {
7441 byte == b'U' && input.peek_second().map(|b| b == b'l').unwrap_or(false)
7442 }
7443}
7444
7445#[derive(Clone, Debug, PartialEq, Eq)]
7451pub struct LambdaSig(Vec<TypeHandle>);
7452
7453impl LambdaSig {
7454 fn demangle_args<'subs, 'prev, 'ctx, W>(
7455 &'subs self,
7456 ctx: &'ctx mut DemangleContext<'subs, W>,
7457 scope: Option<ArgScopeStack<'prev, 'subs>>,
7458 ) -> fmt::Result
7459 where
7460 W: 'subs + DemangleWrite,
7461 {
7462 let mut need_comma = false;
7463 for ty in &self.0 {
7464 if need_comma {
7465 write!(ctx, ", ")?;
7466 }
7467 ty.demangle(ctx, scope)?;
7468 need_comma = true;
7469 }
7470 Ok(())
7471 }
7472}
7473
7474impl Parse for LambdaSig {
7475 fn parse<'a, 'b>(
7476 ctx: &'a ParseContext,
7477 subs: &'a mut SubstitutionTable,
7478 input: IndexStr<'b>,
7479 ) -> Result<(LambdaSig, IndexStr<'b>)> {
7480 try_begin_parse!("LambdaSig", ctx, input);
7481
7482 let (types, tail) = if let Ok(tail) = consume(b"v", input) {
7483 (vec![], tail)
7484 } else {
7485 one_or_more::<TypeHandle>(ctx, subs, input)?
7486 };
7487 Ok((LambdaSig(types), tail))
7488 }
7489}
7490
7491impl<'subs, W> Demangle<'subs, W> for LambdaSig
7492where
7493 W: 'subs + DemangleWrite,
7494{
7495 fn demangle<'prev, 'ctx>(
7496 &'subs self,
7497 ctx: &'ctx mut DemangleContext<'subs, W>,
7498 scope: Option<ArgScopeStack<'prev, 'subs>>,
7499 ) -> fmt::Result {
7500 let ctx = try_begin_demangle!(self, ctx, scope);
7501
7502 ctx.is_lambda_arg = true;
7503 let r = self.demangle_args(ctx, scope);
7504 ctx.is_lambda_arg = false;
7505 r
7506 }
7507}
7508
7509#[derive(Clone, Debug, PartialEq, Eq)]
7515pub struct DataMemberPrefix(SourceName);
7516
7517impl Parse for DataMemberPrefix {
7518 fn parse<'a, 'b>(
7519 ctx: &'a ParseContext,
7520 subs: &'a mut SubstitutionTable,
7521 input: IndexStr<'b>,
7522 ) -> Result<(DataMemberPrefix, IndexStr<'b>)> {
7523 try_begin_parse!("DataMemberPrefix", ctx, input);
7524
7525 let (name, tail) = SourceName::parse(ctx, subs, input)?;
7526 let tail = consume(b"M", tail)?;
7527 Ok((DataMemberPrefix(name), tail))
7528 }
7529}
7530
7531impl<'a> GetLeafName<'a> for DataMemberPrefix {
7532 #[inline]
7533 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7534 Some(LeafName::SourceName(&self.0))
7535 }
7536}
7537
7538impl<'subs, W> Demangle<'subs, W> for DataMemberPrefix
7539where
7540 W: 'subs + DemangleWrite,
7541{
7542 #[inline]
7543 fn demangle<'prev, 'ctx>(
7544 &'subs self,
7545 ctx: &'ctx mut DemangleContext<'subs, W>,
7546 scope: Option<ArgScopeStack<'prev, 'subs>>,
7547 ) -> fmt::Result {
7548 let ctx = try_begin_demangle!(self, ctx, scope);
7549
7550 ctx.push_demangle_node(DemangleNodeType::DataMemberPrefix);
7551 let ret = self.0.demangle(ctx, scope);
7552 ctx.pop_demangle_node();
7553 ret
7554 }
7555}
7556
7557#[derive(Clone, Debug, PartialEq, Eq)]
7574pub enum Substitution {
7575 BackReference(usize),
7578
7579 WellKnown(WellKnownComponent),
7583}
7584
7585impl Parse for Substitution {
7586 fn parse<'a, 'b>(
7587 ctx: &'a ParseContext,
7588 subs: &'a mut SubstitutionTable,
7589 input: IndexStr<'b>,
7590 ) -> Result<(Substitution, IndexStr<'b>)> {
7591 try_begin_parse!("Substitution", ctx, input);
7592
7593 if let Ok((well_known, tail)) = try_recurse!(WellKnownComponent::parse(ctx, subs, input)) {
7594 return Ok((Substitution::WellKnown(well_known), tail));
7595 }
7596
7597 let tail = consume(b"S", input)?;
7598 let (idx, tail) = if let Ok((idx, tail)) = try_recurse!(SeqId::parse(ctx, subs, tail)) {
7599 (idx.0 + 1, tail)
7600 } else {
7601 (0, tail)
7602 };
7603
7604 if !subs.contains(idx) {
7605 return Err(error::Error::BadBackReference);
7606 }
7607
7608 let tail = consume(b"_", tail)?;
7609 log!("Found a reference to @ {}", idx);
7610 Ok((Substitution::BackReference(idx), tail))
7611 }
7612}
7613
7614define_vocabulary! {
7615#[derive(Clone, Debug, PartialEq, Eq)]
7619 pub enum WellKnownComponent {
7620 Std (b"St", "std"),
7621 StdAllocator (b"Sa", "std::allocator"),
7622 StdString1 (b"Sb", "std::basic_string"),
7623 StdString2 (b"Ss", "std::string"),
7624 StdIstream (b"Si", "std::basic_istream<char, std::char_traits<char> >"),
7625 StdOstream (b"So", "std::ostream"),
7626 StdIostream (b"Sd", "std::basic_iostream<char, std::char_traits<char> >")
7627 }
7628}
7629
7630impl<'a> GetLeafName<'a> for WellKnownComponent {
7631 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7632 match *self {
7633 WellKnownComponent::Std => None,
7634 _ => Some(LeafName::WellKnownComponent(self)),
7635 }
7636 }
7637}
7638
7639impl<'a> ArgScope<'a, 'a> for WellKnownComponent {
7640 fn leaf_name(&'a self) -> Result<LeafName<'a>> {
7641 Ok(LeafName::WellKnownComponent(self))
7642 }
7643
7644 fn get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)> {
7645 Err(error::Error::BadTemplateArgReference)
7646 }
7647
7648 fn get_function_arg(&'a self, _: usize) -> Result<&'a Type> {
7649 Err(error::Error::BadFunctionArgReference)
7650 }
7651}
7652
7653impl<'subs, W> DemangleAsLeaf<'subs, W> for WellKnownComponent
7654where
7655 W: 'subs + DemangleWrite,
7656{
7657 fn demangle_as_leaf<'me, 'ctx>(
7658 &'me self,
7659 ctx: &'ctx mut DemangleContext<'subs, W>,
7660 ) -> fmt::Result {
7661 match *self {
7662 WellKnownComponent::Std => {
7663 panic!("should never treat `WellKnownComponent::Std` as a leaf name")
7664 }
7665 WellKnownComponent::StdAllocator => write!(ctx, "allocator"),
7666 WellKnownComponent::StdString1 => write!(ctx, "basic_string"),
7667 WellKnownComponent::StdString2 => write!(ctx, "string"),
7668 WellKnownComponent::StdIstream => write!(ctx, "basic_istream"),
7669 WellKnownComponent::StdOstream => write!(ctx, "ostream"),
7670 WellKnownComponent::StdIostream => write!(ctx, "basic_iostream"),
7671 }
7672 }
7673}
7674
7675#[derive(Clone, Debug, PartialEq, Eq)]
7728pub enum SpecialName {
7729 VirtualTable(TypeHandle),
7731
7732 Vtt(TypeHandle),
7734
7735 Typeinfo(TypeHandle),
7737
7738 TypeinfoName(TypeHandle),
7740
7741 VirtualOverrideThunk(CallOffset, Box<Encoding>),
7743
7744 VirtualOverrideThunkCovariant(CallOffset, CallOffset, Box<Encoding>),
7746
7747 Guard(Name),
7749
7750 GuardTemporary(Name, usize),
7753
7754 ConstructionVtable(TypeHandle, usize, TypeHandle),
7756
7757 TypeinfoFunction(TypeHandle),
7759
7760 TlsInit(Name),
7762
7763 TlsWrapper(Name),
7765
7766 JavaResource(Vec<ResourceName>),
7768
7769 TransactionClone(Box<Encoding>),
7771
7772 NonTransactionClone(Box<Encoding>),
7774}
7775
7776impl Parse for SpecialName {
7777 fn parse<'a, 'b>(
7778 ctx: &'a ParseContext,
7779 subs: &'a mut SubstitutionTable,
7780 input: IndexStr<'b>,
7781 ) -> Result<(SpecialName, IndexStr<'b>)> {
7782 try_begin_parse!("SpecialName", ctx, input);
7783
7784 let (head, tail) = match input.try_split_at(2) {
7785 None => return Err(error::Error::UnexpectedEnd),
7786 Some((head, tail)) => (head, tail),
7787 };
7788
7789 match head.as_ref() {
7790 b"TV" => {
7791 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7792 Ok((SpecialName::VirtualTable(ty), tail))
7793 }
7794 b"TT" => {
7795 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7796 Ok((SpecialName::Vtt(ty), tail))
7797 }
7798 b"TI" => {
7799 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7800 Ok((SpecialName::Typeinfo(ty), tail))
7801 }
7802 b"TS" => {
7803 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7804 Ok((SpecialName::TypeinfoName(ty), tail))
7805 }
7806 b"Tc" => {
7807 let (first, tail) = CallOffset::parse(ctx, subs, tail)?;
7808 let (second, tail) = CallOffset::parse(ctx, subs, tail)?;
7809 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7810 Ok((
7811 SpecialName::VirtualOverrideThunkCovariant(first, second, Box::new(base)),
7812 tail,
7813 ))
7814 }
7815 b"Th" | b"Tv" => {
7816 let tail = consume(b"T", input).unwrap();
7819 let (offset, tail) = CallOffset::parse(ctx, subs, tail)?;
7820 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7821 Ok((
7822 SpecialName::VirtualOverrideThunk(offset, Box::new(base)),
7823 tail,
7824 ))
7825 }
7826 b"TC" => {
7827 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
7828 let (n, tail) = parse_number(10, false, tail)?;
7829 let tail = consume(b"_", tail)?;
7830 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
7831 Ok((SpecialName::ConstructionVtable(ty1, n as usize, ty2), tail))
7832 }
7833 b"TF" => {
7834 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7835 Ok((SpecialName::TypeinfoFunction(ty), tail))
7836 }
7837 b"TH" => {
7838 let (name, tail) = Name::parse(ctx, subs, tail)?;
7839 Ok((SpecialName::TlsInit(name), tail))
7840 }
7841 b"TW" => {
7842 let (name, tail) = Name::parse(ctx, subs, tail)?;
7843 Ok((SpecialName::TlsWrapper(name), tail))
7844 }
7845 b"GV" => {
7846 let (name, tail) = Name::parse(ctx, subs, tail)?;
7847 Ok((SpecialName::Guard(name), tail))
7848 }
7849 b"GR" => {
7850 let (name, tail) = Name::parse(ctx, subs, tail)?;
7851 let (idx, tail) = if let Ok(tail) = consume(b"_", tail) {
7852 (0, tail)
7853 } else {
7854 let (idx, tail) = SeqId::parse(ctx, subs, tail)?;
7855 let tail = consume(b"_", tail)?;
7856 (idx.0 + 1, tail)
7857 };
7858 Ok((SpecialName::GuardTemporary(name, idx), tail))
7859 }
7860 b"Gr" => {
7861 let (resource_name_len, tail) = parse_number(10, false, tail)?;
7862 if resource_name_len == 0 {
7863 return Err(error::Error::UnexpectedText);
7864 }
7865
7866 let (head, tail) = match tail.try_split_at(resource_name_len as _) {
7867 Some((head, tail)) => (head, tail),
7868 None => return Err(error::Error::UnexpectedEnd),
7869 };
7870
7871 let head = consume(b"_", head)?;
7872
7873 let (resource_names, empty) = zero_or_more::<ResourceName>(ctx, subs, head)?;
7874 if !empty.is_empty() {
7875 return Err(error::Error::UnexpectedText);
7876 }
7877
7878 Ok((SpecialName::JavaResource(resource_names), tail))
7879 }
7880 b"GT" => {
7881 match tail.next_or(error::Error::UnexpectedEnd)? {
7882 (b'n', tail) => {
7883 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7884 Ok((SpecialName::NonTransactionClone(Box::new(base)), tail))
7885 }
7886 (b't', tail) | (_, tail) => {
7889 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7890 Ok((SpecialName::TransactionClone(Box::new(base)), tail))
7891 }
7892 }
7893 }
7894 _ => Err(error::Error::UnexpectedText),
7895 }
7896 }
7897}
7898
7899impl<'subs, W> Demangle<'subs, W> for SpecialName
7900where
7901 W: 'subs + DemangleWrite,
7902{
7903 fn demangle<'prev, 'ctx>(
7904 &'subs self,
7905 ctx: &'ctx mut DemangleContext<'subs, W>,
7906 scope: Option<ArgScopeStack<'prev, 'subs>>,
7907 ) -> fmt::Result {
7908 let ctx = try_begin_demangle!(self, ctx, scope);
7909
7910 match *self {
7911 SpecialName::VirtualTable(ref ty) => {
7912 write!(ctx, "{{vtable(")?;
7913 ctx.push_demangle_node(DemangleNodeType::VirtualTable);
7914 ty.demangle(ctx, scope)?;
7915 ctx.pop_demangle_node();
7916 write!(ctx, ")}}")?;
7917 Ok(())
7918 }
7919 SpecialName::Vtt(ref ty) => {
7920 write!(ctx, "{{vtt(")?;
7921 ty.demangle(ctx, scope)?;
7922 write!(ctx, ")}}")?;
7923 Ok(())
7924 }
7925 SpecialName::Typeinfo(ref ty) => {
7926 write!(ctx, "typeinfo for ")?;
7927 ty.demangle(ctx, scope)
7928 }
7929 SpecialName::TypeinfoName(ref ty) => {
7930 write!(ctx, "typeinfo name for ")?;
7931 ty.demangle(ctx, scope)
7932 }
7933 SpecialName::VirtualOverrideThunk(ref offset, ref encoding) => {
7934 write!(ctx, "{{virtual override thunk(")?;
7935 offset.demangle(ctx, scope)?;
7936 write!(ctx, ", ")?;
7937 encoding.demangle(ctx, scope)?;
7938 write!(ctx, ")}}")?;
7939 Ok(())
7940 }
7941 SpecialName::VirtualOverrideThunkCovariant(
7942 ref this_offset,
7943 ref result_offset,
7944 ref encoding,
7945 ) => {
7946 write!(ctx, "{{virtual override thunk(")?;
7947 this_offset.demangle(ctx, scope)?;
7948 write!(ctx, ", ")?;
7949 result_offset.demangle(ctx, scope)?;
7950 write!(ctx, ", ")?;
7951 encoding.demangle(ctx, scope)?;
7952 write!(ctx, ")}}")?;
7953 Ok(())
7954 }
7955 SpecialName::Guard(ref name) => {
7956 write!(ctx, "guard variable for ")?;
7957 name.demangle(ctx, scope)
7958 }
7959 SpecialName::GuardTemporary(ref name, n) => {
7960 write!(ctx, "reference temporary #{} for ", n)?;
7961 name.demangle(ctx, scope)
7962 }
7963 SpecialName::ConstructionVtable(ref ty1, _, ref ty2) => {
7964 write!(ctx, "construction vtable for ")?;
7965 ty1.demangle(ctx, scope)?;
7966 write!(ctx, "-in-")?;
7967 ty2.demangle(ctx, scope)
7968 }
7969 SpecialName::TypeinfoFunction(ref ty) => {
7970 write!(ctx, "typeinfo fn for ")?;
7971 ty.demangle(ctx, scope)
7972 }
7973 SpecialName::TlsInit(ref name) => {
7974 write!(ctx, "TLS init function for ")?;
7975 name.demangle(ctx, scope)
7976 }
7977 SpecialName::TlsWrapper(ref name) => {
7978 write!(ctx, "TLS wrapper function for ")?;
7979 name.demangle(ctx, scope)
7980 }
7981 SpecialName::TransactionClone(ref encoding) => {
7982 write!(ctx, "transaction clone for ")?;
7983 encoding.demangle(ctx, scope)
7984 }
7985 SpecialName::NonTransactionClone(ref encoding) => {
7986 write!(ctx, "non-transaction clone for ")?;
7987 encoding.demangle(ctx, scope)
7988 }
7989 SpecialName::JavaResource(ref names) => {
7990 write!(ctx, "java resource ")?;
7991 for name in names {
7992 name.demangle(ctx, scope)?;
7993 }
7994 Ok(())
7995 }
7996 }
7997 }
7998}
7999
8000#[derive(Clone, Debug, PartialEq, Eq)]
8002pub struct ResourceName {
8003 start: usize,
8004 end: usize,
8005}
8006
8007impl Parse for ResourceName {
8008 fn parse<'a, 'b>(
8009 ctx: &'a ParseContext,
8010 _subs: &'a mut SubstitutionTable,
8011 input: IndexStr<'b>,
8012 ) -> Result<(ResourceName, IndexStr<'b>)> {
8013 try_begin_parse!("ResourceName", ctx, input);
8014
8015 if input.is_empty() {
8016 return Err(error::Error::UnexpectedEnd);
8017 }
8018
8019 let mut end = input
8020 .as_ref()
8021 .iter()
8022 .map(|&c| c as char)
8023 .take_while(|&c| c != '$' || c.is_digit(36))
8024 .count();
8025
8026 if end == 0 {
8027 return Err(error::Error::UnexpectedText);
8028 }
8029
8030 if input.range_from(end..).peek() == Some(b'$') {
8031 match input.range_from(end..).peek_second() {
8032 Some(b'S') | Some(b'_') | Some(b'$') => end += 2,
8033 _ => return Err(error::Error::UnexpectedText),
8034 }
8035 }
8036
8037 let tail = input.range_from(end..);
8038
8039 let resource_name = ResourceName {
8040 start: input.index(),
8041 end: tail.index(),
8042 };
8043
8044 Ok((resource_name, tail))
8045 }
8046}
8047
8048impl<'subs, W> Demangle<'subs, W> for ResourceName
8049where
8050 W: 'subs + DemangleWrite,
8051{
8052 #[inline]
8053 fn demangle<'prev, 'ctx>(
8054 &'subs self,
8055 ctx: &'ctx mut DemangleContext<'subs, W>,
8056 scope: Option<ArgScopeStack<'prev, 'subs>>,
8057 ) -> fmt::Result {
8058 let ctx = try_begin_demangle!(self, ctx, scope);
8059
8060 let mut i = self.start;
8061 while i < self.end {
8062 let ch = ctx.input[i];
8063 if ch == b'$' {
8064 i += 1;
8066 match ctx.input[i] {
8067 b'S' => write!(ctx, "{}", '/')?,
8068 b'_' => write!(ctx, "{}", '.')?,
8069 b'$' => write!(ctx, "{}", '$')?,
8070 _ => {
8071 }
8073 }
8074 } else {
8075 write!(ctx, "{}", ch as char)?;
8076 }
8077 i += 1;
8078 }
8079
8080 Ok(())
8081 }
8082}
8083
8084#[derive(Clone, Debug, PartialEq, Eq)]
8092pub struct SubobjectExpr {
8093 ty: TypeHandle,
8094 expr: Box<Expression>,
8095 offset: isize,
8096}
8097
8098impl Parse for SubobjectExpr {
8099 fn parse<'a, 'b>(
8100 ctx: &'a ParseContext,
8101 subs: &'a mut SubstitutionTable,
8102 input: IndexStr<'b>,
8103 ) -> Result<(SubobjectExpr, IndexStr<'b>)> {
8104 try_begin_parse!("SubobjectExpr", ctx, input);
8105
8106 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
8107 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
8108 let (offset, tail) = parse_number(10, true, tail).unwrap_or((0, tail));
8109
8110 let tail = consume(b"E", tail)?;
8112 Ok((
8113 SubobjectExpr {
8114 ty: ty,
8115 expr: Box::new(expr),
8116 offset: offset,
8117 },
8118 tail,
8119 ))
8120 }
8121}
8122
8123impl<'subs, W> Demangle<'subs, W> for SubobjectExpr
8124where
8125 W: 'subs + DemangleWrite,
8126{
8127 #[inline]
8128 fn demangle<'prev, 'ctx>(
8129 &'subs self,
8130 ctx: &'ctx mut DemangleContext<'subs, W>,
8131 scope: Option<ArgScopeStack<'prev, 'subs>>,
8132 ) -> fmt::Result {
8133 let ctx = try_begin_demangle!(self, ctx, scope);
8134
8135 self.expr.demangle(ctx, scope)?;
8136 write!(ctx, ".<")?;
8137 self.ty.demangle(ctx, scope)?;
8138 write!(ctx, " at offset {}>", self.offset)
8139 }
8140}
8141
8142#[inline]
8147fn consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>> {
8148 match input.try_split_at(expected.len()) {
8149 Some((head, tail)) if head == expected => Ok(tail),
8150 Some(_) => Err(error::Error::UnexpectedText),
8151 None => Err(error::Error::UnexpectedEnd),
8152 }
8153}
8154
8155fn one_or_more<'a, 'b, P>(
8156 ctx: &'a ParseContext,
8157 subs: &'a mut SubstitutionTable,
8158 input: IndexStr<'b>,
8159) -> Result<(Vec<P>, IndexStr<'b>)>
8160where
8161 P: Parse,
8162{
8163 let (first, mut tail) = P::parse(ctx, subs, input)?;
8164 let mut results = vec![first];
8165 loop {
8166 if let Ok((parsed, tail_tail)) = try_recurse!(P::parse(ctx, subs, tail)) {
8167 results.push(parsed);
8168 tail = tail_tail;
8169 } else {
8170 return Ok((results, tail));
8171 }
8172 }
8173}
8174
8175fn zero_or_more<'a, 'b, P>(
8176 ctx: &'a ParseContext,
8177 subs: &'a mut SubstitutionTable,
8178 input: IndexStr<'b>,
8179) -> Result<(Vec<P>, IndexStr<'b>)>
8180where
8181 P: Parse,
8182{
8183 let mut tail = input;
8184 let mut results = vec![];
8185 loop {
8186 if let Ok((parsed, tail_tail)) = try_recurse!(P::parse(ctx, subs, tail)) {
8187 results.push(parsed);
8188 tail = tail_tail;
8189 } else {
8190 return Ok((results, tail));
8191 }
8192 }
8193}
8194
8195#[allow(unsafe_code)]
8198fn parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)> {
8199 if input.is_empty() {
8200 return Err(error::Error::UnexpectedEnd);
8201 }
8202
8203 let num_is_negative = if allow_signed && input.as_ref()[0] == b'n' {
8204 input = input.range_from(1..);
8205
8206 if input.is_empty() {
8207 return Err(error::Error::UnexpectedEnd);
8208 }
8209
8210 true
8211 } else {
8212 false
8213 };
8214
8215 let num_numeric = input
8216 .as_ref()
8217 .iter()
8218 .map(|&c| c as char)
8219 .take_while(|c| c.is_digit(base) && (c.is_numeric() || c.is_uppercase()))
8220 .count();
8221 if num_numeric == 0 {
8222 return Err(error::Error::UnexpectedText);
8223 }
8224
8225 let (head, tail) = input.split_at(num_numeric);
8226 let head = head.as_ref();
8227
8228 if num_numeric > 1 && head[0] == b'0' {
8229 return Err(error::Error::UnexpectedText);
8232 }
8233
8234 let head = unsafe {
8235 str::from_utf8_unchecked(head)
8238 };
8239
8240 let mut number = isize::from_str_radix(head, base).map_err(|_| error::Error::Overflow)?;
8241 if num_is_negative {
8242 number = -number;
8243 }
8244
8245 Ok((number, tail))
8246}
8247
8248#[cfg(test)]
8249mod tests {
8250 use super::{
8251 AbiTag, AbiTags, ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset,
8252 ClassEnumType, ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype,
8253 DestructorName, Discriminator, Encoding, ExceptionSpec, ExprPrimary, Expression,
8254 FunctionParam, FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName,
8255 MangledName, MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName,
8256 ParametricBuiltinType, Parse, ParseContext, PointerToMemberType, Prefix, PrefixHandle,
8257 RefQualifier, ResourceName, SeqId, SimpleId, SimpleOperatorName, SourceName, SpecialName,
8258 StandardBuiltinType, SubobjectExpr, Substitution, TemplateArg, TemplateArgs, TemplateParam,
8259 TemplateTemplateParam, TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName,
8260 UnqualifiedName, UnresolvedName, UnresolvedQualifierLevel, UnresolvedType,
8261 UnresolvedTypeHandle, UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle,
8262 VOffset, VectorType, WellKnownComponent,
8263 };
8264
8265 use crate::error::Error;
8266 use crate::index_str::IndexStr;
8267 use crate::subs::{Substitutable, SubstitutionTable};
8268 use alloc::boxed::Box;
8269 use alloc::string::String;
8270 use core::fmt::Debug;
8271 use core::iter::FromIterator;
8272
8273 fn assert_parse_ok<P, S1, S2, I1, I2>(
8274 production: &'static str,
8275 subs: S1,
8276 input: I1,
8277 expected: P,
8278 expected_tail: I2,
8279 expected_new_subs: S2,
8280 ) where
8281 P: Debug + Parse + PartialEq,
8282 S1: AsRef<[Substitutable]>,
8283 S2: AsRef<[Substitutable]>,
8284 I1: AsRef<[u8]>,
8285 I2: AsRef<[u8]>,
8286 {
8287 let ctx = ParseContext::new(Default::default());
8288 let input = input.as_ref();
8289 let expected_tail = expected_tail.as_ref();
8290
8291 let expected_subs = SubstitutionTable::from_iter(
8292 subs.as_ref()
8293 .iter()
8294 .cloned()
8295 .chain(expected_new_subs.as_ref().iter().cloned()),
8296 );
8297 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
8298
8299 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
8300 Err(error) => panic!(
8301 "Parsing {:?} as {} failed: {}",
8302 String::from_utf8_lossy(input),
8303 production,
8304 error
8305 ),
8306 Ok((value, tail)) => {
8307 if value != expected {
8308 panic!(
8309 "Parsing {:?} as {} produced\n\n{:#?}\n\nbut we expected\n\n{:#?}",
8310 String::from_utf8_lossy(input),
8311 production,
8312 value,
8313 expected
8314 );
8315 }
8316 if tail != expected_tail {
8317 panic!(
8318 "Parsing {:?} as {} left a tail of {:?}, expected {:?}",
8319 String::from_utf8_lossy(input),
8320 production,
8321 tail,
8322 String::from_utf8_lossy(expected_tail)
8323 );
8324 }
8325 if subs[..] != expected_subs[..] {
8326 panic!(
8327 "Parsing {:?} as {} produced a substitutions table of\n\n\
8328 {:#?}\n\n\
8329 but we expected\n\n\
8330 {:#?}",
8331 String::from_utf8_lossy(input),
8332 production,
8333 subs,
8334 expected_subs
8335 );
8336 }
8337 }
8338 }
8339
8340 log!("=== assert_parse_ok PASSED ====================================");
8341 }
8342
8343 fn simple_assert_parse_ok<P, I1, I2>(
8344 production: &'static str,
8345 input: I1,
8346 expected: P,
8347 expected_tail: I2,
8348 ) where
8349 P: Debug + Parse + PartialEq,
8350 I1: AsRef<[u8]>,
8351 I2: AsRef<[u8]>,
8352 {
8353 assert_parse_ok::<P, _, _, _, _>(production, [], input, expected, expected_tail, []);
8354 }
8355
8356 fn assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error)
8357 where
8358 P: Debug + Parse + PartialEq,
8359 S: AsRef<[Substitutable]>,
8360 I: AsRef<[u8]>,
8361 {
8362 let input = input.as_ref();
8363 let ctx = ParseContext::new(Default::default());
8364 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
8365
8366 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
8367 Err(ref error) if *error == expected_error => {}
8368 Err(ref error) => {
8369 panic!(
8370 "Parsing {:?} as {} produced an error of kind {:?}, but we expected kind {:?}",
8371 String::from_utf8_lossy(input),
8372 production,
8373 error,
8374 expected_error
8375 );
8376 }
8377 Ok((value, tail)) => {
8378 panic!(
8379 "Parsing {:?} as {} produced value\
8380 \n\n\
8381 {:#?}\
8382 \n\n\
8383 and tail {:?}, but we expected error kind {:?}",
8384 String::from_utf8_lossy(input),
8385 production,
8386 value,
8387 tail,
8388 expected_error
8389 );
8390 }
8391 }
8392
8393 log!("=== assert_parse_err PASSED ===================================");
8394 }
8395
8396 fn simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error)
8397 where
8398 P: Debug + Parse + PartialEq,
8399 I: AsRef<[u8]>,
8400 {
8401 assert_parse_err::<P, _, _>(production, [], input, expected_error);
8402 }
8403
8404 #[test]
8405 fn recursion_limit() {
8406 let mut mangled = String::new();
8410 for _ in 0..10_000 {
8411 mangled.push('P');
8412 }
8413 mangled += "c";
8414
8415 simple_assert_parse_err::<TypeHandle, _>("TypeHandle", mangled, Error::TooMuchRecursion);
8416 }
8417
8418 macro_rules! assert_parse {
8419 ( $production:ident {
8420 $( with subs $subs:expr => {
8421 Ok => {
8422 $( $input:expr => {
8423 $expected:expr ,
8424 $expected_tail:expr ,
8425 $expected_new_subs:expr
8426 } )*
8427 }
8428 Err => {
8429 $( $error_input:expr => $error:expr , )*
8430 }
8431 } )*
8432 } ) => {
8433 $( $(
8434 assert_parse_ok::<$production, _, _, _, _>(stringify!($production),
8435 $subs,
8436 $input,
8437 $expected,
8438 $expected_tail,
8439 $expected_new_subs);
8440 )* )*
8441
8442 $( $(
8443 assert_parse_err::<$production, _, _>(stringify!($production),
8444 $subs,
8445 $error_input,
8446 $error);
8447 )* )*
8448 };
8449
8450 ( $production:ident {
8451 Ok => {
8452 $( $input:expr => {
8453 $expected:expr ,
8454 $expected_tail:expr
8455 } )*
8456 }
8457 Err => {
8458 $( $error_input:expr => $error:expr , )*
8459 }
8460 } ) => {
8461 $(
8462 simple_assert_parse_ok::<$production, _, _>(stringify!($production),
8463 $input,
8464 $expected,
8465 $expected_tail);
8466 )*
8467
8468
8469 $(
8470 simple_assert_parse_err::<$production, _>(stringify!($production),
8471 $error_input,
8472 $error);
8473 )*
8474 };
8475 }
8476
8477 #[test]
8478 fn parse_mangled_name() {
8479 assert_parse!(MangledName {
8480 Ok => {
8481 b"_Z3foo..." => {
8482 MangledName::Encoding(
8483 Encoding::Data(
8484 Name::Unscoped(
8485 UnscopedName::Unqualified(
8486 UnqualifiedName::Source(
8487 SourceName(Identifier {
8488 start: 3,
8489 end: 6,
8490 }),
8491 AbiTags::default())))), vec![]),
8492 b"..."
8493 }
8494 b"_GLOBAL__I__Z3foo..." => {
8495 MangledName::GlobalCtorDtor(
8496 GlobalCtorDtor::Ctor(
8497 Box::new(
8498 MangledName::Encoding(
8499 Encoding::Data(
8500 Name::Unscoped(
8501 UnscopedName::Unqualified(
8502 UnqualifiedName::Source(
8503 SourceName(
8504 Identifier {
8505 start: 14,
8506 end: 17,
8507 }),
8508 AbiTags::default())))), vec![])))),
8509 b"..."
8510 }
8511 }
8512 Err => {
8513 b"_Y" => Error::UnexpectedText,
8514 b"_Z" => Error::UnexpectedEnd,
8515 b"_" => Error::UnexpectedEnd,
8516 b"" => Error::UnexpectedEnd,
8517 b"_GLOBAL_" => Error::UnexpectedEnd,
8518 }
8519 });
8520 }
8521
8522 #[test]
8523 fn parse_encoding() {
8524 assert_parse!(Encoding {
8525 with subs [] => {
8526 Ok => {
8527 b"3fooi..." => {
8528 Encoding::Function(
8529 Name::Unscoped(
8530 UnscopedName::Unqualified(
8531 UnqualifiedName::Source(
8532 SourceName(Identifier {
8533 start: 1,
8534 end: 4,
8535 }),
8536 AbiTags::default()))),
8537 BareFunctionType(vec![
8538 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
8539 ])),
8540 b"...",
8541 []
8542 }
8543 b"3foo..." => {
8544 Encoding::Data(
8545 Name::Unscoped(
8546 UnscopedName::Unqualified(
8547 UnqualifiedName::Source(
8548 SourceName(Identifier {
8549 start: 1,
8550 end: 4,
8551 }),
8552 AbiTags::default())))),
8553 b"...",
8554 []
8555 }
8556 b"GV3abc..." => {
8557 Encoding::Special(
8558 SpecialName::Guard(
8559 Name::Unscoped(
8560 UnscopedName::Unqualified(
8561 UnqualifiedName::Source(
8562 SourceName(Identifier {
8563 start: 3,
8564 end: 6,
8565 }),
8566 AbiTags::default()))))),
8567 b"...",
8568 []
8569 }
8570 }
8571 Err => {
8572 b"zzz" => Error::UnexpectedText,
8573 b"" => Error::UnexpectedEnd,
8574 }
8575 }
8576 });
8577 }
8578
8579 #[test]
8580 fn parse_global_ctor_dtor() {
8581 assert_parse!(GlobalCtorDtor {
8582 Ok => {
8583 b"_I__Z3foo..." => {
8584 GlobalCtorDtor::Ctor(
8585 Box::new(
8586 MangledName::Encoding(
8587 Encoding::Data(
8588 Name::Unscoped(
8589 UnscopedName::Unqualified(
8590 UnqualifiedName::Source(
8591 SourceName(
8592 Identifier {
8593 start: 6,
8594 end: 9,
8595 }),
8596 AbiTags::default())))), vec![]))),
8597 b"..."
8598 }
8599 b".I__Z3foo..." => {
8600 GlobalCtorDtor::Ctor(
8601 Box::new(
8602 MangledName::Encoding(
8603 Encoding::Data(
8604 Name::Unscoped(
8605 UnscopedName::Unqualified(
8606 UnqualifiedName::Source(
8607 SourceName(
8608 Identifier {
8609 start: 6,
8610 end: 9,
8611 }),
8612 AbiTags::default())))), vec![]))),
8613 b"..."
8614 }
8615 b"$I__Z3foo..." => {
8616 GlobalCtorDtor::Ctor(
8617 Box::new(
8618 MangledName::Encoding(
8619 Encoding::Data(
8620 Name::Unscoped(
8621 UnscopedName::Unqualified(
8622 UnqualifiedName::Source(
8623 SourceName(
8624 Identifier {
8625 start: 6,
8626 end: 9,
8627 }),
8628 AbiTags::default())))), vec![]))),
8629 b"..."
8630 }
8631 b"_D__Z3foo..." => {
8632 GlobalCtorDtor::Dtor(
8633 Box::new(
8634 MangledName::Encoding(
8635 Encoding::Data(
8636 Name::Unscoped(
8637 UnscopedName::Unqualified(
8638 UnqualifiedName::Source(
8639 SourceName(
8640 Identifier {
8641 start: 6,
8642 end: 9,
8643 }),
8644 AbiTags::default())))), vec![]))),
8645 b"..."
8646 }
8647 b".D__Z3foo..." => {
8648 GlobalCtorDtor::Dtor(
8649 Box::new(
8650 MangledName::Encoding(
8651 Encoding::Data(
8652 Name::Unscoped(
8653 UnscopedName::Unqualified(
8654 UnqualifiedName::Source(
8655 SourceName(
8656 Identifier {
8657 start: 6,
8658 end: 9,
8659 }),
8660 AbiTags::default())))), vec![]))),
8661 b"..."
8662 }
8663 b"$D__Z3foo..." => {
8664 GlobalCtorDtor::Dtor(
8665 Box::new(
8666 MangledName::Encoding(
8667 Encoding::Data(
8668 Name::Unscoped(
8669 UnscopedName::Unqualified(
8670 UnqualifiedName::Source(
8671 SourceName(
8672 Identifier {
8673 start: 6,
8674 end: 9,
8675 }),
8676 AbiTags::default())))), vec![]))),
8677 b"..."
8678 }
8679 }
8680 Err => {
8681 b"_I" => Error::UnexpectedEnd,
8682 b"_" => Error::UnexpectedEnd,
8683 b"" => Error::UnexpectedEnd,
8684 b"blag" => Error::UnexpectedText,
8685 b"_J" => Error::UnexpectedText,
8686 b"_IJ" => Error::UnexpectedText,
8687 }
8688 });
8689 }
8690
8691 #[test]
8692 fn parse_name() {
8693 assert_parse!(Name {
8694 with subs [
8695 Substitutable::Prefix(
8696 Prefix::Unqualified(
8697 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
8698 AbiTags::default()))),
8699 Substitutable::Prefix(
8700 Prefix::Nested(PrefixHandle::BackReference(0),
8701 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
8702 AbiTags::default()))),
8703 ] => {
8704 Ok => {
8705 b"NS0_3abcE..." => {
8706 Name::Nested(NestedName::Unqualified(CvQualifiers::default(),
8707 None,
8708 Some(PrefixHandle::BackReference(1)),
8709 UnqualifiedName::Source(SourceName(Identifier {
8710 start: 5,
8711 end: 8,
8712 }), AbiTags::default()))),
8713 b"...",
8714 []
8715 }
8716 b"3abc..." => {
8717 Name::Unscoped(
8718 UnscopedName::Unqualified(
8719 UnqualifiedName::Source(
8720 SourceName(Identifier {
8721 start: 1,
8722 end: 4,
8723 }),
8724 AbiTags::default()))),
8725 b"...",
8726 []
8727 }
8728 b"dlIcE..." => {
8729 Name::UnscopedTemplate(
8730 UnscopedTemplateNameHandle::BackReference(2),
8731 TemplateArgs(vec![
8732 TemplateArg::Type(
8733 TypeHandle::Builtin(
8734 BuiltinType::Standard(StandardBuiltinType::Char)))
8735 ])),
8736 b"...",
8737 [
8738 Substitutable::UnscopedTemplateName(
8739 UnscopedTemplateName(
8740 UnscopedName::Unqualified(
8741 UnqualifiedName::Operator(
8742 OperatorName::Simple(
8743 SimpleOperatorName::Delete),
8744 AbiTags::default())))),
8745 ]
8746 }
8747 b"Z3abcEs..." => {
8748 Name::Local(
8749 LocalName::Relative(
8750 Box::new(Encoding::Data(
8751 Name::Unscoped(
8752 UnscopedName::Unqualified(
8753 UnqualifiedName::Source(
8754 SourceName(Identifier {
8755 start: 2,
8756 end: 5,
8757 }),
8758 AbiTags::default()))))),
8759 None,
8760 None)),
8761 b"...",
8762 []
8763 }
8764 }
8765 Err => {
8766 b"zzz" => Error::UnexpectedText,
8767 b"" => Error::UnexpectedEnd,
8768 }
8769 }
8770 });
8771 }
8772
8773 #[test]
8774 fn parse_unscoped_template_name_handle() {
8775 assert_parse!(UnscopedTemplateNameHandle {
8776 with subs [
8777 Substitutable::UnscopedTemplateName(
8778 UnscopedTemplateName(
8779 UnscopedName::Unqualified(
8780 UnqualifiedName::Operator(
8781 OperatorName::Simple(
8782 SimpleOperatorName::New),
8783 AbiTags::default())))),
8784 ] => {
8785 Ok => {
8786 b"S_..." => {
8787 UnscopedTemplateNameHandle::BackReference(0),
8788 b"...",
8789 []
8790 }
8791 b"dl..." => {
8792 UnscopedTemplateNameHandle::BackReference(1),
8793 b"...",
8794 [
8795 Substitutable::UnscopedTemplateName(
8796 UnscopedTemplateName(
8797 UnscopedName::Unqualified(
8798 UnqualifiedName::Operator(
8799 OperatorName::Simple(
8800 SimpleOperatorName::Delete),
8801 AbiTags::default()))))
8802 ]
8803 }
8804 }
8805 Err => {
8806 b"zzzz" => Error::UnexpectedText,
8807 b"" => Error::UnexpectedEnd,
8808 }
8809 }
8810 });
8811 }
8812
8813 #[test]
8814 fn parse_nested_name() {
8815 assert_parse!(NestedName {
8818 with subs [
8819 Substitutable::Prefix(
8820 Prefix::Unqualified(
8821 UnqualifiedName::Operator(
8822 OperatorName::Simple(
8823 SimpleOperatorName::New),
8824 AbiTags::default()))),
8825 ] => {
8826 Ok => {
8827 b"NKOS_3abcE..." => {
8828 NestedName::Unqualified(
8829 CvQualifiers {
8830 restrict: false,
8831 volatile: false,
8832 const_: true,
8833 },
8834 Some(RefQualifier::RValueRef),
8835 Some(PrefixHandle::BackReference(0)),
8836 UnqualifiedName::Source(
8837 SourceName(Identifier {
8838 start: 6,
8839 end: 9,
8840 }),
8841 AbiTags::default())),
8842 b"...",
8843 []
8844 }
8845 b"NOS_3abcE..." => {
8846 NestedName::Unqualified(
8847 CvQualifiers {
8848 restrict: false,
8849 volatile: false,
8850 const_: false,
8851 },
8852 Some(RefQualifier::RValueRef),
8853 Some(PrefixHandle::BackReference(0)),
8854 UnqualifiedName::Source(
8855 SourceName(Identifier {
8856 start: 5,
8857 end: 8,
8858 }), AbiTags::default())),
8859 b"...",
8860 []
8861 }
8862 b"NS_3abcE..." => {
8863 NestedName::Unqualified(
8864 CvQualifiers {
8865 restrict: false,
8866 volatile: false,
8867 const_: false,
8868 },
8869 None,
8870 Some(PrefixHandle::BackReference(0)),
8871 UnqualifiedName::Source(
8872 SourceName(Identifier {
8873 start: 4,
8874 end: 7,
8875 }), AbiTags::default())),
8876 b"...",
8877 []
8878 }
8879 b"NK1fE..." => {
8880 NestedName::Unqualified(
8881 CvQualifiers {
8882 restrict: false,
8883 volatile: false,
8884 const_: true,
8885 },
8886 None,
8887 None,
8888 UnqualifiedName::Source(
8889 SourceName(Identifier {
8890 start: 3,
8891 end: 4,
8892 }),
8893 AbiTags::default())),
8894 b"...",
8895 []
8896 }
8897 b"NKOS_3abcIJEEE..." => {
8898 NestedName::Template(
8899 CvQualifiers {
8900 restrict: false,
8901 volatile: false,
8902 const_: true,
8903 },
8904 Some(RefQualifier::RValueRef),
8905 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8906 b"...",
8907 [
8908 Substitutable::Prefix(
8909 Prefix::Nested(
8910 PrefixHandle::BackReference(0),
8911 UnqualifiedName::Source(
8912 SourceName(Identifier {
8913 start: 6,
8914 end: 9,
8915 }),
8916 AbiTags::default()))),
8917 ]
8918 }
8919 b"NOS_3abcIJEEE..." => {
8920 NestedName::Template(
8921 CvQualifiers {
8922 restrict: false,
8923 volatile: false,
8924 const_: false,
8925 },
8926 Some(RefQualifier::RValueRef),
8927 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8928 b"...",
8929 [
8930 Substitutable::Prefix(
8931 Prefix::Nested(
8932 PrefixHandle::BackReference(0),
8933 UnqualifiedName::Source(
8934 SourceName(Identifier {
8935 start: 5,
8936 end: 8,
8937 }),
8938 AbiTags::default()))),
8939 ]
8940 }
8941 b"NS_3abcIJEEE..." => {
8942 NestedName::Template(
8943 CvQualifiers {
8944 restrict: false,
8945 volatile: false,
8946 const_: false,
8947 },
8948 None,
8949 PrefixHandle::NonSubstitution(NonSubstitution(0))),
8950 b"...",
8951 [
8952 Substitutable::Prefix(
8953 Prefix::Nested(
8954 PrefixHandle::BackReference(0),
8955 UnqualifiedName::Source(
8956 SourceName(Identifier {
8957 start: 4,
8958 end: 7,
8959 }),
8960 AbiTags::default()))),
8961 ]
8962 }
8963 }
8964 Err => {
8965 b"NS_DttrEE..." => Error::UnexpectedText,
8967
8968 b"zzz" => Error::UnexpectedText,
8969 b"Nzzz" => Error::UnexpectedText,
8970 b"NKzzz" => Error::UnexpectedText,
8971 b"NKOzzz" => Error::UnexpectedText,
8972 b"NKO3abczzz" => Error::UnexpectedText,
8973 b"NKO3abc3abczzz" => Error::UnexpectedText,
8974 b"" => Error::UnexpectedEnd,
8975 b"N" => Error::UnexpectedEnd,
8976 b"NK" => Error::UnexpectedEnd,
8977 b"NKO" => Error::UnexpectedEnd,
8978 b"NKO3abc" => Error::UnexpectedEnd,
8979 b"NKO3abc3abc" => Error::UnexpectedEnd,
8980 }
8981 }
8982 });
8983 }
8984
8985 #[test]
8986 fn parse_prefix_handle() {
8987 assert_parse!(PrefixHandle {
8995 with subs [
8996 Substitutable::Prefix(
8997 Prefix::Unqualified(
8998 UnqualifiedName::Operator(
8999 OperatorName::Simple(
9000 SimpleOperatorName::New),
9001 AbiTags::default()))),
9002 ] => {
9003 Ok => {
9004 b"3foo..." => {
9005 PrefixHandle::BackReference(1),
9006 b"...",
9007 [
9008 Substitutable::Prefix(
9009 Prefix::Unqualified(
9010 UnqualifiedName::Source(
9011 SourceName(Identifier {
9012 start: 1,
9013 end: 4,
9014 }),
9015 AbiTags::default())))
9016 ]
9017 }
9018 b"3abc3def..." => {
9019 PrefixHandle::BackReference(2),
9020 b"...",
9021 [
9022 Substitutable::Prefix(
9023 Prefix::Unqualified(
9024 UnqualifiedName::Source(
9025 SourceName(Identifier {
9026 start: 1,
9027 end: 4,
9028 }),
9029 AbiTags::default()))),
9030 Substitutable::Prefix(
9031 Prefix::Nested(
9032 PrefixHandle::BackReference(1),
9033 UnqualifiedName::Source(
9034 SourceName(Identifier {
9035 start: 5,
9036 end: 8,
9037 }),
9038 AbiTags::default()))),
9039 ]
9040 }
9041 b"3fooIJEE..." => {
9042 PrefixHandle::BackReference(2),
9043 b"...",
9044 [
9045 Substitutable::Prefix(
9046 Prefix::Unqualified(
9047 UnqualifiedName::Source(
9048 SourceName(Identifier {
9049 start: 1,
9050 end: 4,
9051 }),
9052 AbiTags::default()))),
9053 Substitutable::Prefix(
9054 Prefix::Template(PrefixHandle::BackReference(1),
9055 TemplateArgs(vec![
9056 TemplateArg::ArgPack(vec![]),
9057 ])))
9058 ]
9059 }
9060 b"T_..." => {
9061 PrefixHandle::BackReference(1),
9062 b"...",
9063 [
9064 Substitutable::Prefix(Prefix::TemplateParam(TemplateParam(0))),
9065 ]
9066 }
9067 b"DTtrE..." => {
9068 PrefixHandle::BackReference(1),
9069 b"...",
9070 [
9071 Substitutable::Prefix(
9072 Prefix::Decltype(
9073 Decltype::Expression(Expression::Rethrow))),
9074 ]
9075 }
9076 b"3abc3defM..." => {
9077 PrefixHandle::BackReference(2),
9078 b"...",
9079 [
9080 Substitutable::Prefix(
9081 Prefix::Unqualified(
9082 UnqualifiedName::Source(
9083 SourceName(Identifier {
9084 start: 1,
9085 end: 4,
9086 }),
9087 AbiTags::default()))),
9088 Substitutable::Prefix(
9089 Prefix::DataMember(
9090 PrefixHandle::BackReference(1),
9091 DataMemberPrefix(
9092 SourceName(Identifier {
9093 start: 5,
9094 end: 8,
9095 })))),
9096 ]
9097 }
9098 b"S_..." => {
9099 PrefixHandle::BackReference(0),
9100 b"...",
9101 []
9102 }
9103 b"3abc3defE..." => {
9105 PrefixHandle::NonSubstitution(NonSubstitution(0)),
9106 b"E...",
9107 [
9108 Substitutable::Prefix(
9109 Prefix::Unqualified(
9110 UnqualifiedName::Source(
9111 SourceName(Identifier {
9112 start: 1,
9113 end: 4,
9114 }),
9115 AbiTags::default()))),
9116 ]
9117 }
9118 }
9119 Err => {
9120 b"zzz" => Error::UnexpectedText,
9121 b"" => Error::UnexpectedEnd,
9122 }
9123 }
9124 });
9125 }
9126
9127 #[test]
9128 fn parse_type_handle() {
9129 assert_parse!(TypeHandle {
9130 with subs [
9131 Substitutable::Type(
9132 Type::PointerTo(
9133 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9134 ] => {
9135 Ok => {
9136 b"S_..." => {
9137 TypeHandle::BackReference(0),
9138 b"...",
9139 []
9140 }
9141 b"c..." => {
9142 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
9143 b"...",
9144 []
9145 }
9146 b"FS_E..." => {
9147 TypeHandle::BackReference(1),
9148 b"...",
9149 [
9150 Substitutable::Type(
9151 Type::Function(FunctionType {
9152 cv_qualifiers: CvQualifiers {
9153 restrict: false,
9154 volatile: false,
9155 const_: false,
9156 },
9157 exception_spec: None,
9158 transaction_safe: false,
9159 extern_c: false,
9160 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9161 ref_qualifier: None,
9162 })),
9163 ]
9164 }
9165 b"A_S_..." => {
9166 TypeHandle::BackReference(1),
9167 b"...",
9168 [
9169 Substitutable::Type(
9170 Type::Array(ArrayType::NoDimension(TypeHandle::BackReference(0)))),
9171 ]
9172 }
9173 b"MS_S_..." => {
9174 TypeHandle::BackReference(1),
9175 b"...",
9176 [
9177 Substitutable::Type(
9178 Type::PointerToMember(
9179 PointerToMemberType(TypeHandle::BackReference(0),
9180 TypeHandle::BackReference(0)))),
9181 ]
9182 }
9183 b"T_..." => {
9184 TypeHandle::BackReference(1),
9185 b"...",
9186 [
9187 Substitutable::Type(Type::TemplateParam(TemplateParam(0))),
9188 ]
9189 }
9190 b"T_IS_E..." => {
9191 TypeHandle::BackReference(2),
9192 b"...",
9193 [
9194 Substitutable::TemplateTemplateParam(
9195 TemplateTemplateParam(TemplateParam(0))),
9196 Substitutable::Type(
9197 Type::TemplateTemplate(
9198 TemplateTemplateParamHandle::BackReference(1),
9199 TemplateArgs(vec![
9200 TemplateArg::Type(TypeHandle::BackReference(0))
9201 ]))),
9202 ]
9203 }
9204 b"DTtrE..." => {
9205 TypeHandle::BackReference(1),
9206 b"...",
9207 [
9208 Substitutable::Type(
9209 Type::Decltype(Decltype::Expression(Expression::Rethrow))),
9210 ]
9211 }
9212 b"KS_..." => {
9213 TypeHandle::BackReference(1),
9214 b"...",
9215 [
9216 Substitutable::Type(Type::Qualified(CvQualifiers {
9217 restrict: false,
9218 volatile: false,
9219 const_: true,
9220 }, TypeHandle::BackReference(0)))
9221 ]
9222 }
9223 b"PS_..." => {
9224 TypeHandle::BackReference(1),
9225 b"...",
9226 [
9227 Substitutable::Type(Type::PointerTo(TypeHandle::BackReference(0)))
9228 ]
9229 }
9230 b"RS_..." => {
9231 TypeHandle::BackReference(1),
9232 b"...",
9233 [
9234 Substitutable::Type(Type::LvalueRef(TypeHandle::BackReference(0)))
9235 ]
9236 }
9237 b"OS_..." => {
9238 TypeHandle::BackReference(1),
9239 b"...",
9240 [
9241 Substitutable::Type(Type::RvalueRef(TypeHandle::BackReference(0)))
9242 ]
9243 }
9244 b"CS_..." => {
9245 TypeHandle::BackReference(1),
9246 b"...",
9247 [
9248 Substitutable::Type(Type::Complex(TypeHandle::BackReference(0)))
9249 ]
9250 }
9251 b"GS_..." => {
9252 TypeHandle::BackReference(1),
9253 b"...",
9254 [
9255 Substitutable::Type(Type::Imaginary(TypeHandle::BackReference(0)))
9256 ]
9257 }
9258 b"U3abcS_..." => {
9259 TypeHandle::BackReference(1),
9260 b"...",
9261 [
9262 Substitutable::Type(
9263 Type::VendorExtension(
9264 SourceName(Identifier {
9265 start: 2,
9266 end: 5,
9267 }),
9268 None,
9269 TypeHandle::BackReference(0)))
9270 ]
9271 }
9272 b"U3abcIS_ES_..." => {
9273 TypeHandle::BackReference(1),
9274 b"...",
9275 [
9276 Substitutable::Type(
9277 Type::VendorExtension(
9278 SourceName(Identifier {
9279 start: 2,
9280 end: 5,
9281 }),
9282 Some(TemplateArgs(vec![
9283 TemplateArg::Type(TypeHandle::BackReference(0))
9284 ])),
9285 TypeHandle::BackReference(0)))
9286 ]
9287 }
9288 b"DpS_..." => {
9289 TypeHandle::BackReference(1),
9290 b"...",
9291 [
9292 Substitutable::Type(
9293 Type::PackExpansion(TypeHandle::BackReference(0))),
9294 ]
9295 }
9296 b"3abc..." => {
9297 TypeHandle::BackReference(1),
9298 b"...",
9299 [
9300 Substitutable::Type(
9301 Type::ClassEnum(
9302 ClassEnumType::Named(
9303 Name::Unscoped(
9304 UnscopedName::Unqualified(
9305 UnqualifiedName::Source(
9306 SourceName(Identifier {
9307 start: 1,
9308 end: 4,
9309 }),
9310 AbiTags::default()))))))
9311 ]
9312 }
9313 }
9314 Err => {
9315 b"P" => Error::UnexpectedEnd,
9316 b"R" => Error::UnexpectedEnd,
9317 b"O" => Error::UnexpectedEnd,
9318 b"C" => Error::UnexpectedEnd,
9319 b"G" => Error::UnexpectedEnd,
9320 b"Dp" => Error::UnexpectedEnd,
9321 b"D" => Error::UnexpectedEnd,
9322 b"P" => Error::UnexpectedEnd,
9323 b"UlvE_" => Error::UnexpectedText,
9324 b"" => Error::UnexpectedEnd,
9325 }
9326 }
9327 });
9328 }
9329
9330 #[test]
9331 fn parse_exception_spec() {
9332 assert_parse!(ExceptionSpec {
9333 Ok => {
9334 b"Do..." => {
9335 ExceptionSpec::NoExcept,
9336 b"..."
9337 }
9338 b"DOtrE..." => {
9339 ExceptionSpec::Computed(Expression::Rethrow),
9340 b"..."
9341 }
9342 }
9343 Err => {
9344 b"DOtre" => Error::UnexpectedText,
9345 b"DOE" => Error::UnexpectedText,
9346 b"D" => Error::UnexpectedEnd,
9347 b"" => Error::UnexpectedEnd,
9348 }
9349 });
9350 }
9351
9352 #[test]
9353 fn parse_function_type() {
9354 assert_parse!(FunctionType {
9355 with subs [
9356 Substitutable::Type(
9357 Type::PointerTo(
9358 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9359 ] => {
9360 Ok => {
9361 b"KDxFYS_RE..." => {
9362 FunctionType {
9363 cv_qualifiers: CvQualifiers {
9364 restrict: false,
9365 volatile: false,
9366 const_: true,
9367 },
9368 exception_spec: None,
9369 transaction_safe: true,
9370 extern_c: true,
9371 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9372 ref_qualifier: Some(RefQualifier::LValueRef),
9373 },
9374 b"...",
9375 []
9376 }
9377 b"DxFYS_RE..." => {
9378 FunctionType {
9379 cv_qualifiers: CvQualifiers {
9380 restrict: false,
9381 volatile: false,
9382 const_: false,
9383 },
9384 exception_spec: None,
9385 transaction_safe: true,
9386 extern_c: true,
9387 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9388 ref_qualifier: Some(RefQualifier::LValueRef),
9389 },
9390 b"...",
9391 []
9392 }
9393 b"FYS_RE..." => {
9394 FunctionType {
9395 cv_qualifiers: CvQualifiers {
9396 restrict: false,
9397 volatile: false,
9398 const_: false,
9399 },
9400 exception_spec: None,
9401 transaction_safe: false,
9402 extern_c: true,
9403 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9404 ref_qualifier: Some(RefQualifier::LValueRef),
9405 },
9406 b"...",
9407 []
9408 }
9409 b"FS_RE..." => {
9410 FunctionType {
9411 cv_qualifiers: CvQualifiers {
9412 restrict: false,
9413 volatile: false,
9414 const_: false,
9415 },
9416 exception_spec: None,
9417 transaction_safe: false,
9418 extern_c: false,
9419 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9420 ref_qualifier: Some(RefQualifier::LValueRef),
9421 },
9422 b"...",
9423 []
9424 }
9425 b"FS_E..." => {
9426 FunctionType {
9427 cv_qualifiers: CvQualifiers {
9428 restrict: false,
9429 volatile: false,
9430 const_: false,
9431 },
9432 exception_spec: None,
9433 transaction_safe: false,
9434 extern_c: false,
9435 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9436 ref_qualifier: None,
9437 },
9438 b"...",
9439 []
9440 }
9441 }
9442 Err => {
9443 b"DFYS_E" => Error::UnexpectedText,
9444 b"KKFS_E" => Error::UnexpectedText,
9445 b"FYS_..." => Error::UnexpectedText,
9446 b"FYS_" => Error::UnexpectedEnd,
9447 b"F" => Error::UnexpectedEnd,
9448 b"" => Error::UnexpectedEnd,
9449 }
9450 }
9451 });
9452 }
9453
9454 #[test]
9455 fn parse_bare_function_type() {
9456 assert_parse!(BareFunctionType {
9457 with subs [
9458 Substitutable::Type(
9459 Type::PointerTo(
9460 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9461 ] => {
9462 Ok => {
9463 b"S_S_..." => {
9464 BareFunctionType(vec![
9465 TypeHandle::BackReference(0),
9466 TypeHandle::BackReference(0),
9467 ]),
9468 b"...",
9469 []
9470 }
9471 }
9472 Err => {
9473 b"" => Error::UnexpectedEnd,
9474 }
9475 }
9476 });
9477 }
9478
9479 #[test]
9480 fn parse_decltype() {
9481 assert_parse!(Decltype {
9482 Ok => {
9483 b"DTtrE..." => {
9484 Decltype::Expression(Expression::Rethrow),
9485 b"..."
9486 }
9487 b"DttrE..." => {
9488 Decltype::IdExpression(Expression::Rethrow),
9489 b"..."
9490 }
9491 }
9492 Err => {
9493 b"Dtrtz" => Error::UnexpectedText,
9494 b"DTrtz" => Error::UnexpectedText,
9495 b"Dz" => Error::UnexpectedText,
9496 b"Dtrt" => Error::UnexpectedText,
9497 b"DTrt" => Error::UnexpectedText,
9498 b"Dt" => Error::UnexpectedEnd,
9499 b"DT" => Error::UnexpectedEnd,
9500 b"D" => Error::UnexpectedEnd,
9501 b"" => Error::UnexpectedEnd,
9502 }
9503 });
9504 }
9505
9506 #[test]
9507 fn parse_class_enum_type() {
9508 assert_parse!(ClassEnumType {
9509 Ok => {
9510 b"3abc..." => {
9511 ClassEnumType::Named(
9512 Name::Unscoped(
9513 UnscopedName::Unqualified(
9514 UnqualifiedName::Source(
9515 SourceName(Identifier {
9516 start: 1,
9517 end: 4,
9518 }),
9519 AbiTags::default())))),
9520 b"..."
9521 }
9522 b"Ts3abc..." => {
9523 ClassEnumType::ElaboratedStruct(
9524 Name::Unscoped(
9525 UnscopedName::Unqualified(
9526 UnqualifiedName::Source(
9527 SourceName(Identifier {
9528 start: 3,
9529 end: 6,
9530 }),
9531 AbiTags::default())))),
9532 b"..."
9533 }
9534 b"Tu3abc..." => {
9535 ClassEnumType::ElaboratedUnion(
9536 Name::Unscoped(
9537 UnscopedName::Unqualified(
9538 UnqualifiedName::Source(
9539 SourceName(Identifier {
9540 start: 3,
9541 end: 6,
9542 }),
9543 AbiTags::default())))),
9544 b"..."
9545 }
9546 b"Te3abc..." => {
9547 ClassEnumType::ElaboratedEnum(
9548 Name::Unscoped(
9549 UnscopedName::Unqualified(
9550 UnqualifiedName::Source(
9551 SourceName(Identifier {
9552 start: 3,
9553 end: 6,
9554 }),
9555 AbiTags::default())))),
9556 b"..."
9557 }
9558 }
9559 Err => {
9560 b"zzz" => Error::UnexpectedText,
9561 b"Tzzz" => Error::UnexpectedText,
9562 b"T" => Error::UnexpectedEnd,
9563 b"" => Error::UnexpectedEnd,
9564 }
9565 });
9566 }
9567
9568 #[test]
9569 fn parse_array_type() {
9570 assert_parse!(ArrayType {
9571 with subs [
9572 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9573 ] => {
9574 Ok => {
9575 b"A10_S_..." => {
9576 ArrayType::DimensionNumber(10, TypeHandle::BackReference(0)),
9577 b"...",
9578 []
9579 }
9580 b"A10_Sb..." => {
9581 ArrayType::DimensionNumber(10,
9582 TypeHandle::WellKnown(
9583 WellKnownComponent::StdString1)),
9584 b"...",
9585 []
9586 }
9587 b"Atr_S_..." => {
9588 ArrayType::DimensionExpression(Expression::Rethrow,
9589 TypeHandle::BackReference(0)),
9590 b"...",
9591 []
9592 }
9593 b"A_S_..." => {
9594 ArrayType::NoDimension(TypeHandle::BackReference(0)),
9595 b"...",
9596 []
9597 }
9598 }
9599 Err => {
9600 b"A10_" => Error::UnexpectedEnd,
9601 b"A10" => Error::UnexpectedEnd,
9602 b"A" => Error::UnexpectedEnd,
9603 b"" => Error::UnexpectedEnd,
9604 b"A10_..." => Error::UnexpectedText,
9605 b"A10..." => Error::UnexpectedText,
9606 b"A..." => Error::UnexpectedText,
9607 b"..." => Error::UnexpectedText,
9608 }
9609 }
9610 });
9611 }
9612
9613 #[test]
9614 fn parse_vector_type() {
9615 assert_parse!(VectorType {
9616 with subs [
9617 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9618 ] => {
9619 Ok => {
9620 b"Dv10_S_..." => {
9621 VectorType::DimensionNumber(10, TypeHandle::BackReference(0)),
9622 b"...",
9623 []
9624 }
9625 b"Dv10_Sb..." => {
9626 VectorType::DimensionNumber(10,
9627 TypeHandle::WellKnown(
9628 WellKnownComponent::StdString1)),
9629 b"...",
9630 []
9631 }
9632 b"Dvtr_S_..." => {
9633 VectorType::DimensionExpression(Expression::Rethrow,
9634 TypeHandle::BackReference(0)),
9635 b"...",
9636 []
9637 }
9638 }
9639 Err => {
9640 b"Dq" => Error::UnexpectedText,
9641 b"Dv" => Error::UnexpectedEnd,
9642 b"Dv42_" => Error::UnexpectedEnd,
9643 b"Dv42_..." => Error::UnexpectedText,
9644 b"Dvtr_" => Error::UnexpectedEnd,
9645 b"Dvtr_..." => Error::UnexpectedText,
9646 b"" => Error::UnexpectedEnd,
9647 b"..." => Error::UnexpectedText,
9648 }
9649 }
9650 });
9651 }
9652
9653 #[test]
9654 fn parse_pointer_to_member_type() {
9655 assert_parse!(PointerToMemberType {
9656 with subs [
9657 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9658 ] => {
9659 Ok => {
9660 b"MS_S_..." => {
9661 PointerToMemberType(TypeHandle::BackReference(0),
9662 TypeHandle::BackReference(0)),
9663 b"...",
9664 []
9665 }
9666 }
9667 Err => {
9668 b"MS_S" => Error::UnexpectedEnd,
9669 b"MS_" => Error::UnexpectedEnd,
9670 b"MS" => Error::UnexpectedEnd,
9671 b"M" => Error::UnexpectedEnd,
9672 b"" => Error::UnexpectedEnd,
9673 b"MS_..." => Error::UnexpectedText,
9674 b"M..." => Error::UnexpectedText,
9675 b"..." => Error::UnexpectedText,
9676 }
9677 }
9678 });
9679 }
9680
9681 #[test]
9682 fn parse_template_template_param_handle() {
9683 assert_parse!(TemplateTemplateParamHandle {
9684 with subs [
9685 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(0)))
9686 ] => {
9687 Ok => {
9688 b"S_..." => {
9689 TemplateTemplateParamHandle::BackReference(0),
9690 b"...",
9691 []
9692 }
9693 b"T1_..." => {
9694 TemplateTemplateParamHandle::BackReference(1),
9695 b"...",
9696 [
9697 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(2)))
9698 ]
9699 }
9700 }
9701 Err => {
9702 b"S" => Error::UnexpectedText,
9703 b"T" => Error::UnexpectedEnd,
9704 b"" => Error::UnexpectedEnd,
9705 b"S..." => Error::UnexpectedText,
9706 b"T..." => Error::UnexpectedText,
9707 b"..." => Error::UnexpectedText,
9708 }
9709 }
9710 });
9711 }
9712
9713 #[test]
9714 fn parse_template_args() {
9715 assert_parse!(TemplateArgs {
9716 with subs [
9717 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9718 ] => {
9719 Ok => {
9720 b"IS_E..." => {
9721 TemplateArgs(vec![TemplateArg::Type(TypeHandle::BackReference(0))]),
9722 b"...",
9723 []
9724 }
9725 b"IS_S_S_S_E..." => {
9726 TemplateArgs(vec![
9727 TemplateArg::Type(TypeHandle::BackReference(0)),
9728 TemplateArg::Type(TypeHandle::BackReference(0)),
9729 TemplateArg::Type(TypeHandle::BackReference(0)),
9730 TemplateArg::Type(TypeHandle::BackReference(0)),
9731 ]),
9732 b"...",
9733 []
9734 }
9735 }
9736 Err => {
9737 b"zzz" => Error::UnexpectedText,
9738 b"IE" => Error::UnexpectedText,
9739 b"IS_" => Error::UnexpectedEnd,
9740 b"I" => Error::UnexpectedEnd,
9741 b"" => Error::UnexpectedEnd,
9742 }
9743 }
9744 });
9745 }
9746
9747 #[test]
9748 fn parse_template_arg() {
9749 assert_parse!(TemplateArg {
9750 with subs [
9751 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9752 ] => {
9753 Ok => {
9754 b"S_..." => {
9755 TemplateArg::Type(TypeHandle::BackReference(0)),
9756 b"...",
9757 []
9758 }
9759 b"XtrE..." => {
9760 TemplateArg::Expression(Expression::Rethrow),
9761 b"...",
9762 []
9763 }
9764 b"XsrS_1QE..." => {
9765 TemplateArg::Expression(
9766 Expression::UnresolvedName(
9767 UnresolvedName::Nested1(
9768 UnresolvedTypeHandle::BackReference(0),
9769 vec![],
9770 BaseUnresolvedName::Name(
9771 SimpleId(
9772 SourceName(Identifier {
9773 start: 6,
9774 end: 7
9775 }),
9776 None
9777 )
9778 )
9779 )
9780 )
9781 ),
9782 b"...",
9783 []
9784 }
9785 b"XsrS_1QIlEE..." => {
9786 TemplateArg::Expression(
9787 Expression::UnresolvedName(
9788 UnresolvedName::Nested1(
9789 UnresolvedTypeHandle::BackReference(0),
9790 vec![],
9791 BaseUnresolvedName::Name(
9792 SimpleId(
9793 SourceName(Identifier {
9794 start: 6,
9795 end: 7
9796 }),
9797 Some(
9798 TemplateArgs(
9799 vec![
9800 TemplateArg::Type(
9801 TypeHandle::Builtin(
9802 BuiltinType::Standard(
9803 StandardBuiltinType::Long
9804 )
9805 )
9806 )
9807 ]
9808 )
9809 )
9810 )
9811 )
9812 )
9813 )
9814 ),
9815 b"...",
9816 []
9817 }
9818 b"LS_E..." => {
9819 TemplateArg::SimpleExpression(
9820 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3)),
9821 b"...",
9822 []
9823 }
9824 b"JE..." => {
9825 TemplateArg::ArgPack(vec![]),
9826 b"...",
9827 []
9828 }
9829 b"JS_XtrELS_EJEE..." => {
9830 TemplateArg::ArgPack(vec![
9831 TemplateArg::Type(TypeHandle::BackReference(0)),
9832 TemplateArg::Expression(Expression::Rethrow),
9833 TemplateArg::SimpleExpression(
9834 ExprPrimary::Literal(TypeHandle::BackReference(0), 10, 10)),
9835 TemplateArg::ArgPack(vec![]),
9836 ]),
9837 b"...",
9838 []
9839 }
9840 }
9841 Err => {
9842 b"..." => Error::UnexpectedText,
9843 b"X..." => Error::UnexpectedText,
9844 b"J..." => Error::UnexpectedText,
9845 b"JS_..." => Error::UnexpectedText,
9846 b"JS_" => Error::UnexpectedEnd,
9847 b"X" => Error::UnexpectedEnd,
9848 b"J" => Error::UnexpectedEnd,
9849 b"" => Error::UnexpectedEnd,
9850 }
9851 }
9852 });
9853 }
9854
9855 #[test]
9856 fn parse_expression() {
9857 assert_parse!(Expression {
9858 with subs [
9859 Substitutable::Type(
9860 Type::PointerTo(TypeHandle::Builtin(
9861 BuiltinType::Standard(StandardBuiltinType::Int)))),
9862 ] => {
9863 Ok => {
9864 b"psLS_1E..." => {
9865 Expression::Unary(OperatorName::Simple(SimpleOperatorName::UnaryPlus),
9866 Box::new(Expression::Primary(
9867 ExprPrimary::Literal(
9868 TypeHandle::BackReference(0),
9869 5,
9870 6)))),
9871 b"...",
9872 []
9873 }
9874 b"rsLS_1ELS_1E..." => {
9875 Expression::Binary(OperatorName::Simple(SimpleOperatorName::Shr),
9876 Box::new(Expression::Primary(
9877 ExprPrimary::Literal(
9878 TypeHandle::BackReference(0),
9879 5,
9880 6))),
9881 Box::new(Expression::Primary(
9882 ExprPrimary::Literal(
9883 TypeHandle::BackReference(0),
9884 10,
9885 11)))),
9886 b"...",
9887 []
9888 }
9889 b"quLS_1ELS_2ELS_3E..." => {
9890 Expression::Ternary(OperatorName::Simple(SimpleOperatorName::Question),
9891 Box::new(Expression::Primary(
9892 ExprPrimary::Literal(
9893 TypeHandle::BackReference(0),
9894 5,
9895 6))),
9896 Box::new(Expression::Primary(
9897 ExprPrimary::Literal(
9898 TypeHandle::BackReference(0),
9899 10,
9900 11))),
9901 Box::new(Expression::Primary(
9902 ExprPrimary::Literal(
9903 TypeHandle::BackReference(0),
9904 15,
9905 16)))),
9906 b"...",
9907 []
9908 }
9909 b"pp_LS_1E..." => {
9910 Expression::PrefixInc(
9911 Box::new(Expression::Primary(
9912 ExprPrimary::Literal(
9913 TypeHandle::BackReference(0),
9914 6,
9915 7)))),
9916 b"...",
9917 []
9918 }
9919 b"mm_LS_1E..." => {
9920 Expression::PrefixDec(
9921 Box::new(Expression::Primary(
9922 ExprPrimary::Literal(
9923 TypeHandle::BackReference(0),
9924 6,
9925 7)))),
9926 b"...",
9927 []
9928 }
9929 b"clLS_1EE..." => {
9930 Expression::Call(
9931 Box::new(Expression::Primary(
9932 ExprPrimary::Literal(
9933 TypeHandle::BackReference(0),
9934 5,
9935 6))),
9936 vec![]),
9937 b"...",
9938 []
9939 }
9940 b"cvS_LS_1E..." => {
9942 Expression::ConversionOne(
9943 TypeHandle::BackReference(0),
9944 Box::new(Expression::Primary(
9945 ExprPrimary::Literal(
9946 TypeHandle::BackReference(0),
9947 7,
9948 8)))),
9949 b"...",
9950 []
9951 }
9952 b"cvS__LS_1ELS_1EE..." => {
9953 Expression::ConversionMany(
9954 TypeHandle::BackReference(0),
9955 vec![
9956 Expression::Primary(
9957 ExprPrimary::Literal(
9958 TypeHandle::BackReference(0),
9959 8,
9960 9)),
9961 Expression::Primary(
9962 ExprPrimary::Literal(
9963 TypeHandle::BackReference(0),
9964 13,
9965 14)),
9966 ]),
9967 b"...",
9968 []
9969 }
9970 b"tlS_LS_1ELS_1EE..." => {
9971 Expression::ConversionBraced(
9972 TypeHandle::BackReference(0),
9973 vec![
9974 Expression::Primary(
9975 ExprPrimary::Literal(
9976 TypeHandle::BackReference(0),
9977 7,
9978 8)),
9979 Expression::Primary(
9980 ExprPrimary::Literal(
9981 TypeHandle::BackReference(0),
9982 12,
9983 13)),
9984 ]),
9985 b"...",
9986 []
9987 }
9988 b"ilLS_1EE..." => {
9989 Expression::BracedInitList(
9990 Box::new(Expression::Primary(
9991 ExprPrimary::Literal(
9992 TypeHandle::BackReference(0),
9993 5,
9994 6)))),
9995 b"...",
9996 []
9997 }
9998 b"gsnwLS_1E_S_E..." => {
9999 Expression::GlobalNew(
10000 vec![
10001 Expression::Primary(
10002 ExprPrimary::Literal(
10003 TypeHandle::BackReference(0),
10004 7,
10005 8))
10006 ],
10007 TypeHandle::BackReference(0),
10008 None),
10009 b"...",
10010 []
10011 }
10012 b"nwLS_1E_S_E..." => {
10013 Expression::New(
10014 vec![
10015 Expression::Primary(
10016 ExprPrimary::Literal(
10017 TypeHandle::BackReference(0),
10018 5,
10019 6))
10020 ],
10021 TypeHandle::BackReference(0),
10022 None),
10023 b"...",
10024 []
10025 }
10026 b"gsnwLS_1E_S_piE..." => {
10027 Expression::GlobalNew(
10028 vec![
10029 Expression::Primary(
10030 ExprPrimary::Literal(
10031 TypeHandle::BackReference(0),
10032 7,
10033 8))
10034 ],
10035 TypeHandle::BackReference(0),
10036 Some(Initializer(vec![]))),
10037 b"...",
10038 []
10039 }
10040 b"nwLS_1E_S_piE..." => {
10041 Expression::New(
10042 vec![
10043 Expression::Primary(
10044 ExprPrimary::Literal(
10045 TypeHandle::BackReference(0),
10046 5,
10047 6))
10048 ],
10049 TypeHandle::BackReference(0),
10050 Some(Initializer(vec![]))),
10051 b"...",
10052 []
10053 }
10054 b"gsnaLS_1E_S_E..." => {
10055 Expression::GlobalNewArray(
10056 vec![
10057 Expression::Primary(
10058 ExprPrimary::Literal(
10059 TypeHandle::BackReference(0),
10060 7,
10061 8))
10062 ],
10063 TypeHandle::BackReference(0),
10064 None),
10065 b"...",
10066 []
10067 }
10068 b"naLS_1E_S_E..." => {
10069 Expression::NewArray(
10070 vec![
10071 Expression::Primary(
10072 ExprPrimary::Literal(
10073 TypeHandle::BackReference(0),
10074 5,
10075 6))
10076 ],
10077 TypeHandle::BackReference(0),
10078 None),
10079 b"...",
10080 []
10081 }
10082 b"gsnaLS_1E_S_piE..." => {
10083 Expression::GlobalNewArray(
10084 vec![
10085 Expression::Primary(
10086 ExprPrimary::Literal(
10087 TypeHandle::BackReference(0),
10088 7,
10089 8))
10090 ],
10091 TypeHandle::BackReference(0),
10092 Some(Initializer(vec![]))),
10093 b"...",
10094 []
10095 }
10096 b"naLS_1E_S_piE..." => {
10097 Expression::NewArray(
10098 vec![
10099 Expression::Primary(
10100 ExprPrimary::Literal(
10101 TypeHandle::BackReference(0),
10102 5,
10103 6))
10104 ],
10105 TypeHandle::BackReference(0),
10106 Some(Initializer(vec![]))),
10107 b"...",
10108 []
10109 }
10110 b"gsdlLS_1E..." => {
10111 Expression::GlobalDelete(
10112 Box::new(Expression::Primary(
10113 ExprPrimary::Literal(
10114 TypeHandle::BackReference(0),
10115 7,
10116 8)))),
10117 b"...",
10118 []
10119 }
10120 b"dlLS_1E..." => {
10121 Expression::Delete(
10122 Box::new(Expression::Primary(
10123 ExprPrimary::Literal(
10124 TypeHandle::BackReference(0),
10125 5,
10126 6)))),
10127 b"...",
10128 []
10129 }
10130 b"gsdaLS_1E..." => {
10132 Expression::GlobalDeleteArray(
10133 Box::new(Expression::Primary(
10134 ExprPrimary::Literal(
10135 TypeHandle::BackReference(0),
10136 7,
10137 8)))),
10138 b"...",
10139 []
10140 }
10141 b"daLS_1E..." => {
10142 Expression::DeleteArray(
10143 Box::new(Expression::Primary(
10144 ExprPrimary::Literal(
10145 TypeHandle::BackReference(0),
10146 5,
10147 6)))),
10148 b"...",
10149 []
10150 }
10151 b"dcS_LS_1E..." => {
10152 Expression::DynamicCast(
10153 TypeHandle::BackReference(0),
10154 Box::new(Expression::Primary(
10155 ExprPrimary::Literal(
10156 TypeHandle::BackReference(0),
10157 7,
10158 8)))),
10159 b"...",
10160 []
10161 }
10162 b"scS_LS_1E..." => {
10163 Expression::StaticCast(
10164 TypeHandle::BackReference(0),
10165 Box::new(Expression::Primary(
10166 ExprPrimary::Literal(
10167 TypeHandle::BackReference(0),
10168 7,
10169 8)))),
10170 b"...",
10171 []
10172 }
10173 b"ccS_LS_1E..." => {
10174 Expression::ConstCast(
10175 TypeHandle::BackReference(0),
10176 Box::new(Expression::Primary(
10177 ExprPrimary::Literal(
10178 TypeHandle::BackReference(0),
10179 7,
10180 8)))),
10181 b"...",
10182 []
10183 }
10184 b"rcS_LS_1E..." => {
10185 Expression::ReinterpretCast(
10186 TypeHandle::BackReference(0),
10187 Box::new(Expression::Primary(
10188 ExprPrimary::Literal(
10189 TypeHandle::BackReference(0),
10190 7,
10191 8)))),
10192 b"...",
10193 []
10194 }
10195 b"tiS_..." => {
10196 Expression::TypeidType(TypeHandle::BackReference(0)),
10197 b"...",
10198 []
10199 }
10200 b"teLS_1E..." => {
10201 Expression::TypeidExpr(
10202 Box::new(Expression::Primary(
10203 ExprPrimary::Literal(
10204 TypeHandle::BackReference(0),
10205 5,
10206 6)))),
10207 b"...",
10208 []
10209 }
10210 b"stS_..." => {
10211 Expression::SizeofType(TypeHandle::BackReference(0)),
10212 b"...",
10213 []
10214 }
10215 b"szLS_1E..." => {
10216 Expression::SizeofExpr(
10217 Box::new(Expression::Primary(
10218 ExprPrimary::Literal(
10219 TypeHandle::BackReference(0),
10220 5,
10221 6)))),
10222 b"...",
10223 []
10224 }
10225 b"atS_..." => {
10226 Expression::AlignofType(TypeHandle::BackReference(0)),
10227 b"...",
10228 []
10229 }
10230 b"azLS_1E..." => {
10231 Expression::AlignofExpr(
10232 Box::new(Expression::Primary(
10233 ExprPrimary::Literal(
10234 TypeHandle::BackReference(0),
10235 5,
10236 6)))),
10237 b"...",
10238 []
10239 }
10240 b"nxLS_1E..." => {
10241 Expression::Noexcept(
10242 Box::new(Expression::Primary(
10243 ExprPrimary::Literal(
10244 TypeHandle::BackReference(0),
10245 5,
10246 6)))),
10247 b"...",
10248 []
10249 }
10250 b"T_..." => {
10251 Expression::TemplateParam(TemplateParam(0)),
10252 b"...",
10253 []
10254 }
10255 b"fp_..." => {
10256 Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0))),
10257 b"...",
10258 []
10259 }
10260 b"dtT_3abc..." => {
10261 Expression::Member(
10262 Box::new(Expression::TemplateParam(TemplateParam(0))),
10263 MemberName(
10264 Name::Unscoped(
10265 UnscopedName::Unqualified(
10266 UnqualifiedName::Source(
10267 SourceName(
10268 Identifier {
10269 start: 5,
10270 end: 8,
10271 }),
10272 AbiTags::default()))))),
10273 b"...",
10274 []
10275 }
10276 b"ptT_3abc..." => {
10277 Expression::DerefMember(
10278 Box::new(Expression::TemplateParam(TemplateParam(0))),
10279 MemberName(
10280 Name::Unscoped(
10281 UnscopedName::Unqualified(
10282 UnqualifiedName::Source(
10283 SourceName(
10284 Identifier {
10285 start: 5,
10286 end: 8,
10287 }),
10288 AbiTags::default()))))),
10289 b"...",
10290 []
10291 }
10292 b"dtfp_clI3abcE..." => {
10293 Expression::Member(
10294 Box::new(Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0)))),
10295 MemberName(
10296 Name::UnscopedTemplate(
10297 UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(0)),
10298 TemplateArgs(vec![
10299 TemplateArg::Type(
10300 TypeHandle::BackReference(1))])))),
10301 b"...",
10302 [
10303 Substitutable::Type(
10304 Type::ClassEnum(
10305 ClassEnumType::Named(
10306 Name::Unscoped(
10307 UnscopedName::Unqualified(
10308 UnqualifiedName::Source(
10309 SourceName(
10310 Identifier {
10311 start: 9,
10312 end: 12
10313 }),
10314 AbiTags::default()))))))
10315 ]
10316 }
10317 b"dsT_T_..." => {
10319 Expression::PointerToMember(
10320 Box::new(Expression::TemplateParam(TemplateParam(0))),
10321 Box::new(Expression::TemplateParam(TemplateParam(0)))),
10322 b"...",
10323 []
10324 }
10325 b"sZT_..." => {
10326 Expression::SizeofTemplatePack(TemplateParam(0)),
10327 b"...",
10328 []
10329 }
10330 b"sZfp_..." => {
10331 Expression::SizeofFunctionPack(
10332 FunctionParam(0, CvQualifiers::default(), Some(0))),
10333 b"...",
10334 []
10335 }
10336 b"sPE..." => {
10337 Expression::SizeofCapturedTemplatePack(vec![]),
10338 b"...",
10339 []
10340 }
10341 b"spT_..." => {
10342 Expression::PackExpansion(
10343 Box::new(Expression::TemplateParam(TemplateParam(0)))),
10344 b"...",
10345 []
10346 }
10347 b"twT_..." => {
10348 Expression::Throw(Box::new(Expression::TemplateParam(TemplateParam(0)))),
10349 b"...",
10350 []
10351 }
10352 b"tr..." => {
10353 Expression::Rethrow,
10354 b"...",
10355 []
10356 }
10357 b"3abc..." => {
10358 Expression::UnresolvedName(
10359 UnresolvedName::Name(
10360 BaseUnresolvedName::Name(
10361 SimpleId(
10362 SourceName(Identifier {
10363 start: 1,
10364 end: 4,
10365 }),
10366 None)))),
10367 b"...",
10368 []
10369 }
10370 b"L_Z3abcE..." => {
10371 Expression::Primary(
10372 ExprPrimary::External(
10373 MangledName::Encoding(
10374 Encoding::Data(
10375 Name::Unscoped(
10376 UnscopedName::Unqualified(
10377 UnqualifiedName::Source(
10378 SourceName(Identifier {
10379 start: 4,
10380 end: 7,
10381 }),
10382 AbiTags::default())))), vec![]))),
10383 b"...",
10384 []
10385 }
10386 b"cldtdefpT4TypeadsrT_5EnterE..." => {
10388 Expression::Call(
10389 Box::new(Expression::Member(
10390 Box::new(Expression::Unary(OperatorName::Simple(SimpleOperatorName::Deref),
10391 Box::new(Expression::FunctionParam(
10392 FunctionParam(0,
10393 CvQualifiers::default(),
10394 None)
10395 ))
10396 )),
10397 MemberName(
10398 Name::Unscoped(
10399 UnscopedName::Unqualified(
10400 UnqualifiedName::Source(
10401 SourceName(Identifier {
10402 start: 10,
10403 end: 14,
10404 }),
10405 AbiTags::default()))
10406 )
10407 )
10408 )),
10409 vec![Expression::Unary(OperatorName::Simple(SimpleOperatorName::AddressOf),
10410 Box::new(Expression::UnresolvedName(
10411 UnresolvedName::Nested1(
10412 UnresolvedTypeHandle::BackReference(1),
10413 vec![],
10414 BaseUnresolvedName::Name(
10415 SimpleId(
10416 SourceName(Identifier {
10417 start: 21,
10418 end: 26
10419 }
10420 ),
10421 None
10422 )
10423 )
10424 ))))]
10425 ),
10426 b"...",
10427 [
10428 Substitutable::UnresolvedType(UnresolvedType::Template(TemplateParam(0), None))
10429 ]
10430 }
10431 }
10432 Err => {
10433 b"dtStfp_clI3abcE..." => Error::UnexpectedText,
10434 }
10435 }
10436 });
10437 }
10438
10439 #[test]
10440 fn parse_unresolved_name() {
10441 assert_parse!(UnresolvedName {
10442 with subs [
10443 Substitutable::UnresolvedType(
10444 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10445 ] => {
10446 Ok => {
10447 b"gs3abc..." => {
10448 UnresolvedName::Global(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10449 start: 3,
10450 end: 6,
10451 }), None))),
10452 b"...",
10453 []
10454 }
10455 b"3abc..." => {
10456 UnresolvedName::Name(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10457 start: 1,
10458 end: 4,
10459 }), None))),
10460 b"...",
10461 []
10462 }
10463 b"srS_3abc..." => {
10464 UnresolvedName::Nested1(UnresolvedTypeHandle::BackReference(0),
10465 vec![],
10466 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10467 start: 5,
10468 end: 8,
10469 }), None))),
10470 b"...",
10471 []
10472 }
10473 b"srNS_3abc3abcE3abc..." => {
10474 UnresolvedName::Nested1(
10475 UnresolvedTypeHandle::BackReference(0),
10476 vec![
10477 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10478 start: 6,
10479 end: 9,
10480 }), None)),
10481 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10482 start: 10,
10483 end: 13,
10484 }), None)),
10485 ],
10486 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10487 start: 15,
10488 end: 18,
10489 }), None))),
10490 b"...",
10491 []
10492 }
10493 b"gssr3abcE3abc..." => {
10494 UnresolvedName::GlobalNested2(
10495 vec![
10496 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10497 start: 5,
10498 end: 8,
10499 }), None)),
10500 ],
10501 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10502 start: 10,
10503 end: 13,
10504 }), None))),
10505 b"...",
10506 []
10507 }
10508 b"sr3abcE3abc..." => {
10509 UnresolvedName::Nested2(
10510 vec![
10511 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10512 start: 3,
10513 end: 6,
10514 }), None)),
10515 ],
10516 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10517 start: 8,
10518 end: 11,
10519 }), None))),
10520 b"...",
10521 []
10522 }
10523 }
10524 Err => {
10525 b"zzzzzz" => Error::UnexpectedText,
10526 b"gszzz" => Error::UnexpectedText,
10527 b"gssrzzz" => Error::UnexpectedText,
10528 b"srNzzz" => Error::UnexpectedText,
10529 b"srzzz" => Error::UnexpectedText,
10530 b"srN3abczzzz" => Error::UnexpectedText,
10531 b"srN3abcE" => Error::UnexpectedText,
10532 b"srN3abc" => Error::UnexpectedText,
10533 b"srN" => Error::UnexpectedEnd,
10534 b"sr" => Error::UnexpectedEnd,
10535 b"gssr" => Error::UnexpectedEnd,
10536 b"gs" => Error::UnexpectedEnd,
10537 b"" => Error::UnexpectedEnd,
10538 }
10539 }
10540 });
10541 }
10542
10543 #[test]
10544 fn parse_unresolved_type_handle() {
10545 assert_parse!(UnresolvedTypeHandle {
10546 with subs [
10547 Substitutable::UnresolvedType(
10548 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10549 ] => {
10550 Ok => {
10551 b"S_..." => {
10552 UnresolvedTypeHandle::BackReference(0),
10553 b"...",
10554 []
10555 }
10556 b"T_..." => {
10557 UnresolvedTypeHandle::BackReference(1),
10558 b"...",
10559 [
10560 Substitutable::UnresolvedType(
10561 UnresolvedType::Template(TemplateParam(0), None)),
10562 ]
10563 }
10564 b"T_IS_E..." => {
10565 UnresolvedTypeHandle::BackReference(1),
10566 b"...",
10567 [
10568 Substitutable::UnresolvedType(
10569 UnresolvedType::Template(TemplateParam(0), Some(TemplateArgs(vec![
10570 TemplateArg::Type(TypeHandle::BackReference(0))
10571 ])))),
10572 ]
10573 }
10574 b"DTtrE..." => {
10575 UnresolvedTypeHandle::BackReference(1),
10576 b"...",
10577 [
10578 Substitutable::UnresolvedType(
10579 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow)))
10580 ]
10581
10582 }
10583 }
10584 Err => {
10585 b"zzzzzzz" => Error::UnexpectedText,
10586 b"" => Error::UnexpectedEnd,
10587 }
10588 }
10589 });
10590 }
10591
10592 #[test]
10593 fn parse_unresolved_qualifier_level() {
10594 assert_parse!(UnresolvedQualifierLevel {
10595 with subs [
10596 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10597 ] => {
10598 Ok => {
10599 b"3abc..." => {
10600 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10601 start: 1,
10602 end: 4,
10603 }), None)),
10604 b"...",
10605 []
10606 }
10607 b"3abcIS_E..." => {
10608 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10609 start: 1,
10610 end: 4,
10611 }), Some(TemplateArgs(vec![
10612 TemplateArg::Type(TypeHandle::BackReference(0))
10613 ])))),
10614 b"...",
10615 []
10616 }
10617 }
10618 Err => {
10619 b"zzz" => Error::UnexpectedText,
10620 b"" => Error::UnexpectedEnd,
10621 }
10622 }
10623 });
10624 }
10625
10626 #[test]
10627 fn parse_simple_id() {
10628 assert_parse!(SimpleId {
10629 with subs [
10630 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10631 ] => {
10632 Ok => {
10633 b"3abc..." => {
10634 SimpleId(SourceName(Identifier {
10635 start: 1,
10636 end: 4,
10637 }), None),
10638 b"...",
10639 []
10640 }
10641 b"3abcIS_E..." => {
10642 SimpleId(SourceName(Identifier {
10643 start: 1,
10644 end: 4,
10645 }), Some(TemplateArgs(vec![
10646 TemplateArg::Type(TypeHandle::BackReference(0))
10647 ]))),
10648 b"...",
10649 []
10650 }
10651 }
10652 Err => {
10653 b"zzz" => Error::UnexpectedText,
10654 b"" => Error::UnexpectedEnd,
10655 }
10656 }
10657 });
10658 }
10659
10660 #[test]
10661 fn parse_base_unresolved_name() {
10662 assert_parse!(BaseUnresolvedName {
10663 with subs [
10664 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10665 ] => {
10666 Ok => {
10667 b"3abc..." => {
10668 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10669 start: 1,
10670 end: 4,
10671 }), None)),
10672 b"...",
10673 []
10674 }
10675 b"onnw..." => {
10676 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New), None),
10677 b"...",
10678 []
10679 }
10680 b"onnwIS_E..." => {
10681 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
10682 Some(TemplateArgs(vec![
10683 TemplateArg::Type(TypeHandle::BackReference(0))
10684 ]))),
10685 b"...",
10686 []
10687 }
10688 b"dn3abc..." => {
10689 BaseUnresolvedName::Destructor(DestructorName::Name(SimpleId(SourceName(Identifier {
10690 start: 3,
10691 end: 6,
10692 }), None))),
10693 b"...",
10694 []
10695 }
10696 }
10697 Err => {
10698 b"ozzz" => Error::UnexpectedText,
10699 b"dzzz" => Error::UnexpectedText,
10700 b"dn" => Error::UnexpectedEnd,
10701 b"on" => Error::UnexpectedEnd,
10702 b"" => Error::UnexpectedEnd,
10703 }
10704 }
10705 });
10706 }
10707
10708 #[test]
10709 fn parse_destructor_name() {
10710 assert_parse!(DestructorName {
10711 with subs [
10712 Substitutable::UnresolvedType(
10713 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10714 ] => {
10715 Ok => {
10716 b"S_..." => {
10717 DestructorName::Unresolved(UnresolvedTypeHandle::BackReference(0)),
10718 b"...",
10719 []
10720 }
10721 b"3abc..." => {
10722 DestructorName::Name(SimpleId(SourceName(Identifier {
10723 start: 1,
10724 end: 4,
10725 }), None)),
10726 b"...",
10727 []
10728 }
10729 }
10730 Err => {
10731 b"zzz" => Error::UnexpectedText,
10732 b"" => Error::UnexpectedEnd,
10733 }
10734 }
10735 });
10736 }
10737
10738 #[test]
10739 fn parse_expr_primary() {
10740 assert_parse!(ExprPrimary {
10741 with subs [
10742 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10743 ] => {
10744 Ok => {
10745 b"LS_12345E..." => {
10746 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 8),
10747 b"...",
10748 []
10749 }
10750 b"LS_E..." => {
10751 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3),
10752 b"...",
10753 []
10754 }
10755 b"L_Z3abcE..." => {
10756 ExprPrimary::External(
10757 MangledName::Encoding(
10758 Encoding::Data(
10759 Name::Unscoped(
10760 UnscopedName::Unqualified(
10761 UnqualifiedName::Source(
10762 SourceName(Identifier {
10763 start: 4,
10764 end: 7,
10765 }),
10766 AbiTags::default())))), vec![])),
10767 b"...",
10768 []
10769 }
10770 }
10771 Err => {
10772 b"zzz" => Error::UnexpectedText,
10773 b"LS_zzz" => Error::UnexpectedEnd,
10774 b"LS_12345" => Error::UnexpectedEnd,
10775 b"LS_" => Error::UnexpectedEnd,
10776 b"L" => Error::UnexpectedEnd,
10777 b"" => Error::UnexpectedEnd,
10778 }
10779 }
10780 });
10781 }
10782
10783 #[test]
10784 fn parse_initializer() {
10785 assert_parse!(Initializer {
10786 Ok => {
10787 b"piE..." => {
10788 Initializer(vec![]),
10789 b"..."
10790 }
10791 b"pitrtrtrE..." => {
10792 Initializer(vec![
10793 Expression::Rethrow,
10794 Expression::Rethrow,
10795 Expression::Rethrow,
10796 ]),
10797 b"..."
10798 }
10799 }
10800 Err => {
10801 b"pirtrtrt..." => Error::UnexpectedText,
10802 b"pi..." => Error::UnexpectedText,
10803 b"..." => Error::UnexpectedText,
10804 b"pirt" => Error::UnexpectedText,
10805 b"pi" => Error::UnexpectedEnd,
10806 b"p" => Error::UnexpectedEnd,
10807 b"" => Error::UnexpectedEnd,
10808 }
10809 });
10810 }
10811
10812 #[test]
10813 fn parse_local_name() {
10814 assert_parse!(LocalName {
10815 Ok => {
10816 b"Z3abcE3def_0..." => {
10817 LocalName::Relative(
10818 Box::new(Encoding::Data(
10819 Name::Unscoped(
10820 UnscopedName::Unqualified(
10821 UnqualifiedName::Source(
10822 SourceName(Identifier {
10823 start: 2,
10824 end: 5,
10825 }),
10826 AbiTags::default()))))),
10827 Some(Box::new(Name::Unscoped(
10828 UnscopedName::Unqualified(
10829 UnqualifiedName::Source(
10830 SourceName(Identifier {
10831 start: 7,
10832 end: 10,
10833 }),
10834 AbiTags::default()))))),
10835 Some(Discriminator(0))),
10836 b"..."
10837 }
10838 b"Z3abcE3def..." => {
10839 LocalName::Relative(
10840 Box::new(Encoding::Data(
10841 Name::Unscoped(
10842 UnscopedName::Unqualified(
10843 UnqualifiedName::Source(
10844 SourceName(Identifier {
10845 start: 2,
10846 end: 5,
10847 }),
10848 AbiTags::default()))))),
10849 Some(Box::new(Name::Unscoped(
10850 UnscopedName::Unqualified(
10851 UnqualifiedName::Source(
10852 SourceName(Identifier {
10853 start: 7,
10854 end: 10,
10855 }),
10856 AbiTags::default()))))),
10857 None),
10858 b"..."
10859 }
10860 b"Z3abcEs_0..." => {
10861 LocalName::Relative(
10862 Box::new(Encoding::Data(
10863 Name::Unscoped(
10864 UnscopedName::Unqualified(
10865 UnqualifiedName::Source(
10866 SourceName(Identifier {
10867 start: 2,
10868 end: 5,
10869 }),
10870 AbiTags::default()))))),
10871 None,
10872 Some(Discriminator(0))),
10873 b"..."
10874 }
10875 b"Z3abcEs..." => {
10876 LocalName::Relative(
10877 Box::new(Encoding::Data(
10878 Name::Unscoped(
10879 UnscopedName::Unqualified(
10880 UnqualifiedName::Source(
10881 SourceName(Identifier {
10882 start: 2,
10883 end: 5,
10884 }),
10885 AbiTags::default()))))),
10886 None,
10887 None),
10888 b"..."
10889 }
10890 b"Z3abcEd1_3abc..." => {
10891 LocalName::Default(
10892 Box::new(Encoding::Data(
10893 Name::Unscoped(
10894 UnscopedName::Unqualified(
10895 UnqualifiedName::Source(
10896 SourceName(Identifier {
10897 start: 2,
10898 end: 5,
10899 }),
10900 AbiTags::default()))))),
10901 Some(1),
10902 Box::new(Name::Unscoped(
10903 UnscopedName::Unqualified(
10904 UnqualifiedName::Source(
10905 SourceName(Identifier {
10906 start: 10,
10907 end: 13,
10908 }),
10909 AbiTags::default()))))),
10910 b"..."
10911 }
10912 b"Z3abcEd_3abc..." => {
10913 LocalName::Default(
10914 Box::new(Encoding::Data(
10915 Name::Unscoped(
10916 UnscopedName::Unqualified(
10917 UnqualifiedName::Source(
10918 SourceName(Identifier {
10919 start: 2,
10920 end: 5,
10921 }),
10922 AbiTags::default()))))),
10923 None,
10924 Box::new(Name::Unscoped(
10925 UnscopedName::Unqualified(
10926 UnqualifiedName::Source(
10927 SourceName(Identifier {
10928 start: 9,
10929 end: 12,
10930 }), AbiTags::default()))))),
10931 b"..."
10932 }
10933 }
10934 Err => {
10935 b"A" => Error::UnexpectedText,
10936 b"Z1a" => Error::UnexpectedEnd,
10937 b"Z1aE" => Error::UnexpectedEnd,
10938 b"Z" => Error::UnexpectedEnd,
10939 b"" => Error::UnexpectedEnd,
10940 }
10941 });
10942 }
10943
10944 #[test]
10945 fn parse_closure_type_name() {
10946 assert_parse!(ClosureTypeName {
10947 Ok => {
10948 b"UlvE_..." => {
10949 ClosureTypeName(LambdaSig(vec![]), None),
10950 b"..."
10951 }
10952 b"UlvE36_..." => {
10953 ClosureTypeName(LambdaSig(vec![]), Some(36)),
10954 b"..."
10955 }
10956 }
10957 Err => {
10958 b"UlvE36zzz" => Error::UnexpectedText,
10959 b"UlvEzzz" => Error::UnexpectedText,
10960 b"Ulvzzz" => Error::UnexpectedText,
10961 b"zzz" => Error::UnexpectedText,
10962 b"UlvE10" => Error::UnexpectedEnd,
10963 b"UlvE" => Error::UnexpectedEnd,
10964 b"Ulv" => Error::UnexpectedEnd,
10965 b"Ul" => Error::UnexpectedEnd,
10966 b"U" => Error::UnexpectedEnd,
10967 b"" => Error::UnexpectedEnd,
10968 }
10969 });
10970 }
10971
10972 #[test]
10973 fn parse_lambda_sig() {
10974 assert_parse!(LambdaSig {
10975 with subs [
10976 Substitutable::Type(
10977 Type::PointerTo(
10978 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool))))
10979 ] => {
10980 Ok => {
10981 b"v..." => {
10982 LambdaSig(vec![]),
10983 b"...",
10984 []
10985 }
10986 b"S_S_S_..." => {
10987 LambdaSig(vec![
10988 TypeHandle::BackReference(0),
10989 TypeHandle::BackReference(0),
10990 TypeHandle::BackReference(0),
10991 ]),
10992 b"...",
10993 []
10994 }
10995 }
10996 Err => {
10997 b"..." => Error::UnexpectedText,
10998 b"S" => Error::UnexpectedEnd,
10999 b"" => Error::UnexpectedEnd,
11000 }
11001 }
11002 });
11003 }
11004
11005 #[test]
11006 fn parse_substitution() {
11007 assert_parse!(Substitution {
11008 with subs [
11009 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
11010 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
11011 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
11012 ] => {
11013 Ok => {
11014 b"S_..." => {
11015 Substitution::BackReference(0),
11016 b"...",
11017 []
11018 }
11019 b"S1_..." => {
11020 Substitution::BackReference(2),
11021 b"...",
11022 []
11023 }
11024 b"St..." => {
11025 Substitution::WellKnown(WellKnownComponent::Std),
11026 b"...",
11027 []
11028 }
11029 b"Sa..." => {
11030 Substitution::WellKnown(WellKnownComponent::StdAllocator),
11031 b"...",
11032 []
11033 }
11034 b"Sb..." => {
11035 Substitution::WellKnown(WellKnownComponent::StdString1),
11036 b"...",
11037 []
11038 }
11039 b"Ss..." => {
11040 Substitution::WellKnown(WellKnownComponent::StdString2),
11041 b"...",
11042 []
11043 }
11044 b"Si..." => {
11045 Substitution::WellKnown(WellKnownComponent::StdIstream),
11046 b"...",
11047 []
11048 }
11049 b"So..." => {
11050 Substitution::WellKnown(WellKnownComponent::StdOstream),
11051 b"...",
11052 []
11053 }
11054 b"Sd..." => {
11055 Substitution::WellKnown(WellKnownComponent::StdIostream),
11056 b"...",
11057 []
11058 }
11059 }
11060 Err => {
11061 b"S999_" => Error::BadBackReference,
11062 b"Sz" => Error::UnexpectedText,
11063 b"zzz" => Error::UnexpectedText,
11064 b"S1" => Error::UnexpectedEnd,
11065 b"S" => Error::UnexpectedEnd,
11066 b"" => Error::UnexpectedEnd,
11067 }
11068 }
11069 });
11070 }
11071
11072 #[test]
11073 fn parse_special_name() {
11074 assert_parse!(SpecialName {
11075 Ok => {
11076 b"TVi..." => {
11077 SpecialName::VirtualTable(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11078 b"..."
11079 }
11080 b"TTi..." => {
11081 SpecialName::Vtt(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11082 b"..."
11083 }
11084 b"TIi..." => {
11085 SpecialName::Typeinfo(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11086 b"..."
11087 }
11088 b"TSi..." => {
11089 SpecialName::TypeinfoName(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11090 b"..."
11091 }
11092 b"Tv42_36_3abc..." => {
11093 SpecialName::VirtualOverrideThunk(
11094 CallOffset::Virtual(VOffset(42, 36)),
11095 Box::new(Encoding::Data(
11096 Name::Unscoped(
11097 UnscopedName::Unqualified(
11098 UnqualifiedName::Source(
11099 SourceName(Identifier {
11100 start: 9,
11101 end: 12,
11102 }), AbiTags::default())))))),
11103 b"..."
11104 }
11105 b"Tcv42_36_v42_36_3abc..." => {
11106 SpecialName::VirtualOverrideThunkCovariant(
11107 CallOffset::Virtual(VOffset(42, 36)),
11108 CallOffset::Virtual(VOffset(42, 36)),
11109 Box::new(Encoding::Data(
11110 Name::Unscoped(
11111 UnscopedName::Unqualified(
11112 UnqualifiedName::Source(
11113 SourceName(Identifier {
11114 start: 17,
11115 end: 20,
11116 }), AbiTags::default())))))),
11117 b"..."
11118 }
11119 b"GV3abc..." => {
11120 SpecialName::Guard(
11121 Name::Unscoped(
11122 UnscopedName::Unqualified(
11123 UnqualifiedName::Source(
11124 SourceName(Identifier {
11125 start: 3,
11126 end: 6,
11127 }), AbiTags::default())))),
11128 b"..."
11129 }
11130 b"GR3abc_..." => {
11131 SpecialName::GuardTemporary(
11132 Name::Unscoped(
11133 UnscopedName::Unqualified(
11134 UnqualifiedName::Source(
11135 SourceName(Identifier {
11136 start: 3,
11137 end: 6,
11138 }),
11139 AbiTags::default()))),
11140 0),
11141 b"..."
11142 }
11143 b"GR3abc0_..." => {
11144 SpecialName::GuardTemporary(
11145 Name::Unscoped(
11146 UnscopedName::Unqualified(
11147 UnqualifiedName::Source(
11148 SourceName(Identifier {
11149 start: 3,
11150 end: 6,
11151 }),
11152 AbiTags::default()))),
11153 1),
11154 b"..."
11155 }
11156 b"Gr4_abc..." => {
11157 SpecialName::JavaResource(vec![ResourceName {
11158 start: 4,
11159 end: 7,
11160 }]),
11161 b"..."
11162 }
11163 b"TCc7_i..." => {
11164 SpecialName::ConstructionVtable(
11165 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
11166 7,
11167 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
11168 ),
11169 b"..."
11170 }
11171 b"TFi..." => {
11172 SpecialName::TypeinfoFunction(
11173 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11174 b"..."
11175 }
11176 b"TH4name..." => {
11177 SpecialName::TlsInit(
11178 Name::Unscoped(
11179 UnscopedName::Unqualified(
11180 UnqualifiedName::Source(
11181 SourceName(Identifier { start: 3, end: 7 }),
11182 AbiTags::default())))),
11183 b"..."
11184 }
11185 b"TW4name..." => {
11186 SpecialName::TlsWrapper(
11187 Name::Unscoped(
11188 UnscopedName::Unqualified(
11189 UnqualifiedName::Source(
11190 SourceName(Identifier { start: 3, end: 7 }),
11191 AbiTags::default())))),
11192 b"..."
11193 }
11194 }
11195 Err => {
11196 b"TZ" => Error::UnexpectedText,
11197 b"GZ" => Error::UnexpectedText,
11198 b"GR3abcz" => Error::UnexpectedText,
11199 b"GR3abc0z" => Error::UnexpectedText,
11200 b"T" => Error::UnexpectedEnd,
11201 b"G" => Error::UnexpectedEnd,
11202 b"" => Error::UnexpectedEnd,
11203 b"GR3abc" => Error::UnexpectedEnd,
11204 b"GR3abc0" => Error::UnexpectedEnd,
11205 b"TCcn7_i..." => Error::UnexpectedText,
11207 b"Gr3abc0" => Error::UnexpectedText,
11208 }
11209 });
11210 }
11211
11212 #[test]
11213 fn parse_function_param() {
11214 assert_parse!(FunctionParam {
11215 Ok => {
11216 b"fpK_..." => {
11217 FunctionParam(0,
11218 CvQualifiers {
11219 restrict: false,
11220 volatile: false,
11221 const_: true,
11222 },
11223 Some(0)),
11224 b"..."
11225 }
11226 b"fL1pK_..." => {
11227 FunctionParam(1,
11228 CvQualifiers {
11229 restrict: false,
11230 volatile: false,
11231 const_: true,
11232 },
11233 Some(0)),
11234 b"..."
11235 }
11236 b"fpK3_..." => {
11237 FunctionParam(0,
11238 CvQualifiers {
11239 restrict: false,
11240 volatile: false,
11241 const_: true,
11242 },
11243 Some(4)),
11244 b"..."
11245 }
11246 b"fL1pK4_..." => {
11247 FunctionParam(1,
11248 CvQualifiers {
11249 restrict: false,
11250 volatile: false,
11251 const_: true,
11252 },
11253 Some(5)),
11254 b"..."
11255 }
11256 }
11257 Err => {
11258 b"fz" => Error::UnexpectedText,
11259 b"fLp_" => Error::UnexpectedText,
11260 b"fpL_" => Error::UnexpectedText,
11261 b"fL1pK4z" => Error::UnexpectedText,
11262 b"fL1pK4" => Error::UnexpectedEnd,
11263 b"fL1p" => Error::UnexpectedEnd,
11264 b"fL1" => Error::UnexpectedEnd,
11265 b"fL" => Error::UnexpectedEnd,
11266 b"f" => Error::UnexpectedEnd,
11267 b"" => Error::UnexpectedEnd,
11268 }
11269 });
11270 }
11271
11272 #[test]
11273 fn parse_discriminator() {
11274 assert_parse!(Discriminator {
11275 Ok => {
11276 b"_0..." => {
11277 Discriminator(0),
11278 b"..."
11279 }
11280 b"_9..." => {
11281 Discriminator(9),
11282 b"..."
11283 }
11284 b"__99_..." => {
11285 Discriminator(99),
11286 b"..."
11287 }
11288 }
11289 Err => {
11290 b"_n1" => Error::UnexpectedText,
11291 b"__99..." => Error::UnexpectedText,
11292 b"__99" => Error::UnexpectedEnd,
11293 b"..." => Error::UnexpectedText,
11294 }
11295 });
11296 }
11297
11298 #[test]
11299 fn parse_data_member_prefix() {
11300 assert_parse!(DataMemberPrefix {
11301 Ok => {
11302 b"3fooM..." => {
11303 DataMemberPrefix(SourceName(Identifier {
11304 start: 1,
11305 end: 4,
11306 })),
11307 b"..."
11308 }
11309 }
11310 Err => {
11311 b"zzz" => Error::UnexpectedText,
11312 b"1" => Error::UnexpectedEnd,
11313 b"" => Error::UnexpectedEnd,
11314 }
11315 });
11316 }
11317
11318 #[test]
11319 fn parse_ref_qualifier() {
11320 assert_parse!(RefQualifier {
11321 Ok => {
11322 b"R..." => {
11323 RefQualifier::LValueRef,
11324 b"..."
11325 }
11326 b"O..." => {
11327 RefQualifier::RValueRef,
11328 b"..."
11329 }
11330 }
11331 Err => {
11332 b"..." => Error::UnexpectedText,
11333 b"" => Error::UnexpectedEnd,
11334 }
11335 });
11336 }
11337
11338 #[test]
11339 fn parse_cv_qualifiers() {
11340 assert_parse!(CvQualifiers {
11341 Ok => {
11342 b"" => {
11343 CvQualifiers { restrict: false, volatile: false, const_: false },
11344 b""
11345 }
11346 b"..." => {
11347 CvQualifiers { restrict: false, volatile: false, const_: false },
11348 b"..."
11349 }
11350 b"r..." => {
11351 CvQualifiers { restrict: true, volatile: false, const_: false },
11352 b"..."
11353 }
11354 b"rV..." => {
11355 CvQualifiers { restrict: true, volatile: true, const_: false },
11356 b"..."
11357 }
11358 b"rVK..." => {
11359 CvQualifiers { restrict: true, volatile: true, const_: true },
11360 b"..."
11361 }
11362 b"V" => {
11363 CvQualifiers { restrict: false, volatile: true, const_: false },
11364 b""
11365 }
11366 b"VK" => {
11367 CvQualifiers { restrict: false, volatile: true, const_: true },
11368 b""
11369 }
11370 b"K..." => {
11371 CvQualifiers { restrict: false, volatile: false, const_: true },
11372 b"..."
11373 }
11374 }
11375 Err => {
11376 }
11378 });
11379 }
11380
11381 #[test]
11382 fn parse_builtin_type() {
11383 assert_parse!(BuiltinType {
11384 Ok => {
11385 b"c..." => {
11386 BuiltinType::Standard(StandardBuiltinType::Char),
11387 b"..."
11388 }
11389 b"c" => {
11390 BuiltinType::Standard(StandardBuiltinType::Char),
11391 b""
11392 }
11393 b"u3abc..." => {
11394 BuiltinType::Extension(SourceName(Identifier {
11395 start: 2,
11396 end: 5,
11397 })),
11398 b"..."
11399 }
11400 b"DF16b..." => {
11401 BuiltinType::Standard(StandardBuiltinType::BFloat16),
11402 b"..."
11403 }
11404 }
11405 Err => {
11406 b"." => Error::UnexpectedText,
11407 b"" => Error::UnexpectedEnd,
11408 }
11409 });
11410 }
11411
11412 #[test]
11413 fn parse_parametric_builtin_type() {
11414 assert_parse!(BuiltinType {
11415 Ok => {
11416 b"DB8_..." => {
11417 BuiltinType::Parametric(ParametricBuiltinType::SignedBitInt(8)),
11418 b"..."
11419 }
11420 b"DUsZT_" => {
11421 BuiltinType::Parametric(ParametricBuiltinType::UnsignedBitIntExpression(Box::new(Expression::SizeofTemplatePack(TemplateParam(0))))),
11422 b""
11423 }
11424 b"DF128_..." => {
11425 BuiltinType::Parametric(ParametricBuiltinType::FloatN(128)),
11426 b"..."
11427 }
11428 b"DF256x..." => {
11429 BuiltinType::Parametric(ParametricBuiltinType::FloatNx(256)),
11430 b"..."
11431 }
11432 }
11433 Err => {
11434 b"DB100000000000000000000000_" => Error::Overflow,
11435 b"DFsZT_" => Error::UnexpectedText,
11436 b"DB" => Error::UnexpectedEnd,
11437 b"DB32" => Error::UnexpectedEnd,
11438 }
11439 });
11440 }
11441
11442 #[test]
11443 fn parse_template_param() {
11444 assert_parse!(TemplateParam {
11445 Ok => {
11446 b"T_..." => {
11447 TemplateParam(0),
11448 b"..."
11449 }
11450 b"T3_..." => {
11451 TemplateParam(4),
11452 b"..."
11453 }
11454 }
11455 Err => {
11456 b"wtf" => Error::UnexpectedText,
11457 b"Twtf" => Error::UnexpectedText,
11458 b"T3wtf" => Error::UnexpectedText,
11459 b"T" => Error::UnexpectedEnd,
11460 b"T3" => Error::UnexpectedEnd,
11461 b"" => Error::UnexpectedEnd,
11462 }
11463 });
11464 }
11465
11466 #[test]
11467 fn parse_unscoped_name() {
11468 assert_parse!(UnscopedName {
11469 Ok => {
11470 b"St5hello..." => {
11471 UnscopedName::Std(UnqualifiedName::Source(SourceName(Identifier {
11472 start: 3,
11473 end: 8,
11474 }),
11475 AbiTags::default())),
11476 b"..."
11477 }
11478 b"5hello..." => {
11479 UnscopedName::Unqualified(UnqualifiedName::Source(SourceName(Identifier {
11480 start: 1,
11481 end: 6,
11482 }), AbiTags::default())),
11483 b"..."
11484 }
11485 }
11486 Err => {
11487 b"St..." => Error::UnexpectedText,
11488 b"..." => Error::UnexpectedText,
11489 b"" => Error::UnexpectedEnd,
11490 }
11491 });
11492 }
11493
11494 #[test]
11495 fn parse_unqualified_name() {
11496 assert_parse!(UnqualifiedName {
11503 Ok => {
11504 b"qu.." => {
11505 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question), AbiTags::default()),
11506 b".."
11507 }
11508 b"C1.." => {
11509 UnqualifiedName::CtorDtor(CtorDtorName::CompleteConstructor(None), AbiTags::default()),
11510 b".."
11511 }
11512 b"10abcdefghij..." => {
11513 UnqualifiedName::Source(SourceName(Identifier {
11514 start: 2,
11515 end: 12,
11516 }), AbiTags::default()),
11517 b"..."
11518 }
11519 b"UllE_..." => {
11520 UnqualifiedName::ClosureType(
11521 ClosureTypeName(
11522 LambdaSig(vec![
11523 TypeHandle::Builtin(
11524 BuiltinType::Standard(
11525 StandardBuiltinType::Long))
11526 ]),
11527 None),
11528 AbiTags::default()),
11529 b"..."
11530 }
11531 b"Ut5_..." => {
11532 UnqualifiedName::UnnamedType(UnnamedTypeName(Some(5)), AbiTags::default()),
11533 b"..."
11534 }
11535 b"L3foo_0..." => {
11536 UnqualifiedName::LocalSourceName(
11537 SourceName(Identifier {
11538 start: 2,
11539 end: 5
11540 }),
11541 Some(Discriminator(0)),
11542 AbiTags::default(),
11543 ),
11544 "..."
11545 }
11546 b"L3foo..." => {
11547 UnqualifiedName::LocalSourceName(
11548 SourceName(Identifier {
11549 start: 2,
11550 end: 5
11551 }),
11552 None,
11553 AbiTags::default(),
11554 ),
11555 "..."
11556 }
11557 b"quB1Q.." => {
11558 UnqualifiedName::Operator(
11559 OperatorName::Simple(SimpleOperatorName::Question),
11560 AbiTags(vec![AbiTag(
11561 SourceName(
11562 Identifier {
11563 start: 4,
11564 end: 5,
11565 },
11566 ),
11567 )])
11568 ),
11569 b".."
11570 }
11571 b"C1B1Q.." => {
11572 UnqualifiedName::CtorDtor(
11573 CtorDtorName::CompleteConstructor(None),
11574 AbiTags(vec![AbiTag(
11575 SourceName(
11576 Identifier {
11577 start: 4,
11578 end: 5,
11579 },
11580 ),
11581 )])
11582 ),
11583 b".."
11584 }
11585 b"10abcdefghijB1QB2lp..." => {
11586 UnqualifiedName::Source(
11587 SourceName(Identifier {
11588 start: 2,
11589 end: 12,
11590 }),
11591 AbiTags(vec![
11592 AbiTag(
11593 SourceName(
11594 Identifier {
11595 start: 14,
11596 end: 15,
11597 },
11598 ),
11599 ),
11600 AbiTag(
11601 SourceName(
11602 Identifier {
11603 start: 17,
11604 end: 19,
11605 },
11606 ),
11607 ),
11608 ])
11609 ),
11610 b"..."
11611 }
11612 b"UllE_B1Q..." => {
11613 UnqualifiedName::ClosureType(
11614 ClosureTypeName(
11615 LambdaSig(vec![
11616 TypeHandle::Builtin(
11617 BuiltinType::Standard(
11618 StandardBuiltinType::Long))
11619 ]),
11620 None),
11621 AbiTags(vec![AbiTag(
11622 SourceName(
11623 Identifier {
11624 start: 7,
11625 end: 8,
11626 },
11627 ),
11628 )])
11629 ),
11630 b"..."
11631 }
11632 b"Ut5_B1QB2lp..." => {
11633 UnqualifiedName::UnnamedType(
11634 UnnamedTypeName(Some(5)),
11635 AbiTags(vec![
11636 AbiTag(
11637 SourceName(
11638 Identifier {
11639 start: 6,
11640 end: 7,
11641 },
11642 ),
11643 ),
11644 AbiTag(
11645 SourceName(
11646 Identifier {
11647 start: 9,
11648 end: 11,
11649 },
11650 ),
11651 ),
11652 ])
11653 ),
11654 b"..."
11655 }
11656 b"L3foo_0B1Q..." => {
11657 UnqualifiedName::LocalSourceName(
11658 SourceName(Identifier {
11659 start: 2,
11660 end: 5
11661 }),
11662 Some(Discriminator(0)),
11663 AbiTags(vec![AbiTag(
11664 SourceName(
11665 Identifier {
11666 start: 9,
11667 end: 10,
11668 },
11669 ),
11670 )])
11671 ),
11672 "..."
11673 }
11674 b"L3fooB1QB2lp..." => {
11675 UnqualifiedName::LocalSourceName(
11676 SourceName(Identifier {
11677 start: 2,
11678 end: 5
11679 }),
11680 None,
11681 AbiTags(vec![
11682 AbiTag(
11683 SourceName(
11684 Identifier {
11685 start: 7,
11686 end: 8,
11687 },
11688 ),
11689 ),
11690 AbiTag(
11691 SourceName(
11692 Identifier {
11693 start: 10,
11694 end: 12,
11695 },
11696 ),
11697 )
11698 ])
11699 ),
11700 "..."
11701 }
11702 }
11703 Err => {
11704 b"zzz" => Error::UnexpectedText,
11705 b"Uq" => Error::UnexpectedText,
11706 b"C" => Error::UnexpectedEnd,
11707 b"" => Error::UnexpectedEnd,
11708 }
11709 });
11710 }
11711
11712 #[test]
11713 fn parse_unnamed_type_name() {
11714 assert_parse!(UnnamedTypeName {
11715 Ok => {
11716 b"Ut_abc" => {
11717 UnnamedTypeName(None),
11718 b"abc"
11719 }
11720 b"Ut42_abc" => {
11721 UnnamedTypeName(Some(42)),
11722 b"abc"
11723 }
11724 b"Ut42_" => {
11725 UnnamedTypeName(Some(42)),
11726 b""
11727 }
11728 }
11729 Err => {
11730 b"ut_" => Error::UnexpectedText,
11731 b"u" => Error::UnexpectedEnd,
11732 b"Ut" => Error::UnexpectedEnd,
11733 b"Ut._" => Error::UnexpectedText,
11734 b"Ut42" => Error::UnexpectedEnd,
11735 }
11736 });
11737 }
11738
11739 #[test]
11740 fn parse_identifier() {
11741 assert_parse!(Identifier {
11742 Ok => {
11743 b"1abc" => {
11744 Identifier { start: 0, end: 4 },
11745 b""
11746 }
11747 b"_Az1\0\0\0" => {
11748 Identifier { start: 0, end: 4 },
11749 b"\0\0\0"
11750 }
11751 b"$_0\0\0\0" => {
11752 Identifier { start: 0, end: 3 },
11753 b"\0\0\0"
11754 }
11755 }
11756 Err => {
11757 b"\0\0\0" => Error::UnexpectedText,
11758 b"" => Error::UnexpectedEnd,
11759 }
11760 });
11761 }
11762
11763 #[test]
11764 fn parse_source_name() {
11765 assert_parse!(SourceName {
11766 Ok => {
11767 b"1abc" => {
11768 SourceName(Identifier { start: 1, end: 2 }),
11769 b"bc"
11770 }
11771 b"10abcdefghijklm" => {
11772 SourceName(Identifier { start: 2, end: 12 }),
11773 b"klm"
11774 }
11775 }
11776 Err => {
11777 b"0abc" => Error::UnexpectedText,
11778 b"n1abc" => Error::UnexpectedText,
11779 b"10abcdef" => Error::UnexpectedEnd,
11780 b"" => Error::UnexpectedEnd,
11781 }
11782 });
11783 }
11784
11785 #[test]
11786 fn parse_number() {
11787 assert_parse!(Number {
11788 Ok => {
11789 b"n2n3" => {
11790 -2,
11791 b"n3"
11792 }
11793 b"12345abcdef" => {
11794 12345,
11795 b"abcdef"
11796 }
11797 b"0abcdef" => {
11798 0,
11799 b"abcdef"
11800 }
11801 b"42" => {
11802 42,
11803 b""
11804 }
11805 }
11806 Err => {
11807 b"001" => Error::UnexpectedText,
11808 b"wutang" => Error::UnexpectedText,
11809 b"n" => Error::UnexpectedEnd,
11810 b"" => Error::UnexpectedEnd,
11811 }
11812 });
11813 }
11814
11815 #[test]
11816 fn parse_call_offset() {
11817 assert_parse!(CallOffset {
11818 Ok => {
11819 b"hn42_..." => {
11820 CallOffset::NonVirtual(NvOffset(-42)),
11821 b"..."
11822 }
11823 b"vn42_36_..." => {
11824 CallOffset::Virtual(VOffset(-42, 36)),
11825 b"..."
11826 }
11827 }
11828 Err => {
11829 b"h1..." => Error::UnexpectedText,
11830 b"v1_1..." => Error::UnexpectedText,
11831 b"hh" => Error::UnexpectedText,
11832 b"vv" => Error::UnexpectedText,
11833 b"z" => Error::UnexpectedText,
11834 b"" => Error::UnexpectedEnd,
11835 }
11836 });
11837 }
11838
11839 #[test]
11840 fn parse_v_offset() {
11841 assert_parse!(VOffset {
11842 Ok => {
11843 b"n2_n3abcdef" => {
11844 VOffset(-2, -3),
11845 b"abcdef"
11846 }
11847 b"12345_12345abcdef" => {
11848 VOffset(12345, 12345),
11849 b"abcdef"
11850 }
11851 b"0_0abcdef" => {
11852 VOffset(0, 0),
11853 b"abcdef"
11854 }
11855 b"42_n3" => {
11856 VOffset(42, -3),
11857 b""
11858 }
11859 }
11860 Err => {
11861 b"001" => Error::UnexpectedText,
11862 b"1_001" => Error::UnexpectedText,
11863 b"wutang" => Error::UnexpectedText,
11864 b"n_" => Error::UnexpectedText,
11865 b"1_n" => Error::UnexpectedEnd,
11866 b"1_" => Error::UnexpectedEnd,
11867 b"n" => Error::UnexpectedEnd,
11868 b"" => Error::UnexpectedEnd,
11869 }
11870 });
11871 }
11872
11873 #[test]
11874 fn parse_nv_offset() {
11875 assert_parse!(NvOffset {
11876 Ok => {
11877 b"n2n3" => {
11878 NvOffset(-2),
11879 b"n3"
11880 }
11881 b"12345abcdef" => {
11882 NvOffset(12345),
11883 b"abcdef"
11884 }
11885 b"0abcdef" => {
11886 NvOffset(0),
11887 b"abcdef"
11888 }
11889 b"42" => {
11890 NvOffset(42),
11891 b""
11892 }
11893 }
11894 Err => {
11895 b"001" => Error::UnexpectedText,
11896 b"wutang" => Error::UnexpectedText,
11897 b"" => Error::UnexpectedEnd,
11898 }
11899 });
11900 }
11901
11902 #[test]
11903 fn parse_seq_id() {
11904 assert_parse!(SeqId {
11905 Ok => {
11906 b"1_" => {
11907 SeqId(1),
11908 b"_"
11909 }
11910 b"42" => {
11911 SeqId(146),
11912 b""
11913 }
11914 b"ABCabc" => {
11915 SeqId(13368),
11916 b"abc"
11917 }
11918 }
11919 Err => {
11920 b"abc" => Error::UnexpectedText,
11921 b"001" => Error::UnexpectedText,
11922 b"wutang" => Error::UnexpectedText,
11923 b"" => Error::UnexpectedEnd,
11924 }
11925 });
11926 }
11927
11928 #[test]
11929 fn parse_ctor_dtor_name() {
11930 assert_parse!(CtorDtorName {
11931 Ok => {
11932 b"D0" => {
11933 CtorDtorName::DeletingDestructor,
11934 b""
11935 }
11936 b"C101" => {
11937 CtorDtorName::CompleteConstructor(None),
11938 b"01"
11939 }
11940 }
11941 Err => {
11942 b"gayagaya" => Error::UnexpectedText,
11943 b"C" => Error::UnexpectedEnd,
11944 b"" => Error::UnexpectedEnd,
11945 }
11946 });
11947 }
11948
11949 #[test]
11950 fn parse_operator_name() {
11951 assert_parse!(OperatorName {
11952 Ok => {
11953 b"qu..." => {
11954 OperatorName::Simple(SimpleOperatorName::Question),
11955 b"..."
11956 }
11957 b"cvi..." => {
11958 OperatorName::Conversion(
11959 TypeHandle::Builtin(
11960 BuiltinType::Standard(
11961 StandardBuiltinType::Int))),
11962 b"..."
11963 }
11964 b"li3Foo..." => {
11965 OperatorName::Literal(SourceName(Identifier {
11966 start: 3,
11967 end: 6,
11968 })),
11969 b"..."
11970 }
11971 b"v33Foo..." => {
11972 OperatorName::VendorExtension(3, SourceName(Identifier {
11973 start: 3,
11974 end: 6
11975 })),
11976 b"..."
11977 }
11978 }
11979 Err => {
11980 b"cv" => Error::UnexpectedEnd,
11981 b"li3ab" => Error::UnexpectedEnd,
11982 b"li" => Error::UnexpectedEnd,
11983 b"v33ab" => Error::UnexpectedEnd,
11984 b"v3" => Error::UnexpectedEnd,
11985 b"v" => Error::UnexpectedEnd,
11986 b"" => Error::UnexpectedEnd,
11987 b"q" => Error::UnexpectedText,
11988 b"c" => Error::UnexpectedText,
11989 b"l" => Error::UnexpectedText,
11990 b"zzz" => Error::UnexpectedText,
11991 }
11992 });
11993 }
11994
11995 #[test]
11996 fn parse_simple_operator_name() {
11997 assert_parse!(SimpleOperatorName {
11998 Ok => {
11999 b"qu" => {
12000 SimpleOperatorName::Question,
12001 b""
12002 }
12003 b"quokka" => {
12004 SimpleOperatorName::Question,
12005 b"okka"
12006 }
12007 }
12008 Err => {
12009 b"bu-buuuu" => Error::UnexpectedText,
12010 b"q" => Error::UnexpectedEnd,
12011 b"" => Error::UnexpectedEnd,
12012 }
12013 });
12014 }
12015
12016 #[test]
12017 fn parse_subobject_expr() {
12018 assert_parse!(SubobjectExpr {
12019 with subs [] => {
12020 Ok => {
12021 "PKcL_Z3FooEE..." => {
12022 SubobjectExpr {
12023 ty: TypeHandle::BackReference(1),
12024 expr: Box::new(Expression::Primary(
12025 ExprPrimary::External(
12026 MangledName::Encoding(
12027 Encoding::Data(
12028 Name::Unscoped(
12029 UnscopedName::Unqualified(
12030 UnqualifiedName::Source(
12031 SourceName(
12032 Identifier {
12033 start: 7,
12034 end: 10,
12035 }
12036 ),
12037 AbiTags::default()
12038 )
12039 )
12040 )
12041 ),
12042 vec![]
12043 )
12044 )
12045 )),
12046 offset: 0,
12047 },
12048 b"...",
12049 [
12050 Substitutable::Type(
12051 Type::Qualified(
12052 CvQualifiers {
12053 restrict: false,
12054 volatile: false,
12055 const_: true,
12056 },
12057 TypeHandle::Builtin(
12058 BuiltinType::Standard(
12059 StandardBuiltinType::Char,
12060 ),
12061 ),
12062 )
12063 ),
12064 Substitutable::Type(
12065 Type::PointerTo(
12066 TypeHandle::BackReference(
12067 0,
12068 ),
12069 ),
12070 )
12071 ]
12072 }
12073 }
12074 Err => {
12075 "" => Error::UnexpectedEnd,
12076 "" => Error::UnexpectedEnd,
12077 }
12078 }
12079 });
12080 }
12081}