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 UnqualifiedName::starts_with(c, &tail) => {
2339 let (name, tail_tail) = UnqualifiedName::parse(ctx, subs, tail)?;
2347 if tail_tail.peek() == Some(b'M') {
2348 let prefix = match current {
2352 None => Prefix::Unqualified(name),
2353 Some(current) => {
2354 let name = match name {
2355 UnqualifiedName::Source(name, _) => name,
2356 UnqualifiedName::LocalSourceName(name, ..) => name,
2357 _ => return Err(error::Error::UnexpectedText),
2358 };
2359 Prefix::DataMember(current, DataMemberPrefix(name))
2360 }
2361 };
2362 current = Some(save(subs, prefix, tail_tail));
2363 tail = consume(b"M", tail_tail).unwrap();
2364 } else {
2365 let prefix = match current {
2366 None => Prefix::Unqualified(name),
2367 Some(handle) => Prefix::Nested(handle, name),
2368 };
2369 current = Some(save(subs, prefix, tail_tail));
2370 tail = tail_tail;
2371 }
2372 }
2373 Some(_) => {
2374 if let Some(handle) = current {
2375 return Ok((handle, tail));
2376 } else if tail.is_empty() {
2377 return Err(error::Error::UnexpectedEnd);
2378 } else {
2379 return Err(error::Error::UnexpectedText);
2380 }
2381 }
2382 }
2383 }
2384 }
2385}
2386
2387impl<'a> GetLeafName<'a> for Prefix {
2388 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2389 match *self {
2390 Prefix::Nested(ref prefix, ref name) => name
2391 .get_leaf_name(subs)
2392 .or_else(|| prefix.get_leaf_name(subs)),
2393 Prefix::Unqualified(ref name) => name.get_leaf_name(subs),
2394 Prefix::Template(ref prefix, _) => prefix.get_leaf_name(subs),
2395 Prefix::DataMember(_, ref name) => name.get_leaf_name(subs),
2396 Prefix::TemplateParam(_) | Prefix::Decltype(_) => None,
2397 }
2398 }
2399}
2400
2401impl GetTemplateArgs for PrefixHandle {
2402 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
2405 match *self {
2406 PrefixHandle::BackReference(idx) => {
2407 if let Some(&Substitutable::Prefix(ref p)) = subs.get(idx) {
2408 p.get_template_args(subs)
2409 } else {
2410 None
2411 }
2412 }
2413 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2414 if let Some(&Substitutable::Prefix(ref p)) = subs.get_non_substitution(idx) {
2415 p.get_template_args(subs)
2416 } else {
2417 None
2418 }
2419 }
2420 _ => None,
2421 }
2422 }
2423}
2424
2425impl<'subs, W> Demangle<'subs, W> for Prefix
2426where
2427 W: 'subs + DemangleWrite,
2428{
2429 fn demangle<'prev, 'ctx>(
2430 &'subs self,
2431 ctx: &'ctx mut DemangleContext<'subs, W>,
2432 scope: Option<ArgScopeStack<'prev, 'subs>>,
2433 ) -> fmt::Result {
2434 let ctx = try_begin_demangle!(self, ctx, scope);
2435 if ctx.is_template_prefix {
2436 ctx.push_demangle_node(DemangleNodeType::TemplatePrefix);
2437 ctx.is_template_prefix = false;
2438 } else if ctx.is_template_prefix_in_nested_name {
2439 ctx.push_demangle_node(DemangleNodeType::NestedName);
2440 ctx.is_template_prefix_in_nested_name = false;
2441 } else {
2442 ctx.push_demangle_node(DemangleNodeType::Prefix);
2443 }
2444
2445 let ret = match *self {
2446 Prefix::Unqualified(ref unqualified) => unqualified.demangle(ctx, scope),
2447 Prefix::Nested(ref prefix, ref unqualified) => {
2448 prefix.demangle(ctx, scope)?;
2449 write!(ctx, "::")?;
2450 unqualified.demangle(ctx, scope)
2451 }
2452 Prefix::Template(ref prefix, ref args) => {
2453 ctx.is_template_prefix = true;
2454 prefix.demangle(ctx, scope)?;
2455 ctx.is_template_prefix = false;
2456 args.demangle(ctx, scope)
2457 }
2458 Prefix::TemplateParam(ref param) => param.demangle(ctx, scope),
2459 Prefix::Decltype(ref dt) => dt.demangle(ctx, scope),
2460 Prefix::DataMember(ref prefix, ref member) => {
2461 prefix.demangle(ctx, scope)?;
2462 write!(ctx, "::")?;
2463 member.demangle(ctx, scope)
2464 }
2465 };
2466 ctx.pop_demangle_node();
2467 ret
2468 }
2469}
2470
2471impl IsCtorDtorConversion for Prefix {
2472 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2473 match *self {
2474 Prefix::Unqualified(ref unqualified) | Prefix::Nested(_, ref unqualified) => {
2475 unqualified.is_ctor_dtor_conversion(subs)
2476 }
2477 Prefix::Template(ref prefix, _) => prefix.is_ctor_dtor_conversion(subs),
2478 _ => false,
2479 }
2480 }
2481}
2482
2483impl IsCtorDtorConversion for PrefixHandle {
2484 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
2485 match *self {
2486 PrefixHandle::BackReference(idx) => {
2487 if let Some(sub) = subs.get(idx) {
2488 sub.is_ctor_dtor_conversion(subs)
2489 } else {
2490 false
2491 }
2492 }
2493 PrefixHandle::NonSubstitution(NonSubstitution(idx)) => {
2494 if let Some(sub) = subs.get_non_substitution(idx) {
2495 sub.is_ctor_dtor_conversion(subs)
2496 } else {
2497 false
2498 }
2499 }
2500 PrefixHandle::WellKnown(_) => false,
2501 }
2502 }
2503}
2504
2505impl PrefixHandle {
2506 fn is_template_prefix(&self) -> bool {
2509 match *self {
2510 PrefixHandle::BackReference(_) | PrefixHandle::WellKnown(_) => true,
2511 PrefixHandle::NonSubstitution(_) => false,
2512 }
2513 }
2514}
2515
2516#[derive(Clone, Debug, PartialEq, Eq)]
2531pub enum UnqualifiedName {
2532 Operator(OperatorName, AbiTags),
2534 CtorDtor(CtorDtorName, AbiTags),
2536 Source(SourceName, AbiTags),
2538 LocalSourceName(SourceName, Option<Discriminator>, AbiTags),
2540 UnnamedType(UnnamedTypeName, AbiTags),
2542 ClosureType(ClosureTypeName, AbiTags),
2544}
2545
2546impl Parse for UnqualifiedName {
2547 fn parse<'a, 'b>(
2548 ctx: &'a ParseContext,
2549 subs: &'a mut SubstitutionTable,
2550 input: IndexStr<'b>,
2551 ) -> Result<(UnqualifiedName, IndexStr<'b>)> {
2552 try_begin_parse!("UnqualifiedName", ctx, input);
2553
2554 let operator_name_input = consume(b"on", input).unwrap_or(input);
2557 if let Ok((op, tail)) = try_recurse!(OperatorName::parse(ctx, subs, operator_name_input)) {
2558 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2559 return Ok((UnqualifiedName::Operator(op, abi_tags), tail));
2560 }
2561
2562 if let Ok((ctor_dtor, tail)) = try_recurse!(CtorDtorName::parse(ctx, subs, input)) {
2563 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2564 return Ok((UnqualifiedName::CtorDtor(ctor_dtor, abi_tags), tail));
2565 }
2566
2567 if let Ok(tail) = consume(b"L", input) {
2568 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
2569 let (discr, tail) =
2570 if let Ok((d, t)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
2571 (Some(d), t)
2572 } else {
2573 (None, tail)
2574 };
2575 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2576 return Ok((
2577 UnqualifiedName::LocalSourceName(name, discr, abi_tags),
2578 tail,
2579 ));
2580 }
2581
2582 if let Ok((source, tail)) = try_recurse!(SourceName::parse(ctx, subs, input)) {
2583 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2584 return Ok((UnqualifiedName::Source(source, abi_tags), tail));
2585 }
2586
2587 if let Ok((closure, tail)) = try_recurse!(ClosureTypeName::parse(ctx, subs, input)) {
2588 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2589 return Ok((UnqualifiedName::ClosureType(closure, abi_tags), tail));
2590 }
2591
2592 let (unnamed, tail) = UnnamedTypeName::parse(ctx, subs, input)?;
2593 let (abi_tags, tail) = AbiTags::parse(ctx, subs, tail)?;
2594 Ok((UnqualifiedName::UnnamedType(unnamed, abi_tags), tail))
2595 }
2596}
2597
2598impl<'subs, W> Demangle<'subs, W> for UnqualifiedName
2599where
2600 W: 'subs + DemangleWrite,
2601{
2602 fn demangle<'prev, 'ctx>(
2603 &'subs self,
2604 ctx: &'ctx mut DemangleContext<'subs, W>,
2605 scope: Option<ArgScopeStack<'prev, 'subs>>,
2606 ) -> fmt::Result {
2607 let ctx = try_begin_demangle!(self, ctx, scope);
2608
2609 ctx.push_demangle_node(DemangleNodeType::UnqualifiedName);
2610 let ret = match *self {
2611 UnqualifiedName::Operator(ref op_name, ref abi_tags) => {
2612 write!(ctx, "operator")?;
2613 op_name.demangle(ctx, scope)?;
2614 abi_tags.demangle(ctx, scope)
2615 }
2616 UnqualifiedName::CtorDtor(ref ctor_dtor, ref abi_tags) => {
2617 ctor_dtor.demangle(ctx, scope)?;
2618 abi_tags.demangle(ctx, scope)
2619 }
2620 UnqualifiedName::Source(ref name, ref abi_tags)
2621 | UnqualifiedName::LocalSourceName(ref name, _, ref abi_tags) => {
2622 name.demangle(ctx, scope)?;
2623 abi_tags.demangle(ctx, scope)
2624 }
2625 UnqualifiedName::UnnamedType(ref unnamed, ref abi_tags) => {
2626 unnamed.demangle(ctx, scope)?;
2627 abi_tags.demangle(ctx, scope)
2628 }
2629 UnqualifiedName::ClosureType(ref closure, ref abi_tags) => {
2630 closure.demangle(ctx, scope)?;
2631 abi_tags.demangle(ctx, scope)
2632 }
2633 };
2634 ctx.pop_demangle_node();
2635 ret
2636 }
2637}
2638
2639impl<'a> GetLeafName<'a> for UnqualifiedName {
2640 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
2641 match *self {
2642 UnqualifiedName::Operator(..) | UnqualifiedName::CtorDtor(..) => None,
2643 UnqualifiedName::UnnamedType(ref name, _) => Some(LeafName::UnnamedType(name)),
2644 UnqualifiedName::ClosureType(ref closure, _) => closure.get_leaf_name(subs),
2645 UnqualifiedName::Source(ref name, _)
2646 | UnqualifiedName::LocalSourceName(ref name, ..) => Some(LeafName::SourceName(name)),
2647 }
2648 }
2649}
2650
2651impl IsCtorDtorConversion for UnqualifiedName {
2652 fn is_ctor_dtor_conversion(&self, _: &SubstitutionTable) -> bool {
2653 match *self {
2654 UnqualifiedName::CtorDtor(..)
2655 | UnqualifiedName::Operator(OperatorName::Conversion(_), _) => true,
2656 UnqualifiedName::Operator(..)
2657 | UnqualifiedName::Source(..)
2658 | UnqualifiedName::LocalSourceName(..)
2659 | UnqualifiedName::UnnamedType(..)
2660 | UnqualifiedName::ClosureType(..) => false,
2661 }
2662 }
2663}
2664
2665impl UnqualifiedName {
2666 #[inline]
2667 fn starts_with(byte: u8, input: &IndexStr) -> bool {
2668 byte == b'L'
2669 || OperatorName::starts_with(byte)
2670 || CtorDtorName::starts_with(byte)
2671 || SourceName::starts_with(byte)
2672 || UnnamedTypeName::starts_with(byte)
2673 || ClosureTypeName::starts_with(byte, input)
2674 }
2675}
2676
2677#[derive(Clone, Debug, PartialEq, Eq)]
2683pub struct SourceName(Identifier);
2684
2685impl Parse for SourceName {
2686 fn parse<'a, 'b>(
2687 ctx: &'a ParseContext,
2688 subs: &'a mut SubstitutionTable,
2689 input: IndexStr<'b>,
2690 ) -> Result<(SourceName, IndexStr<'b>)> {
2691 try_begin_parse!("SourceName", ctx, input);
2692
2693 let (source_name_len, input) = parse_number(10, false, input)?;
2694 debug_assert!(source_name_len >= 0);
2695 if source_name_len == 0 {
2696 return Err(error::Error::UnexpectedText);
2697 }
2698
2699 let (head, tail) = match input.try_split_at(source_name_len as _) {
2700 Some((head, tail)) => (head, tail),
2701 None => return Err(error::Error::UnexpectedEnd),
2702 };
2703
2704 let (identifier, empty) = Identifier::parse(ctx, subs, head)?;
2705 if !empty.is_empty() {
2706 return Err(error::Error::UnexpectedText);
2707 }
2708
2709 let source_name = SourceName(identifier);
2710 Ok((source_name, tail))
2711 }
2712}
2713
2714impl<'subs> ArgScope<'subs, 'subs> for SourceName {
2715 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
2716 Ok(LeafName::SourceName(self))
2717 }
2718
2719 fn get_template_arg(
2720 &'subs self,
2721 _: usize,
2722 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
2723 Err(error::Error::BadTemplateArgReference)
2724 }
2725
2726 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
2727 Err(error::Error::BadFunctionArgReference)
2728 }
2729}
2730
2731impl SourceName {
2732 #[inline]
2733 fn starts_with(byte: u8) -> bool {
2734 byte == b'0' || (b'0' <= byte && byte <= b'9')
2735 }
2736}
2737
2738impl<'subs, W> Demangle<'subs, W> for SourceName
2739where
2740 W: 'subs + DemangleWrite,
2741{
2742 #[inline]
2743 fn demangle<'prev, 'ctx>(
2744 &'subs self,
2745 ctx: &'ctx mut DemangleContext<'subs, W>,
2746 scope: Option<ArgScopeStack<'prev, 'subs>>,
2747 ) -> fmt::Result {
2748 let ctx = try_begin_demangle!(self, ctx, scope);
2749
2750 self.0.demangle(ctx, scope)
2751 }
2752}
2753
2754#[derive(Clone, Debug, Default, PartialEq, Eq)]
2765pub struct AbiTags(Vec<AbiTag>);
2766
2767impl Parse for AbiTags {
2768 fn parse<'a, 'b>(
2769 ctx: &'a ParseContext,
2770 subs: &'a mut SubstitutionTable,
2771 input: IndexStr<'b>,
2772 ) -> Result<(AbiTags, IndexStr<'b>)> {
2773 try_begin_parse!("AbiTags", ctx, input);
2774
2775 let (tags, tail) = zero_or_more::<AbiTag>(ctx, subs, input)?;
2776 Ok((AbiTags(tags), tail))
2777 }
2778}
2779
2780impl<'subs, W> Demangle<'subs, W> for AbiTags
2781where
2782 W: 'subs + DemangleWrite,
2783{
2784 fn demangle<'prev, 'ctx>(
2785 &'subs self,
2786 ctx: &'ctx mut DemangleContext<'subs, W>,
2787 scope: Option<ArgScopeStack<'prev, 'subs>>,
2788 ) -> fmt::Result {
2789 let ctx = try_begin_demangle!(self, ctx, scope);
2790
2791 for tag in &self.0 {
2792 tag.demangle(ctx, scope)?;
2793 }
2794 Ok(())
2795 }
2796}
2797
2798#[derive(Clone, Debug, PartialEq, Eq)]
2804pub struct AbiTag(SourceName);
2805
2806impl Parse for AbiTag {
2807 fn parse<'a, 'b>(
2808 ctx: &'a ParseContext,
2809 subs: &'a mut SubstitutionTable,
2810 input: IndexStr<'b>,
2811 ) -> Result<(AbiTag, IndexStr<'b>)> {
2812 try_begin_parse!("AbiTag", ctx, input);
2813
2814 let tail = consume(b"B", input)?;
2815 let (source_name, tail) = SourceName::parse(ctx, subs, tail)?;
2816 Ok((AbiTag(source_name), tail))
2817 }
2818}
2819
2820impl<'subs, W> Demangle<'subs, W> for AbiTag
2821where
2822 W: 'subs + DemangleWrite,
2823{
2824 fn demangle<'prev, 'ctx>(
2825 &'subs self,
2826 ctx: &'ctx mut DemangleContext<'subs, W>,
2827 scope: Option<ArgScopeStack<'prev, 'subs>>,
2828 ) -> fmt::Result {
2829 let ctx = try_begin_demangle!(self, ctx, scope);
2830
2831 write!(ctx, "[abi:")?;
2832 self.0.demangle(ctx, scope)?;
2833 write!(ctx, "]")
2834 }
2835}
2836
2837#[derive(Clone, Debug, PartialEq, Eq)]
2850pub struct Identifier {
2851 start: usize,
2852 end: usize,
2853}
2854
2855impl Parse for Identifier {
2856 fn parse<'a, 'b>(
2857 ctx: &'a ParseContext,
2858 _subs: &'a mut SubstitutionTable,
2859 input: IndexStr<'b>,
2860 ) -> Result<(Identifier, IndexStr<'b>)> {
2861 try_begin_parse!("Identifier", ctx, input);
2862
2863 if input.is_empty() {
2864 return Err(error::Error::UnexpectedEnd);
2865 }
2866
2867 let end = input
2868 .as_ref()
2869 .iter()
2870 .map(|&c| c as char)
2871 .take_while(|&c| c == '$' || c == '_' || c == '.' || c.is_digit(36))
2872 .count();
2873
2874 if end == 0 {
2875 return Err(error::Error::UnexpectedText);
2876 }
2877
2878 let tail = input.range_from(end..);
2879
2880 let identifier = Identifier {
2881 start: input.index(),
2882 end: tail.index(),
2883 };
2884
2885 Ok((identifier, tail))
2886 }
2887}
2888
2889impl<'subs, W> Demangle<'subs, W> for Identifier
2890where
2891 W: 'subs + DemangleWrite,
2892{
2893 #[inline]
2894 fn demangle<'prev, 'ctx>(
2895 &'subs self,
2896 ctx: &'ctx mut DemangleContext<'subs, W>,
2897 scope: Option<ArgScopeStack<'prev, 'subs>>,
2898 ) -> fmt::Result {
2899 let ctx = try_begin_demangle!(self, ctx, scope);
2900
2901 let ident = &ctx.input[self.start..self.end];
2902
2903 let anon_namespace_prefix = b"_GLOBAL_";
2905 if ident.starts_with(anon_namespace_prefix)
2906 && ident.len() >= anon_namespace_prefix.len() + 2
2907 {
2908 let first = ident[anon_namespace_prefix.len()];
2909 let second = ident[anon_namespace_prefix.len() + 1];
2910
2911 match (first, second) {
2912 (b'.', b'N') | (b'_', b'N') | (b'$', b'N') => {
2913 write!(ctx, "(anonymous namespace)")?;
2914 return Ok(());
2915 }
2916 _ => {
2917 }
2919 }
2920 }
2921
2922 let source_name = String::from_utf8_lossy(ident);
2923 ctx.set_source_name(self.start, self.end);
2924 write!(ctx, "{}", source_name)?;
2925 Ok(())
2926 }
2927}
2928
2929#[derive(Clone, Debug, PartialEq, Eq)]
2935pub struct CloneTypeIdentifier {
2936 start: usize,
2937 end: usize,
2938}
2939
2940impl Parse for CloneTypeIdentifier {
2941 fn parse<'a, 'b>(
2942 ctx: &'a ParseContext,
2943 _subs: &'a mut SubstitutionTable,
2944 input: IndexStr<'b>,
2945 ) -> Result<(CloneTypeIdentifier, IndexStr<'b>)> {
2946 try_begin_parse!("CloneTypeIdentifier", ctx, input);
2947
2948 if input.is_empty() {
2949 return Err(error::Error::UnexpectedEnd);
2950 }
2951
2952 let end = input
2953 .as_ref()
2954 .iter()
2955 .map(|&c| c as char)
2956 .take_while(|&c| c == '$' || c == '_' || c.is_digit(36))
2957 .count();
2958
2959 if end == 0 {
2960 return Err(error::Error::UnexpectedText);
2961 }
2962
2963 let tail = input.range_from(end..);
2964
2965 let identifier = CloneTypeIdentifier {
2966 start: input.index(),
2967 end: tail.index(),
2968 };
2969
2970 Ok((identifier, tail))
2971 }
2972}
2973
2974impl<'subs, W> Demangle<'subs, W> for CloneTypeIdentifier
2975where
2976 W: 'subs + DemangleWrite,
2977{
2978 #[inline]
2979 fn demangle<'prev, 'ctx>(
2980 &'subs self,
2981 ctx: &'ctx mut DemangleContext<'subs, W>,
2982 scope: Option<ArgScopeStack<'prev, 'subs>>,
2983 ) -> fmt::Result {
2984 let ctx = try_begin_demangle!(self, ctx, scope);
2985
2986 let ident = &ctx.input[self.start..self.end];
2987
2988 let source_name = String::from_utf8_lossy(ident);
2989 ctx.set_source_name(self.start, self.end);
2990 write!(ctx, " .{}", source_name)?;
2991 Ok(())
2992 }
2993}
2994
2995type Number = isize;
3001
3002impl Parse for Number {
3003 fn parse<'a, 'b>(
3004 ctx: &'a ParseContext,
3005 _subs: &'a mut SubstitutionTable,
3006 input: IndexStr<'b>,
3007 ) -> Result<(isize, IndexStr<'b>)> {
3008 try_begin_parse!("Number", ctx, input);
3009 parse_number(10, true, input)
3010 }
3011}
3012
3013#[derive(Clone, Debug, PartialEq, Eq)]
3019pub struct SeqId(usize);
3020
3021impl Parse for SeqId {
3022 fn parse<'a, 'b>(
3023 ctx: &'a ParseContext,
3024 _subs: &'a mut SubstitutionTable,
3025 input: IndexStr<'b>,
3026 ) -> Result<(SeqId, IndexStr<'b>)> {
3027 try_begin_parse!("SeqId", ctx, input);
3028
3029 parse_number(36, false, input).map(|(num, tail)| (SeqId(num as _), tail))
3030 }
3031}
3032
3033#[derive(Clone, Debug, PartialEq, Eq)]
3042pub enum OperatorName {
3043 Simple(SimpleOperatorName),
3045
3046 Cast(TypeHandle),
3048
3049 Conversion(TypeHandle),
3051
3052 Literal(SourceName),
3054
3055 VendorExtension(u8, SourceName),
3057}
3058
3059impl OperatorName {
3060 fn starts_with(byte: u8) -> bool {
3061 byte == b'c' || byte == b'l' || byte == b'v' || SimpleOperatorName::starts_with(byte)
3062 }
3063
3064 fn arity(&self) -> u8 {
3065 match self {
3066 &OperatorName::Cast(_) | &OperatorName::Conversion(_) | &OperatorName::Literal(_) => 1,
3067 &OperatorName::Simple(ref s) => s.arity(),
3068 &OperatorName::VendorExtension(arity, _) => arity,
3069 }
3070 }
3071
3072 fn parse_from_expr<'a, 'b>(
3073 ctx: &'a ParseContext,
3074 subs: &'a mut SubstitutionTable,
3075 input: IndexStr<'b>,
3076 ) -> Result<(Expression, IndexStr<'b>)> {
3077 let (operator, tail) = OperatorName::parse_internal(ctx, subs, input, true)?;
3078
3079 let arity = operator.arity();
3080 if arity == 1 {
3081 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3082 let expr = Expression::Unary(operator, Box::new(first));
3083 Ok((expr, tail))
3084 } else if arity == 2 {
3085 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3086 let (second, tail) = Expression::parse(ctx, subs, tail)?;
3087 let expr = Expression::Binary(operator, Box::new(first), Box::new(second));
3088 Ok((expr, tail))
3089 } else if arity == 3 {
3090 let (first, tail) = Expression::parse(ctx, subs, tail)?;
3091 let (second, tail) = Expression::parse(ctx, subs, tail)?;
3092 let (third, tail) = Expression::parse(ctx, subs, tail)?;
3093 let expr =
3094 Expression::Ternary(operator, Box::new(first), Box::new(second), Box::new(third));
3095 Ok((expr, tail))
3096 } else {
3097 Err(error::Error::UnexpectedText)
3098 }
3099 }
3100
3101 fn parse_internal<'a, 'b>(
3102 ctx: &'a ParseContext,
3103 subs: &'a mut SubstitutionTable,
3104 input: IndexStr<'b>,
3105 from_expr: bool,
3106 ) -> Result<(OperatorName, IndexStr<'b>)> {
3107 try_begin_parse!("OperatorName", ctx, input);
3108
3109 if let Ok((simple, tail)) = try_recurse!(SimpleOperatorName::parse(ctx, subs, input)) {
3110 return Ok((OperatorName::Simple(simple), tail));
3111 }
3112
3113 if let Ok(tail) = consume(b"cv", input) {
3114 let previously_in_conversion = ctx.set_in_conversion(!from_expr);
3117 let parse_result = TypeHandle::parse(ctx, subs, tail);
3118 ctx.set_in_conversion(previously_in_conversion);
3119 let (ty, tail) = parse_result?;
3120 if from_expr {
3121 return Ok((OperatorName::Cast(ty), tail));
3122 } else {
3123 return Ok((OperatorName::Conversion(ty), tail));
3124 }
3125 }
3126
3127 if let Ok(tail) = consume(b"li", input) {
3128 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3129 return Ok((OperatorName::Literal(name), tail));
3130 }
3131
3132 let tail = consume(b"v", input)?;
3133 let (arity, tail) = match tail.peek() {
3134 Some(c) if b'0' <= c && c <= b'9' => (c - b'0', tail.range_from(1..)),
3135 None => return Err(error::Error::UnexpectedEnd),
3136 _ => return Err(error::Error::UnexpectedText),
3137 };
3138 let (name, tail) = SourceName::parse(ctx, subs, tail)?;
3139 Ok((OperatorName::VendorExtension(arity, name), tail))
3140 }
3141}
3142
3143impl Parse for OperatorName {
3144 fn parse<'a, 'b>(
3145 ctx: &'a ParseContext,
3146 subs: &'a mut SubstitutionTable,
3147 input: IndexStr<'b>,
3148 ) -> Result<(OperatorName, IndexStr<'b>)> {
3149 OperatorName::parse_internal(ctx, subs, input, false)
3150 }
3151}
3152
3153impl<'subs, W> Demangle<'subs, W> for OperatorName
3154where
3155 W: 'subs + DemangleWrite,
3156{
3157 fn demangle<'prev, 'ctx>(
3158 &'subs self,
3159 ctx: &'ctx mut DemangleContext<'subs, W>,
3160 scope: Option<ArgScopeStack<'prev, 'subs>>,
3161 ) -> fmt::Result {
3162 let ctx = try_begin_demangle!(self, ctx, scope);
3163
3164 match *self {
3165 OperatorName::Simple(ref simple) => {
3166 match *simple {
3167 SimpleOperatorName::New
3168 | SimpleOperatorName::NewArray
3169 | SimpleOperatorName::Delete
3170 | SimpleOperatorName::DeleteArray => {
3171 ctx.ensure_space()?;
3172 }
3173 _ => {}
3174 }
3175 simple.demangle(ctx, scope)
3176 }
3177 OperatorName::Cast(ref ty) | OperatorName::Conversion(ref ty) => {
3178 inner_barrier!(ctx);
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 match try_recurse!(TemplateArgs::parse(ctx, &mut tmp_subs, tail)) {
3774 Ok((_, new_tail)) if new_tail.peek() == Some(b'I') => {
3775 }
3781 _ => {
3782 let ty = Type::TemplateParam(param);
3784 return insert_and_return_handle(ty, subs, tail);
3785 }
3786 }
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)]
5771pub enum Expression {
5772 Unary(OperatorName, Box<Expression>),
5774
5775 Binary(OperatorName, Box<Expression>, Box<Expression>),
5777
5778 Ternary(
5780 OperatorName,
5781 Box<Expression>,
5782 Box<Expression>,
5783 Box<Expression>,
5784 ),
5785
5786 PrefixInc(Box<Expression>),
5788
5789 PrefixDec(Box<Expression>),
5791
5792 Call(Box<Expression>, Vec<Expression>),
5794
5795 ConversionOne(TypeHandle, Box<Expression>),
5797
5798 ConversionMany(TypeHandle, Vec<Expression>),
5800
5801 ConversionBraced(TypeHandle, Vec<Expression>),
5803
5804 BracedInitList(Vec<Expression>),
5806
5807 New(Vec<Expression>, TypeHandle, Option<Initializer>),
5809
5810 GlobalNew(Vec<Expression>, TypeHandle, Option<Initializer>),
5812
5813 NewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5815
5816 GlobalNewArray(Vec<Expression>, TypeHandle, Option<Initializer>),
5818
5819 Delete(Box<Expression>),
5821
5822 GlobalDelete(Box<Expression>),
5824
5825 DeleteArray(Box<Expression>),
5827
5828 GlobalDeleteArray(Box<Expression>),
5830
5831 DynamicCast(TypeHandle, Box<Expression>),
5833
5834 StaticCast(TypeHandle, Box<Expression>),
5836
5837 ConstCast(TypeHandle, Box<Expression>),
5839
5840 ReinterpretCast(TypeHandle, Box<Expression>),
5842
5843 TypeidType(TypeHandle),
5845
5846 TypeidExpr(Box<Expression>),
5848
5849 SizeofType(TypeHandle),
5851
5852 SizeofExpr(Box<Expression>),
5854
5855 AlignofType(TypeHandle),
5857
5858 AlignofExpr(Box<Expression>),
5860
5861 Noexcept(Box<Expression>),
5863
5864 Subobject(SubobjectExpr),
5866
5867 TemplateParam(TemplateParam),
5869
5870 FunctionParam(FunctionParam),
5872
5873 Member(Box<Expression>, MemberName),
5875
5876 DerefMember(Box<Expression>, MemberName),
5878
5879 PointerToMember(Box<Expression>, Box<Expression>),
5881
5882 SizeofTemplatePack(TemplateParam),
5884
5885 SizeofFunctionPack(FunctionParam),
5887
5888 SizeofCapturedTemplatePack(Vec<TemplateArg>),
5891
5892 PackExpansion(Box<Expression>),
5894
5895 Fold(FoldExpr),
5897
5898 Throw(Box<Expression>),
5900
5901 Rethrow,
5903
5904 UnresolvedName(UnresolvedName),
5907
5908 Primary(ExprPrimary),
5910}
5911
5912impl Parse for Expression {
5913 fn parse<'a, 'b>(
5914 ctx: &'a ParseContext,
5915 subs: &'a mut SubstitutionTable,
5916 input: IndexStr<'b>,
5917 ) -> Result<(Expression, IndexStr<'b>)> {
5918 try_begin_parse!("Expression", ctx, input);
5919
5920 if let Ok(tail) = consume(b"pp_", input) {
5921 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5922 let expr = Expression::PrefixInc(Box::new(expr));
5923 return Ok((expr, tail));
5924 }
5925
5926 if let Ok(tail) = consume(b"mm_", input) {
5927 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5928 let expr = Expression::PrefixDec(Box::new(expr));
5929 return Ok((expr, tail));
5930 }
5931
5932 if let Some((head, tail)) = input.try_split_at(2) {
5933 match head.as_ref() {
5934 b"cl" => {
5935 let (func, tail) = Expression::parse(ctx, subs, tail)?;
5936 let (args, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5937 let tail = consume(b"E", tail)?;
5938 let expr = Expression::Call(Box::new(func), args);
5939 return Ok((expr, tail));
5940 }
5941 b"cv" => {
5942 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5943 if let Ok(tail) = consume(b"_", tail) {
5944 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5945 let tail = consume(b"E", tail)?;
5946 let expr = Expression::ConversionMany(ty, exprs);
5947 return Ok((expr, tail));
5948 } else {
5949 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5950 let expr = Expression::ConversionOne(ty, Box::new(expr));
5951 return Ok((expr, tail));
5952 }
5953 }
5954 b"tl" => {
5955 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5956 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5957 let expr = Expression::ConversionBraced(ty, exprs);
5958 let tail = consume(b"E", tail)?;
5959 return Ok((expr, tail));
5960 }
5961 b"il" => {
5962 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
5963 let expr = Expression::BracedInitList(exprs);
5964 let tail = consume(b"E", tail)?;
5965 return Ok((expr, tail));
5966 }
5967 b"dc" => {
5968 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5969 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5970 let expr = Expression::DynamicCast(ty, Box::new(expr));
5971 return Ok((expr, tail));
5972 }
5973 b"sc" => {
5974 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5975 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5976 let expr = Expression::StaticCast(ty, Box::new(expr));
5977 return Ok((expr, tail));
5978 }
5979 b"cc" => {
5980 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5981 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5982 let expr = Expression::ConstCast(ty, Box::new(expr));
5983 return Ok((expr, tail));
5984 }
5985 b"rc" => {
5986 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5987 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5988 let expr = Expression::ReinterpretCast(ty, Box::new(expr));
5989 return Ok((expr, tail));
5990 }
5991 b"ti" => {
5992 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
5993 let expr = Expression::TypeidType(ty);
5994 return Ok((expr, tail));
5995 }
5996 b"te" => {
5997 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
5998 let expr = Expression::TypeidExpr(Box::new(expr));
5999 return Ok((expr, tail));
6000 }
6001 b"st" => {
6002 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6003 let expr = Expression::SizeofType(ty);
6004 return Ok((expr, tail));
6005 }
6006 b"sz" => {
6007 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6008 let expr = Expression::SizeofExpr(Box::new(expr));
6009 return Ok((expr, tail));
6010 }
6011 b"at" => {
6012 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6013 let expr = Expression::AlignofType(ty);
6014 return Ok((expr, tail));
6015 }
6016 b"az" => {
6017 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6018 let expr = Expression::AlignofExpr(Box::new(expr));
6019 return Ok((expr, tail));
6020 }
6021 b"nx" => {
6022 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6023 let expr = Expression::Noexcept(Box::new(expr));
6024 return Ok((expr, tail));
6025 }
6026 b"so" => {
6027 let (expr, tail) = SubobjectExpr::parse(ctx, subs, tail)?;
6028 let expr = Expression::Subobject(expr);
6029 return Ok((expr, tail));
6030 }
6031 b"dt" => {
6032 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6033 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
6034 let expr = Expression::Member(Box::new(expr), name);
6035 return Ok((expr, tail));
6036 }
6037 b"pt" => {
6038 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6039 let (name, tail) = MemberName::parse(ctx, subs, tail)?;
6040 let expr = Expression::DerefMember(Box::new(expr), name);
6041 return Ok((expr, tail));
6042 }
6043 b"ds" => {
6044 let (first, tail) = Expression::parse(ctx, subs, tail)?;
6045 let (second, tail) = Expression::parse(ctx, subs, tail)?;
6046 let expr = Expression::PointerToMember(Box::new(first), Box::new(second));
6047 return Ok((expr, tail));
6048 }
6049 b"sZ" => {
6050 if let Ok((param, tail)) = TemplateParam::parse(ctx, subs, tail) {
6051 let expr = Expression::SizeofTemplatePack(param);
6052 return Ok((expr, tail));
6053 }
6054
6055 let (param, tail) = FunctionParam::parse(ctx, subs, tail)?;
6056 let expr = Expression::SizeofFunctionPack(param);
6057 return Ok((expr, tail));
6058 }
6059 b"sP" => {
6060 let (args, tail) = zero_or_more::<TemplateArg>(ctx, subs, tail)?;
6061 let expr = Expression::SizeofCapturedTemplatePack(args);
6062 let tail = consume(b"E", tail)?;
6063 return Ok((expr, tail));
6064 }
6065 b"sp" => {
6066 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6067 let expr = Expression::PackExpansion(Box::new(expr));
6068 return Ok((expr, tail));
6069 }
6070 b"fl" | b"fr" | b"fR" => {
6071 let (expr, tail) = FoldExpr::parse(ctx, subs, input)?;
6072 let expr = Expression::Fold(expr);
6073 return Ok((expr, tail));
6074 }
6075 b"fL" if tail.peek().map(|c| !c.is_ascii_digit()).unwrap_or(false) => {
6079 let (expr, tail) = FoldExpr::parse(ctx, subs, input)?;
6080 let expr = Expression::Fold(expr);
6081 return Ok((expr, tail));
6082 }
6083 b"tw" => {
6084 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6085 let expr = Expression::Throw(Box::new(expr));
6086 return Ok((expr, tail));
6087 }
6088 b"tr" => {
6089 let expr = Expression::Rethrow;
6090 return Ok((expr, tail));
6091 }
6092 b"gs" => {
6093 if let Ok((expr, tail)) = try_recurse!(can_be_global(true, ctx, subs, tail)) {
6094 return Ok((expr, tail));
6095 }
6096 }
6097 _ => {}
6098 }
6099 }
6100
6101 if let Ok((expr, tail)) = try_recurse!(can_be_global(false, ctx, subs, input)) {
6102 return Ok((expr, tail));
6103 }
6104
6105 if let Ok((param, tail)) = try_recurse!(TemplateParam::parse(ctx, subs, input)) {
6106 let expr = Expression::TemplateParam(param);
6107 return Ok((expr, tail));
6108 }
6109
6110 if let Ok((param, tail)) = try_recurse!(FunctionParam::parse(ctx, subs, input)) {
6111 let expr = Expression::FunctionParam(param);
6112 return Ok((expr, tail));
6113 }
6114
6115 if let Ok((name, tail)) = try_recurse!(UnresolvedName::parse(ctx, subs, input)) {
6116 let expr = Expression::UnresolvedName(name);
6117 return Ok((expr, tail));
6118 }
6119
6120 if let Ok((prim, tail)) = try_recurse!(ExprPrimary::parse(ctx, subs, input)) {
6121 let expr = Expression::Primary(prim);
6122 return Ok((expr, tail));
6123 }
6124
6125 let (expr, tail) = OperatorName::parse_from_expr(ctx, subs, input)?;
6130 return Ok((expr, tail));
6131
6132 fn can_be_global<'a, 'b>(
6137 is_global: bool,
6138 ctx: &'a ParseContext,
6139 subs: &'a mut SubstitutionTable,
6140 input: IndexStr<'b>,
6141 ) -> Result<(Expression, IndexStr<'b>)> {
6142 match input.try_split_at(2) {
6143 None => Err(error::Error::UnexpectedEnd),
6144 Some((head, tail)) => match head.as_ref() {
6145 b"nw" => {
6146 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6147 let tail = consume(b"_", tail)?;
6148 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6149 if let Ok(tail) = consume(b"E", tail) {
6150 let expr = if is_global {
6151 Expression::GlobalNew(exprs, ty, None)
6152 } else {
6153 Expression::New(exprs, ty, None)
6154 };
6155 Ok((expr, tail))
6156 } else {
6157 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
6158 let expr = if is_global {
6159 Expression::GlobalNew(exprs, ty, Some(init))
6160 } else {
6161 Expression::New(exprs, ty, Some(init))
6162 };
6163 Ok((expr, tail))
6164 }
6165 }
6166 b"na" => {
6167 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
6168 let tail = consume(b"_", tail)?;
6169 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
6170 if let Ok(tail) = consume(b"E", tail) {
6171 let expr = if is_global {
6172 Expression::GlobalNewArray(exprs, ty, None)
6173 } else {
6174 Expression::NewArray(exprs, ty, None)
6175 };
6176 Ok((expr, tail))
6177 } else {
6178 let (init, tail) = Initializer::parse(ctx, subs, tail)?;
6179 let expr = if is_global {
6180 Expression::GlobalNewArray(exprs, ty, Some(init))
6181 } else {
6182 Expression::NewArray(exprs, ty, Some(init))
6183 };
6184 Ok((expr, tail))
6185 }
6186 }
6187 b"dl" => {
6188 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6189 let expr = if is_global {
6190 Expression::GlobalDelete(Box::new(expr))
6191 } else {
6192 Expression::Delete(Box::new(expr))
6193 };
6194 Ok((expr, tail))
6195 }
6196 b"da" => {
6197 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
6198 let expr = if is_global {
6199 Expression::GlobalDeleteArray(Box::new(expr))
6200 } else {
6201 Expression::DeleteArray(Box::new(expr))
6202 };
6203 Ok((expr, tail))
6204 }
6205 _ => Err(error::Error::UnexpectedText),
6206 },
6207 }
6208 }
6209 }
6210}
6211
6212impl<'subs, W> Demangle<'subs, W> for Expression
6213where
6214 W: 'subs + DemangleWrite,
6215{
6216 fn demangle<'prev, 'ctx>(
6217 &'subs self,
6218 ctx: &'ctx mut DemangleContext<'subs, W>,
6219 scope: Option<ArgScopeStack<'prev, 'subs>>,
6220 ) -> fmt::Result {
6221 let ctx = try_begin_demangle!(self, ctx, scope);
6222
6223 match *self {
6224 Expression::Unary(OperatorName::Simple(ref op), ref expr)
6225 if *op == SimpleOperatorName::PostInc || *op == SimpleOperatorName::PostDec =>
6226 {
6227 expr.demangle_as_subexpr(ctx, scope)?;
6228 op.demangle(ctx, scope)
6229 }
6230 Expression::Unary(ref op, ref expr) => {
6231 op.demangle(ctx, scope)?;
6232 expr.demangle_as_subexpr(ctx, scope)
6233 }
6234 Expression::Binary(
6237 OperatorName::Simple(SimpleOperatorName::Greater),
6238 ref lhs,
6239 ref rhs,
6240 ) => {
6241 write!(ctx, "((")?;
6242 lhs.demangle(ctx, scope)?;
6243 write!(ctx, ")>(")?;
6244 rhs.demangle(ctx, scope)?;
6245 write!(ctx, "))")
6246 }
6247 Expression::Binary(ref op, ref lhs, ref rhs) => {
6248 lhs.demangle_as_subexpr(ctx, scope)?;
6249 op.demangle(ctx, scope)?;
6250 rhs.demangle_as_subexpr(ctx, scope)
6251 }
6252 Expression::Ternary(
6253 OperatorName::Simple(SimpleOperatorName::Question),
6254 ref condition,
6255 ref consequent,
6256 ref alternative,
6257 ) => {
6258 condition.demangle_as_subexpr(ctx, scope)?;
6259 write!(ctx, "?")?;
6260 consequent.demangle_as_subexpr(ctx, scope)?;
6261 write!(ctx, " : ")?;
6262 alternative.demangle_as_subexpr(ctx, scope)
6263 }
6264 Expression::Ternary(ref op, ref e1, ref e2, ref e3) => {
6265 op.demangle(ctx, scope)?;
6270 write!(ctx, "(")?;
6271 e1.demangle(ctx, scope)?;
6272 write!(ctx, ", ")?;
6273 e2.demangle(ctx, scope)?;
6274 write!(ctx, ", ")?;
6275 e3.demangle(ctx, scope)?;
6276 write!(ctx, ")")?;
6277 Ok(())
6278 }
6279 Expression::PrefixInc(ref expr) => {
6280 write!(ctx, "++")?;
6281 expr.demangle(ctx, scope)
6282 }
6283 Expression::PrefixDec(ref expr) => {
6284 write!(ctx, "--")?;
6285 expr.demangle(ctx, scope)
6286 }
6287 Expression::Call(ref functor_expr, ref args) => {
6288 functor_expr.demangle_as_subexpr(ctx, scope)?;
6289 write!(ctx, "(")?;
6290 let mut need_comma = false;
6291 for arg in args {
6292 if need_comma {
6293 write!(ctx, ", ")?;
6294 }
6295 arg.demangle(ctx, scope)?;
6296 need_comma = true;
6297 }
6298 write!(ctx, ")")?;
6299 Ok(())
6300 }
6301 Expression::ConversionOne(ref ty, ref expr) => {
6302 write!(ctx, "(")?;
6303 ty.demangle(ctx, scope)?;
6304 write!(ctx, ")(")?;
6305 expr.demangle(ctx, scope)?;
6306 write!(ctx, ")")?;
6307 Ok(())
6308 }
6309 Expression::ConversionMany(ref ty, ref exprs) => {
6310 ty.demangle(ctx, scope)?;
6311 write!(ctx, "(")?;
6312 let mut need_comma = false;
6313 for expr in exprs {
6314 if need_comma {
6315 write!(ctx, ", ")?;
6316 }
6317 expr.demangle(ctx, scope)?;
6318 need_comma = true;
6319 }
6320 write!(ctx, ")")?;
6321 Ok(())
6322 }
6323 Expression::ConversionBraced(ref ty, ref exprs) => {
6324 ty.demangle(ctx, scope)?;
6325 write!(ctx, "{{")?;
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 Ok(())
6336 }
6337 Expression::BracedInitList(ref exprs) => {
6338 write!(ctx, "{{")?;
6339 let mut need_comma = false;
6340 for expr in exprs {
6341 if need_comma {
6342 write!(ctx, ", ")?;
6343 }
6344 expr.demangle(ctx, scope)?;
6345 need_comma = true;
6346 }
6347 write!(ctx, "}}")?;
6348 Ok(())
6349 }
6350 Expression::New(ref exprs, ref ty, ref init) => {
6352 write!(ctx, "new (")?;
6353 let mut need_comma = false;
6354 for expr in exprs {
6355 if need_comma {
6356 write!(ctx, ", ")?;
6357 }
6358 expr.demangle(ctx, scope)?;
6359 need_comma = true;
6360 }
6361 write!(ctx, ") ")?;
6362 ty.demangle(ctx, scope)?;
6363 if let Some(ref init) = *init {
6364 init.demangle(ctx, scope)?;
6365 }
6366 Ok(())
6367 }
6368 Expression::GlobalNew(ref exprs, ref ty, ref init) => {
6369 write!(ctx, "::new (")?;
6370 let mut need_comma = false;
6371 for expr in exprs {
6372 if need_comma {
6373 write!(ctx, ", ")?;
6374 }
6375 expr.demangle(ctx, scope)?;
6376 need_comma = true;
6377 }
6378 write!(ctx, ") ")?;
6379 ty.demangle(ctx, scope)?;
6380 if let Some(ref init) = *init {
6381 init.demangle(ctx, scope)?;
6382 }
6383 Ok(())
6384 }
6385 Expression::NewArray(ref exprs, ref ty, ref init) => {
6386 write!(ctx, "new[] (")?;
6387 let mut need_comma = false;
6388 for expr in exprs {
6389 if need_comma {
6390 write!(ctx, ", ")?;
6391 }
6392 expr.demangle(ctx, scope)?;
6393 need_comma = true;
6394 }
6395 write!(ctx, ") ")?;
6396 ty.demangle(ctx, scope)?;
6397 if let Some(ref init) = *init {
6398 init.demangle(ctx, scope)?;
6399 }
6400 Ok(())
6401 }
6402 Expression::GlobalNewArray(ref exprs, ref ty, ref init) => {
6403 write!(ctx, "::new[] (")?;
6404 let mut need_comma = false;
6405 for expr in exprs {
6406 if need_comma {
6407 write!(ctx, ", ")?;
6408 }
6409 expr.demangle(ctx, scope)?;
6410 need_comma = true;
6411 }
6412 write!(ctx, ") ")?;
6413 ty.demangle(ctx, scope)?;
6414 if let Some(ref init) = *init {
6415 init.demangle(ctx, scope)?;
6416 }
6417 Ok(())
6418 }
6419 Expression::Delete(ref expr) => {
6420 write!(ctx, "delete ")?;
6421 expr.demangle(ctx, scope)
6422 }
6423 Expression::GlobalDelete(ref expr) => {
6424 write!(ctx, "::delete ")?;
6425 expr.demangle(ctx, scope)
6426 }
6427 Expression::DeleteArray(ref expr) => {
6428 write!(ctx, "delete[] ")?;
6429 expr.demangle(ctx, scope)
6430 }
6431 Expression::GlobalDeleteArray(ref expr) => {
6432 write!(ctx, "::delete[] ")?;
6433 expr.demangle(ctx, scope)
6434 }
6435 Expression::DynamicCast(ref ty, ref expr) => {
6437 write!(ctx, "dynamic_cast<")?;
6438 ty.demangle(ctx, scope)?;
6439 write!(ctx, ">(")?;
6440 expr.demangle(ctx, scope)?;
6441 write!(ctx, ")")?;
6442 Ok(())
6443 }
6444 Expression::StaticCast(ref ty, ref expr) => {
6445 write!(ctx, "static_cast<")?;
6446 ty.demangle(ctx, scope)?;
6447 write!(ctx, ">(")?;
6448 expr.demangle(ctx, scope)?;
6449 write!(ctx, ")")?;
6450 Ok(())
6451 }
6452 Expression::ConstCast(ref ty, ref expr) => {
6453 write!(ctx, "const_cast<")?;
6454 ty.demangle(ctx, scope)?;
6455 write!(ctx, ">(")?;
6456 expr.demangle(ctx, scope)?;
6457 write!(ctx, ")")?;
6458 Ok(())
6459 }
6460 Expression::ReinterpretCast(ref ty, ref expr) => {
6461 write!(ctx, "reinterpret_cast<")?;
6462 ty.demangle(ctx, scope)?;
6463 write!(ctx, ">(")?;
6464 expr.demangle(ctx, scope)?;
6465 write!(ctx, ")")?;
6466 Ok(())
6467 }
6468 Expression::TypeidType(ref ty) => {
6469 write!(ctx, "typeid (")?;
6470 ty.demangle(ctx, scope)?;
6471 write!(ctx, ")")?;
6472 Ok(())
6473 }
6474 Expression::TypeidExpr(ref expr) => {
6475 write!(ctx, "typeid (")?;
6476 expr.demangle(ctx, scope)?;
6477 write!(ctx, ")")?;
6478 Ok(())
6479 }
6480 Expression::SizeofType(ref ty) => {
6481 write!(ctx, "sizeof (")?;
6482 ty.demangle(ctx, scope)?;
6483 write!(ctx, ")")?;
6484 Ok(())
6485 }
6486 Expression::SizeofExpr(ref expr) => {
6487 write!(ctx, "sizeof (")?;
6488 expr.demangle(ctx, scope)?;
6489 write!(ctx, ")")?;
6490 Ok(())
6491 }
6492 Expression::AlignofType(ref ty) => {
6493 write!(ctx, "alignof (")?;
6494 ty.demangle(ctx, scope)?;
6495 write!(ctx, ")")?;
6496 Ok(())
6497 }
6498 Expression::AlignofExpr(ref expr) => {
6499 write!(ctx, "alignof (")?;
6500 expr.demangle(ctx, scope)?;
6501 write!(ctx, ")")?;
6502 Ok(())
6503 }
6504 Expression::Noexcept(ref expr) => {
6505 write!(ctx, "noexcept (")?;
6506 expr.demangle(ctx, scope)?;
6507 write!(ctx, ")")?;
6508 Ok(())
6509 }
6510 Expression::Subobject(ref expr) => expr.demangle(ctx, scope),
6511 Expression::Fold(ref expr) => expr.demangle(ctx, scope),
6512 Expression::TemplateParam(ref param) => param.demangle(ctx, scope),
6513 Expression::FunctionParam(ref param) => param.demangle(ctx, scope),
6514 Expression::Member(ref expr, ref name) => {
6515 expr.demangle_as_subexpr(ctx, scope)?;
6516 write!(ctx, ".")?;
6517 name.demangle(ctx, scope)
6518 }
6519 Expression::DerefMember(ref expr, ref name) => {
6520 expr.demangle(ctx, scope)?;
6521 write!(ctx, "->")?;
6522 name.demangle(ctx, scope)
6523 }
6524 Expression::PointerToMember(ref e1, ref e2) => {
6525 e1.demangle(ctx, scope)?;
6526 write!(ctx, ".*")?;
6527 e2.demangle(ctx, scope)
6528 }
6529 Expression::SizeofTemplatePack(ref param) => {
6530 write!(ctx, "sizeof...(")?;
6531 param.demangle(ctx, scope)?;
6532 write!(ctx, ")")?;
6533 Ok(())
6534 }
6535 Expression::SizeofFunctionPack(ref param) => {
6536 write!(ctx, "sizeof...(")?;
6537 param.demangle(ctx, scope)?;
6538 write!(ctx, ")")?;
6539 Ok(())
6540 }
6541 Expression::SizeofCapturedTemplatePack(ref args) => {
6542 write!(ctx, "sizeof...(")?;
6543 let mut need_comma = false;
6544 for arg in args {
6545 if need_comma {
6546 write!(ctx, ", ")?;
6547 }
6548 arg.demangle(ctx, scope)?;
6549 need_comma = true;
6550 }
6551 write!(ctx, ")")?;
6552 Ok(())
6553 }
6554 Expression::PackExpansion(ref pack) => {
6555 pack.demangle_as_subexpr(ctx, scope)?;
6556 write!(ctx, "...")?;
6557 Ok(())
6558 }
6559 Expression::Throw(ref expr) => {
6560 write!(ctx, "throw ")?;
6561 expr.demangle(ctx, scope)
6562 }
6563 Expression::Rethrow => {
6564 write!(ctx, "throw")?;
6565 Ok(())
6566 }
6567 Expression::UnresolvedName(ref name) => name.demangle(ctx, scope),
6568 Expression::Primary(ref expr) => expr.demangle(ctx, scope),
6569 }
6570 }
6571}
6572
6573impl Expression {
6574 fn demangle_as_subexpr<'subs, 'prev, 'ctx, W>(
6575 &'subs self,
6576 ctx: &'ctx mut DemangleContext<'subs, W>,
6577 scope: Option<ArgScopeStack<'prev, 'subs>>,
6578 ) -> fmt::Result
6579 where
6580 W: 'subs + DemangleWrite,
6581 {
6582 let needs_parens = match *self {
6583 Expression::FunctionParam(_) | Expression::Primary(ExprPrimary::External(_)) => false,
6584 _ => true,
6585 };
6586
6587 if needs_parens {
6588 write!(ctx, "(")?;
6589 }
6590
6591 self.demangle(ctx, scope)?;
6592
6593 if needs_parens {
6594 write!(ctx, ")")?;
6595 }
6596
6597 Ok(())
6598 }
6599}
6600
6601#[derive(Clone, Debug, PartialEq, Eq)]
6614pub enum UnresolvedName {
6615 Name(BaseUnresolvedName),
6617
6618 Global(BaseUnresolvedName),
6620
6621 Nested1(
6623 UnresolvedTypeHandle,
6624 Vec<UnresolvedQualifierLevel>,
6625 BaseUnresolvedName,
6626 ),
6627
6628 Nested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6630
6631 GlobalNested2(Vec<UnresolvedQualifierLevel>, BaseUnresolvedName),
6633}
6634
6635impl Parse for UnresolvedName {
6636 fn parse<'a, 'b>(
6637 ctx: &'a ParseContext,
6638 subs: &'a mut SubstitutionTable,
6639 input: IndexStr<'b>,
6640 ) -> Result<(UnresolvedName, IndexStr<'b>)> {
6641 try_begin_parse!("UnresolvedName", ctx, input);
6642
6643 if let Ok(tail) = consume(b"gs", input) {
6644 if let Ok((name, tail)) = try_recurse!(BaseUnresolvedName::parse(ctx, subs, tail)) {
6645 return Ok((UnresolvedName::Global(name), tail));
6646 }
6647
6648 let tail = consume(b"sr", tail)?;
6649 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6650 let tail = consume(b"E", tail)?;
6651 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6652 return Ok((UnresolvedName::GlobalNested2(levels, name), tail));
6653 }
6654
6655 if let Ok((name, tail)) = try_recurse!(BaseUnresolvedName::parse(ctx, subs, input)) {
6656 return Ok((UnresolvedName::Name(name), tail));
6657 }
6658
6659 let tail = consume(b"sr", input)?;
6660
6661 if tail.peek() == Some(b'N') {
6662 let tail = consume(b"N", tail).unwrap();
6663 let (ty, tail) = UnresolvedTypeHandle::parse(ctx, subs, tail)?;
6664 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6665 let tail = consume(b"E", tail)?;
6666 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6667 return Ok((UnresolvedName::Nested1(ty, levels, name), tail));
6668 }
6669
6670 if let Ok((ty, tail)) = try_recurse!(UnresolvedTypeHandle::parse(ctx, subs, tail)) {
6671 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6672 return Ok((UnresolvedName::Nested1(ty, vec![], name), tail));
6673 }
6674
6675 let (levels, tail) = one_or_more::<UnresolvedQualifierLevel>(ctx, subs, tail)?;
6676 let tail = consume(b"E", tail)?;
6677 let (name, tail) = BaseUnresolvedName::parse(ctx, subs, tail)?;
6678 Ok((UnresolvedName::Nested2(levels, name), tail))
6679 }
6680}
6681
6682impl<'subs, W> Demangle<'subs, W> for UnresolvedName
6683where
6684 W: 'subs + DemangleWrite,
6685{
6686 fn demangle<'prev, 'ctx>(
6687 &'subs self,
6688 ctx: &'ctx mut DemangleContext<'subs, W>,
6689 scope: Option<ArgScopeStack<'prev, 'subs>>,
6690 ) -> fmt::Result {
6691 let ctx = try_begin_demangle!(self, ctx, scope);
6692
6693 match *self {
6694 UnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6695 UnresolvedName::Global(ref name) => {
6696 write!(ctx, "::")?;
6697 name.demangle(ctx, scope)
6698 }
6699 UnresolvedName::Nested1(ref ty, ref levels, ref name) => {
6700 ty.demangle(ctx, scope)?;
6701 write!(ctx, "::")?;
6702 for lvl in &levels[..] {
6703 lvl.demangle(ctx, scope)?;
6704 write!(ctx, "::")?;
6705 }
6706 name.demangle(ctx, scope)
6707 }
6708 UnresolvedName::Nested2(ref levels, ref name) => {
6709 for lvl in &levels[..] {
6710 lvl.demangle(ctx, scope)?;
6711 write!(ctx, "::")?;
6712 }
6713 name.demangle(ctx, scope)
6714 }
6715 UnresolvedName::GlobalNested2(ref levels, ref name) => {
6717 write!(ctx, "::")?;
6718 for lvl in &levels[..] {
6719 lvl.demangle(ctx, scope)?;
6720 write!(ctx, "::")?;
6721 }
6722 name.demangle(ctx, scope)
6723 }
6724 }
6725 }
6726}
6727
6728#[derive(Clone, Debug, PartialEq, Eq)]
6736pub enum UnresolvedType {
6737 Template(TemplateParam, Option<TemplateArgs>),
6739
6740 Decltype(Decltype),
6742}
6743
6744define_handle! {
6745 pub enum UnresolvedTypeHandle
6747}
6748
6749impl Parse for UnresolvedTypeHandle {
6750 fn parse<'a, 'b>(
6751 ctx: &'a ParseContext,
6752 subs: &'a mut SubstitutionTable,
6753 input: IndexStr<'b>,
6754 ) -> Result<(UnresolvedTypeHandle, IndexStr<'b>)> {
6755 try_begin_parse!("UnresolvedTypeHandle", ctx, input);
6756
6757 if let Ok((param, tail)) = try_recurse!(TemplateParam::parse(ctx, subs, input)) {
6758 let (args, tail) =
6759 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6760 (Some(args), tail)
6761 } else {
6762 (None, tail)
6763 };
6764 let ty = UnresolvedType::Template(param, args);
6765 let ty = Substitutable::UnresolvedType(ty);
6766 let idx = subs.insert(ty);
6767 let handle = UnresolvedTypeHandle::BackReference(idx);
6768 return Ok((handle, tail));
6769 }
6770
6771 if let Ok((decltype, tail)) = try_recurse!(Decltype::parse(ctx, subs, input)) {
6772 let ty = UnresolvedType::Decltype(decltype);
6773 let ty = Substitutable::UnresolvedType(ty);
6774 let idx = subs.insert(ty);
6775 let handle = UnresolvedTypeHandle::BackReference(idx);
6776 return Ok((handle, tail));
6777 }
6778
6779 let (sub, tail) = Substitution::parse(ctx, subs, input)?;
6780 match sub {
6781 Substitution::WellKnown(component) => {
6782 Ok((UnresolvedTypeHandle::WellKnown(component), tail))
6783 }
6784 Substitution::BackReference(idx) => {
6785 Ok((UnresolvedTypeHandle::BackReference(idx), tail))
6788 }
6789 }
6790 }
6791}
6792
6793impl<'subs, W> Demangle<'subs, W> for UnresolvedType
6794where
6795 W: 'subs + DemangleWrite,
6796{
6797 fn demangle<'prev, 'ctx>(
6798 &'subs self,
6799 ctx: &'ctx mut DemangleContext<'subs, W>,
6800 scope: Option<ArgScopeStack<'prev, 'subs>>,
6801 ) -> fmt::Result {
6802 let ctx = try_begin_demangle!(self, ctx, scope);
6803
6804 match *self {
6805 UnresolvedType::Decltype(ref dt) => dt.demangle(ctx, scope),
6806 UnresolvedType::Template(ref param, ref args) => {
6807 if let Some(ref args) = *args {
6808 let scope = scope.push(args);
6809 param.demangle(ctx, scope)?;
6810 args.demangle(ctx, scope)?;
6811 } else {
6812 param.demangle(ctx, scope)?;
6813 }
6814 Ok(())
6815 }
6816 }
6817 }
6818}
6819
6820#[derive(Clone, Debug, PartialEq, Eq)]
6826pub struct UnresolvedQualifierLevel(SimpleId);
6827
6828impl Parse for UnresolvedQualifierLevel {
6829 fn parse<'a, 'b>(
6830 ctx: &'a ParseContext,
6831 subs: &'a mut SubstitutionTable,
6832 input: IndexStr<'b>,
6833 ) -> Result<(UnresolvedQualifierLevel, IndexStr<'b>)> {
6834 try_begin_parse!("UnresolvedQualifierLevel", ctx, input);
6835
6836 let (id, tail) = SimpleId::parse(ctx, subs, input)?;
6837 Ok((UnresolvedQualifierLevel(id), tail))
6838 }
6839}
6840
6841impl<'subs, W> Demangle<'subs, W> for UnresolvedQualifierLevel
6842where
6843 W: 'subs + DemangleWrite,
6844{
6845 #[inline]
6846 fn demangle<'prev, 'ctx>(
6847 &'subs self,
6848 ctx: &'ctx mut DemangleContext<'subs, W>,
6849 scope: Option<ArgScopeStack<'prev, 'subs>>,
6850 ) -> fmt::Result {
6851 let ctx = try_begin_demangle!(self, ctx, scope);
6852
6853 self.0.demangle(ctx, scope)
6854 }
6855}
6856
6857#[derive(Clone, Debug, PartialEq, Eq)]
6863pub struct SimpleId(SourceName, Option<TemplateArgs>);
6864
6865impl Parse for SimpleId {
6866 fn parse<'a, 'b>(
6867 ctx: &'a ParseContext,
6868 subs: &'a mut SubstitutionTable,
6869 input: IndexStr<'b>,
6870 ) -> Result<(SimpleId, IndexStr<'b>)> {
6871 try_begin_parse!("SimpleId", ctx, input);
6872
6873 let (name, tail) = SourceName::parse(ctx, subs, input)?;
6874 let (args, tail) =
6875 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6876 (Some(args), tail)
6877 } else {
6878 (None, tail)
6879 };
6880 Ok((SimpleId(name, args), tail))
6881 }
6882}
6883
6884impl<'subs, W> Demangle<'subs, W> for SimpleId
6885where
6886 W: 'subs + DemangleWrite,
6887{
6888 fn demangle<'prev, 'ctx>(
6889 &'subs self,
6890 ctx: &'ctx mut DemangleContext<'subs, W>,
6891 scope: Option<ArgScopeStack<'prev, 'subs>>,
6892 ) -> fmt::Result {
6893 let ctx = try_begin_demangle!(self, ctx, scope);
6894
6895 self.0.demangle(ctx, scope)?;
6896 if let Some(ref args) = self.1 {
6897 args.demangle(ctx, scope)?;
6898 }
6899 Ok(())
6900 }
6901}
6902
6903#[derive(Clone, Debug, PartialEq, Eq)]
6913pub enum BaseUnresolvedName {
6914 Name(SimpleId),
6916
6917 Operator(OperatorName, Option<TemplateArgs>),
6919
6920 Destructor(DestructorName),
6922}
6923
6924impl Parse for BaseUnresolvedName {
6925 fn parse<'a, 'b>(
6926 ctx: &'a ParseContext,
6927 subs: &'a mut SubstitutionTable,
6928 input: IndexStr<'b>,
6929 ) -> Result<(BaseUnresolvedName, IndexStr<'b>)> {
6930 try_begin_parse!("BaseUnresolvedName", ctx, input);
6931
6932 if let Ok((name, tail)) = try_recurse!(SimpleId::parse(ctx, subs, input)) {
6933 return Ok((BaseUnresolvedName::Name(name), tail));
6934 }
6935
6936 if let Ok(tail) = consume(b"on", input) {
6937 let (opname, tail) = OperatorName::parse(ctx, subs, tail)?;
6938 let (args, tail) =
6939 if let Ok((args, tail)) = try_recurse!(TemplateArgs::parse(ctx, subs, tail)) {
6940 (Some(args), tail)
6941 } else {
6942 (None, tail)
6943 };
6944 return Ok((BaseUnresolvedName::Operator(opname, args), tail));
6945 }
6946
6947 let tail = consume(b"dn", input)?;
6948 let (name, tail) = DestructorName::parse(ctx, subs, tail)?;
6949 Ok((BaseUnresolvedName::Destructor(name), tail))
6950 }
6951}
6952
6953impl<'subs, W> Demangle<'subs, W> for BaseUnresolvedName
6954where
6955 W: 'subs + DemangleWrite,
6956{
6957 fn demangle<'prev, 'ctx>(
6958 &'subs self,
6959 ctx: &'ctx mut DemangleContext<'subs, W>,
6960 scope: Option<ArgScopeStack<'prev, 'subs>>,
6961 ) -> fmt::Result {
6962 let ctx = try_begin_demangle!(self, ctx, scope);
6963
6964 match *self {
6965 BaseUnresolvedName::Name(ref name) => name.demangle(ctx, scope),
6966 BaseUnresolvedName::Destructor(ref dtor) => dtor.demangle(ctx, scope),
6967 BaseUnresolvedName::Operator(ref op, ref args) => {
6968 op.demangle(ctx, scope)?;
6969 if let Some(ref args) = *args {
6970 args.demangle(ctx, scope)?;
6971 }
6972 Ok(())
6973 }
6974 }
6975 }
6976}
6977
6978#[derive(Clone, Debug, PartialEq, Eq)]
6985pub enum DestructorName {
6986 Unresolved(UnresolvedTypeHandle),
6988
6989 Name(SimpleId),
6991}
6992
6993impl Parse for DestructorName {
6994 fn parse<'a, 'b>(
6995 ctx: &'a ParseContext,
6996 subs: &'a mut SubstitutionTable,
6997 input: IndexStr<'b>,
6998 ) -> Result<(DestructorName, IndexStr<'b>)> {
6999 try_begin_parse!("DestructorName", ctx, input);
7000
7001 if let Ok((ty, tail)) = try_recurse!(UnresolvedTypeHandle::parse(ctx, subs, input)) {
7002 return Ok((DestructorName::Unresolved(ty), tail));
7003 }
7004
7005 let (name, tail) = SimpleId::parse(ctx, subs, input)?;
7006 Ok((DestructorName::Name(name), tail))
7007 }
7008}
7009
7010impl<'subs, W> Demangle<'subs, W> for DestructorName
7011where
7012 W: 'subs + DemangleWrite,
7013{
7014 fn demangle<'prev, 'ctx>(
7015 &'subs self,
7016 ctx: &'ctx mut DemangleContext<'subs, W>,
7017 scope: Option<ArgScopeStack<'prev, 'subs>>,
7018 ) -> fmt::Result {
7019 let ctx = try_begin_demangle!(self, ctx, scope);
7020
7021 write!(ctx, "~")?;
7022 match *self {
7023 DestructorName::Unresolved(ref ty) => ty.demangle(ctx, scope),
7024 DestructorName::Name(ref name) => name.demangle(ctx, scope),
7025 }
7026 }
7027}
7028
7029#[derive(Clone, Debug, PartialEq, Eq)]
7041pub enum ExprPrimary {
7042 Literal(TypeHandle, usize, usize),
7044
7045 External(MangledName),
7047}
7048
7049impl Parse for ExprPrimary {
7050 fn parse<'a, 'b>(
7051 ctx: &'a ParseContext,
7052 subs: &'a mut SubstitutionTable,
7053 input: IndexStr<'b>,
7054 ) -> Result<(ExprPrimary, IndexStr<'b>)> {
7055 try_begin_parse!("ExprPrimary", ctx, input);
7056
7057 let tail = consume(b"L", input)?;
7058
7059 if let Ok((ty, tail)) = try_recurse!(TypeHandle::parse(ctx, subs, tail)) {
7060 let start = tail.index();
7061 let num_bytes_in_literal = tail.as_ref().iter().take_while(|&&c| c != b'E').count();
7062 let tail = tail.range_from(num_bytes_in_literal..);
7063 let end = tail.index();
7064 let tail = consume(b"E", tail)?;
7065 let expr = ExprPrimary::Literal(ty, start, end);
7066 return Ok((expr, tail));
7067 }
7068
7069 let (name, tail) = MangledName::parse(ctx, subs, tail)?;
7070 let tail = consume(b"E", tail)?;
7071 let expr = ExprPrimary::External(name);
7072 Ok((expr, tail))
7073 }
7074}
7075
7076impl<'subs, W> Demangle<'subs, W> for ExprPrimary
7077where
7078 W: 'subs + DemangleWrite,
7079{
7080 fn demangle<'prev, 'ctx>(
7081 &'subs self,
7082 ctx: &'ctx mut DemangleContext<'subs, W>,
7083 scope: Option<ArgScopeStack<'prev, 'subs>>,
7084 ) -> fmt::Result {
7085 let ctx = try_begin_demangle!(self, ctx, scope);
7086
7087 fn write_literal<W>(ctx: &mut DemangleContext<W>, start: usize, end: usize) -> fmt::Result
7088 where
7089 W: DemangleWrite,
7090 {
7091 debug_assert!(start <= end);
7092 let start = if start < end && ctx.input[start] == b'n' {
7093 write!(ctx, "-")?;
7094 start + 1
7095 } else {
7096 start
7097 };
7098 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
7099 log!("Error writing literal: {}", e);
7100 fmt::Error
7101 })?;
7102 ctx.write_str(s)
7103 }
7104
7105 match *self {
7106 ExprPrimary::External(ref name) => {
7107 let saved_show_params = ctx.show_params;
7108 ctx.show_params = true;
7109 let ret = name.demangle(ctx, scope);
7110 ctx.show_params = saved_show_params;
7111 ret
7112 }
7113 ExprPrimary::Literal(
7114 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool)),
7115 start,
7116 end,
7117 ) => match &ctx.input[start..end] {
7118 b"0" => write!(ctx, "false"),
7119 b"1" => write!(ctx, "true"),
7120 _ => {
7121 write!(ctx, "(bool)")?;
7122 write_literal(ctx, start, end)
7123 }
7124 },
7125 ExprPrimary::Literal(
7126 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Nullptr)),
7127 _,
7128 _,
7129 ) => write!(ctx, "nullptr"),
7130 ExprPrimary::Literal(
7131 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Double)),
7132 start,
7133 end,
7134 )
7135 | ExprPrimary::Literal(
7136 ref ty @ TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Float)),
7137 start,
7138 end,
7139 ) => {
7140 if ctx.show_expression_literal_types {
7141 write!(ctx, "(")?;
7142 ty.demangle(ctx, scope)?;
7143 write!(ctx, ")")?;
7144 }
7145 let start = if start < end && ctx.input[start] == b'n' {
7146 write!(ctx, "-[")?;
7147 start + 1
7148 } else {
7149 write!(ctx, "[")?;
7150 start
7151 };
7152 let s = str::from_utf8(&ctx.input[start..end]).map_err(|e| {
7153 log!("Error writing literal: {}", e);
7154 fmt::Error
7155 })?;
7156 ctx.write_str(s)?;
7157 write!(ctx, "]")
7158 }
7159 ExprPrimary::Literal(
7160 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int)),
7161 start,
7162 end,
7163 ) => write_literal(ctx, start, end),
7164 ExprPrimary::Literal(ref ty, start, end) => {
7165 if ctx.show_expression_literal_types {
7166 write!(ctx, "(")?;
7167 ty.demangle(ctx, scope)?;
7168 write!(ctx, ")")?;
7169 }
7170 write_literal(ctx, start, end)
7171 }
7172 }
7173 }
7174}
7175
7176#[derive(Clone, Debug, PartialEq, Eq)]
7182pub struct Initializer(Vec<Expression>);
7183
7184impl Parse for Initializer {
7185 fn parse<'a, 'b>(
7186 ctx: &'a ParseContext,
7187 subs: &'a mut SubstitutionTable,
7188 input: IndexStr<'b>,
7189 ) -> Result<(Initializer, IndexStr<'b>)> {
7190 try_begin_parse!("Initializer", ctx, input);
7191
7192 let tail = consume(b"pi", input)?;
7193 let (exprs, tail) = zero_or_more::<Expression>(ctx, subs, tail)?;
7194 let tail = consume(b"E", tail)?;
7195 Ok((Initializer(exprs), tail))
7196 }
7197}
7198
7199impl<'subs, W> Demangle<'subs, W> for Initializer
7200where
7201 W: 'subs + DemangleWrite,
7202{
7203 fn demangle<'prev, 'ctx>(
7204 &'subs self,
7205 ctx: &'ctx mut DemangleContext<'subs, W>,
7206 scope: Option<ArgScopeStack<'prev, 'subs>>,
7207 ) -> fmt::Result {
7208 let ctx = try_begin_demangle!(self, ctx, scope);
7209
7210 write!(ctx, "(")?;
7211 let mut need_comma = false;
7212 for expr in &self.0 {
7213 if need_comma {
7214 write!(ctx, ", ")?;
7215 }
7216 expr.demangle(ctx, scope)?;
7217 need_comma = true;
7218 }
7219 write!(ctx, ")")?;
7220 Ok(())
7221 }
7222}
7223
7224#[derive(Clone, Debug, PartialEq, Eq)]
7232pub enum LocalName {
7233 Relative(Box<Encoding>, Option<Box<Name>>, Option<Discriminator>),
7236
7237 Default(Box<Encoding>, Option<usize>, Box<Name>),
7239}
7240
7241impl Parse for LocalName {
7242 fn parse<'a, 'b>(
7243 ctx: &'a ParseContext,
7244 subs: &'a mut SubstitutionTable,
7245 input: IndexStr<'b>,
7246 ) -> Result<(LocalName, IndexStr<'b>)> {
7247 try_begin_parse!("LocalName", ctx, input);
7248
7249 let tail = consume(b"Z", input)?;
7250 let (encoding, tail) = Encoding::parse(ctx, subs, tail)?;
7251 let tail = consume(b"E", tail)?;
7252
7253 if let Ok(tail) = consume(b"s", tail) {
7254 let (disc, tail) =
7255 if let Ok((disc, tail)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
7256 (Some(disc), tail)
7257 } else {
7258 (None, tail)
7259 };
7260 return Ok((LocalName::Relative(Box::new(encoding), None, disc), tail));
7261 }
7262
7263 if let Ok(tail) = consume(b"d", tail) {
7264 let (param, tail) =
7265 if let Ok((num, tail)) = try_recurse!(Number::parse(ctx, subs, tail)) {
7266 (Some(num as _), tail)
7267 } else {
7268 (None, tail)
7269 };
7270 let tail = consume(b"_", tail)?;
7271 let (name, tail) = Name::parse(ctx, subs, tail)?;
7272 return Ok((
7273 LocalName::Default(Box::new(encoding), param, Box::new(name)),
7274 tail,
7275 ));
7276 }
7277
7278 let (name, tail) = Name::parse(ctx, subs, tail)?;
7279 let (disc, tail) =
7280 if let Ok((disc, tail)) = try_recurse!(Discriminator::parse(ctx, subs, tail)) {
7281 (Some(disc), tail)
7282 } else {
7283 (None, tail)
7284 };
7285
7286 Ok((
7287 LocalName::Relative(Box::new(encoding), Some(Box::new(name)), disc),
7288 tail,
7289 ))
7290 }
7291}
7292
7293impl<'subs, W> Demangle<'subs, W> for LocalName
7294where
7295 W: 'subs + DemangleWrite,
7296{
7297 fn demangle<'prev, 'ctx>(
7298 &'subs self,
7299 ctx: &'ctx mut DemangleContext<'subs, W>,
7300 scope: Option<ArgScopeStack<'prev, 'subs>>,
7301 ) -> fmt::Result {
7302 let ctx = try_begin_demangle!(self, ctx, scope);
7303
7304 let saved_show_params = ctx.show_params;
7305 ctx.show_params = true;
7306 let ret = match *self {
7307 LocalName::Relative(ref encoding, Some(ref name), _) => {
7308 encoding.demangle(ctx, scope)?;
7309 write!(ctx, "::")?;
7310 name.demangle(ctx, scope)
7311 }
7312 LocalName::Relative(ref encoding, None, _) => {
7313 encoding.demangle(ctx, scope)?;
7315 write!(ctx, "::string literal")?;
7316 Ok(())
7317 }
7318 LocalName::Default(ref encoding, _, _) => encoding.demangle(ctx, scope),
7319 };
7320 ctx.show_params = saved_show_params;
7321 ret
7322 }
7323}
7324
7325impl GetTemplateArgs for LocalName {
7326 fn get_template_args<'a>(&'a self, subs: &'a SubstitutionTable) -> Option<&'a TemplateArgs> {
7327 match *self {
7328 LocalName::Relative(_, None, _) => None,
7329 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
7330 name.get_template_args(subs)
7331 }
7332 }
7333 }
7334}
7335
7336impl<'a> GetLeafName<'a> for LocalName {
7337 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7338 match *self {
7339 LocalName::Relative(_, None, _) => None,
7340 LocalName::Relative(_, Some(ref name), _) | LocalName::Default(_, _, ref name) => {
7341 name.get_leaf_name(subs)
7342 }
7343 }
7344 }
7345}
7346
7347#[derive(Clone, Debug, PartialEq, Eq)]
7354pub struct Discriminator(usize);
7355
7356impl Parse for Discriminator {
7357 fn parse<'a, 'b>(
7358 ctx: &'a ParseContext,
7359 _subs: &'a mut SubstitutionTable,
7360 input: IndexStr<'b>,
7361 ) -> Result<(Discriminator, IndexStr<'b>)> {
7362 try_begin_parse!("Discriminator", ctx, input);
7363
7364 let tail = consume(b"_", input)?;
7365
7366 if let Ok(tail) = consume(b"_", tail) {
7367 let (num, tail) = parse_number(10, false, tail)?;
7368 debug_assert!(num >= 0);
7369 if num < 10 {
7370 return Err(error::Error::UnexpectedText);
7371 }
7372 let tail = consume(b"_", tail)?;
7373 return Ok((Discriminator(num as _), tail));
7374 }
7375
7376 match tail.try_split_at(1) {
7377 None => Err(error::Error::UnexpectedEnd),
7378 Some((head, tail)) => match head.as_ref()[0] {
7379 b'0' => Ok((Discriminator(0), tail)),
7380 b'1' => Ok((Discriminator(1), tail)),
7381 b'2' => Ok((Discriminator(2), tail)),
7382 b'3' => Ok((Discriminator(3), tail)),
7383 b'4' => Ok((Discriminator(4), tail)),
7384 b'5' => Ok((Discriminator(5), tail)),
7385 b'6' => Ok((Discriminator(6), tail)),
7386 b'7' => Ok((Discriminator(7), tail)),
7387 b'8' => Ok((Discriminator(8), tail)),
7388 b'9' => Ok((Discriminator(9), tail)),
7389 _ => Err(error::Error::UnexpectedText),
7390 },
7391 }
7392 }
7393}
7394
7395#[derive(Clone, Debug, PartialEq, Eq)]
7401pub struct ClosureTypeName(LambdaSig, Option<usize>);
7402
7403impl Parse for ClosureTypeName {
7404 fn parse<'a, 'b>(
7405 ctx: &'a ParseContext,
7406 subs: &'a mut SubstitutionTable,
7407 input: IndexStr<'b>,
7408 ) -> Result<(ClosureTypeName, IndexStr<'b>)> {
7409 try_begin_parse!("ClosureTypeName", ctx, input);
7410
7411 let tail = consume(b"Ul", input)?;
7412 let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
7413 let tail = consume(b"E", tail)?;
7414 let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
7415 (Some(num as _), tail)
7416 } else {
7417 (None, tail)
7418 };
7419 let tail = consume(b"_", tail)?;
7420 Ok((ClosureTypeName(sig, num), tail))
7421 }
7422}
7423
7424impl<'subs, W> Demangle<'subs, W> for ClosureTypeName
7425where
7426 W: 'subs + DemangleWrite,
7427{
7428 fn demangle<'prev, 'ctx>(
7429 &'subs self,
7430 ctx: &'ctx mut DemangleContext<'subs, W>,
7431 scope: Option<ArgScopeStack<'prev, 'subs>>,
7432 ) -> fmt::Result {
7433 let ctx = try_begin_demangle!(self, ctx, scope);
7434
7435 write!(ctx, "{{lambda(")?;
7436 self.0.demangle(ctx, scope)?;
7437 write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
7438 Ok(())
7439 }
7440}
7441
7442impl<'subs> ArgScope<'subs, 'subs> for ClosureTypeName {
7443 fn leaf_name(&'subs self) -> Result<LeafName<'subs>> {
7444 Ok(LeafName::Closure(self))
7445 }
7446
7447 fn get_template_arg(
7448 &'subs self,
7449 _: usize,
7450 ) -> Result<(&'subs TemplateArg, &'subs TemplateArgs)> {
7451 Err(error::Error::BadTemplateArgReference)
7452 }
7453
7454 fn get_function_arg(&'subs self, _: usize) -> Result<&'subs Type> {
7455 Err(error::Error::BadFunctionArgReference)
7456 }
7457}
7458
7459impl<'a> GetLeafName<'a> for ClosureTypeName {
7460 #[inline]
7461 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7462 Some(LeafName::Closure(self))
7463 }
7464}
7465
7466impl ClosureTypeName {
7467 #[inline]
7468 fn starts_with(byte: u8, input: &IndexStr) -> bool {
7469 byte == b'U' && input.peek_second().map(|b| b == b'l').unwrap_or(false)
7470 }
7471}
7472
7473#[derive(Clone, Debug, PartialEq, Eq)]
7479pub struct LambdaSig(Vec<TypeHandle>);
7480
7481impl LambdaSig {
7482 fn demangle_args<'subs, 'prev, 'ctx, W>(
7483 &'subs self,
7484 ctx: &'ctx mut DemangleContext<'subs, W>,
7485 scope: Option<ArgScopeStack<'prev, 'subs>>,
7486 ) -> fmt::Result
7487 where
7488 W: 'subs + DemangleWrite,
7489 {
7490 let mut need_comma = false;
7491 for ty in &self.0 {
7492 if need_comma {
7493 write!(ctx, ", ")?;
7494 }
7495 ty.demangle(ctx, scope)?;
7496 need_comma = true;
7497 }
7498 Ok(())
7499 }
7500}
7501
7502impl Parse for LambdaSig {
7503 fn parse<'a, 'b>(
7504 ctx: &'a ParseContext,
7505 subs: &'a mut SubstitutionTable,
7506 input: IndexStr<'b>,
7507 ) -> Result<(LambdaSig, IndexStr<'b>)> {
7508 try_begin_parse!("LambdaSig", ctx, input);
7509
7510 let (types, tail) = if let Ok(tail) = consume(b"v", input) {
7511 (vec![], tail)
7512 } else {
7513 one_or_more::<TypeHandle>(ctx, subs, input)?
7514 };
7515 Ok((LambdaSig(types), tail))
7516 }
7517}
7518
7519impl<'subs, W> Demangle<'subs, W> for LambdaSig
7520where
7521 W: 'subs + DemangleWrite,
7522{
7523 fn demangle<'prev, 'ctx>(
7524 &'subs self,
7525 ctx: &'ctx mut DemangleContext<'subs, W>,
7526 scope: Option<ArgScopeStack<'prev, 'subs>>,
7527 ) -> fmt::Result {
7528 let ctx = try_begin_demangle!(self, ctx, scope);
7529
7530 ctx.is_lambda_arg = true;
7531 let r = self.demangle_args(ctx, scope);
7532 ctx.is_lambda_arg = false;
7533 r
7534 }
7535}
7536
7537#[derive(Clone, Debug, PartialEq, Eq)]
7543pub struct DataMemberPrefix(SourceName);
7544
7545impl Parse for DataMemberPrefix {
7546 fn parse<'a, 'b>(
7547 ctx: &'a ParseContext,
7548 subs: &'a mut SubstitutionTable,
7549 input: IndexStr<'b>,
7550 ) -> Result<(DataMemberPrefix, IndexStr<'b>)> {
7551 try_begin_parse!("DataMemberPrefix", ctx, input);
7552
7553 let (name, tail) = SourceName::parse(ctx, subs, input)?;
7554 let tail = consume(b"M", tail)?;
7555 Ok((DataMemberPrefix(name), tail))
7556 }
7557}
7558
7559impl<'a> GetLeafName<'a> for DataMemberPrefix {
7560 #[inline]
7561 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7562 Some(LeafName::SourceName(&self.0))
7563 }
7564}
7565
7566impl<'subs, W> Demangle<'subs, W> for DataMemberPrefix
7567where
7568 W: 'subs + DemangleWrite,
7569{
7570 #[inline]
7571 fn demangle<'prev, 'ctx>(
7572 &'subs self,
7573 ctx: &'ctx mut DemangleContext<'subs, W>,
7574 scope: Option<ArgScopeStack<'prev, 'subs>>,
7575 ) -> fmt::Result {
7576 let ctx = try_begin_demangle!(self, ctx, scope);
7577
7578 ctx.push_demangle_node(DemangleNodeType::DataMemberPrefix);
7579 let ret = self.0.demangle(ctx, scope);
7580 ctx.pop_demangle_node();
7581 ret
7582 }
7583}
7584
7585#[derive(Clone, Debug, PartialEq, Eq)]
7602pub enum Substitution {
7603 BackReference(usize),
7606
7607 WellKnown(WellKnownComponent),
7611}
7612
7613impl Parse for Substitution {
7614 fn parse<'a, 'b>(
7615 ctx: &'a ParseContext,
7616 subs: &'a mut SubstitutionTable,
7617 input: IndexStr<'b>,
7618 ) -> Result<(Substitution, IndexStr<'b>)> {
7619 try_begin_parse!("Substitution", ctx, input);
7620
7621 if let Ok((well_known, tail)) = try_recurse!(WellKnownComponent::parse(ctx, subs, input)) {
7622 return Ok((Substitution::WellKnown(well_known), tail));
7623 }
7624
7625 let tail = consume(b"S", input)?;
7626 let (idx, tail) = if let Ok((idx, tail)) = try_recurse!(SeqId::parse(ctx, subs, tail)) {
7627 (idx.0 + 1, tail)
7628 } else {
7629 (0, tail)
7630 };
7631
7632 if !subs.contains(idx) {
7633 return Err(error::Error::BadBackReference);
7634 }
7635
7636 let tail = consume(b"_", tail)?;
7637 log!("Found a reference to @ {}", idx);
7638 Ok((Substitution::BackReference(idx), tail))
7639 }
7640}
7641
7642define_vocabulary! {
7643#[derive(Clone, Debug, PartialEq, Eq)]
7647 pub enum WellKnownComponent {
7648 Std (b"St", "std"),
7649 StdAllocator (b"Sa", "std::allocator"),
7650 StdString1 (b"Sb", "std::basic_string"),
7651 StdString2 (b"Ss", "std::string"),
7652 StdIstream (b"Si", "std::basic_istream<char, std::char_traits<char> >"),
7653 StdOstream (b"So", "std::ostream"),
7654 StdIostream (b"Sd", "std::basic_iostream<char, std::char_traits<char> >")
7655 }
7656}
7657
7658impl<'a> GetLeafName<'a> for WellKnownComponent {
7659 fn get_leaf_name(&'a self, _: &'a SubstitutionTable) -> Option<LeafName<'a>> {
7660 match *self {
7661 WellKnownComponent::Std => None,
7662 _ => Some(LeafName::WellKnownComponent(self)),
7663 }
7664 }
7665}
7666
7667impl<'a> ArgScope<'a, 'a> for WellKnownComponent {
7668 fn leaf_name(&'a self) -> Result<LeafName<'a>> {
7669 Ok(LeafName::WellKnownComponent(self))
7670 }
7671
7672 fn get_template_arg(&'a self, _: usize) -> Result<(&'a TemplateArg, &'a TemplateArgs)> {
7673 Err(error::Error::BadTemplateArgReference)
7674 }
7675
7676 fn get_function_arg(&'a self, _: usize) -> Result<&'a Type> {
7677 Err(error::Error::BadFunctionArgReference)
7678 }
7679}
7680
7681impl<'subs, W> DemangleAsLeaf<'subs, W> for WellKnownComponent
7682where
7683 W: 'subs + DemangleWrite,
7684{
7685 fn demangle_as_leaf<'me, 'ctx>(
7686 &'me self,
7687 ctx: &'ctx mut DemangleContext<'subs, W>,
7688 ) -> fmt::Result {
7689 match *self {
7690 WellKnownComponent::Std => {
7691 panic!("should never treat `WellKnownComponent::Std` as a leaf name")
7692 }
7693 WellKnownComponent::StdAllocator => write!(ctx, "allocator"),
7694 WellKnownComponent::StdString1 => write!(ctx, "basic_string"),
7695 WellKnownComponent::StdString2 => write!(ctx, "string"),
7696 WellKnownComponent::StdIstream => write!(ctx, "basic_istream"),
7697 WellKnownComponent::StdOstream => write!(ctx, "ostream"),
7698 WellKnownComponent::StdIostream => write!(ctx, "basic_iostream"),
7699 }
7700 }
7701}
7702
7703#[derive(Clone, Debug, PartialEq, Eq)]
7756pub enum SpecialName {
7757 VirtualTable(TypeHandle),
7759
7760 Vtt(TypeHandle),
7762
7763 Typeinfo(TypeHandle),
7765
7766 TypeinfoName(TypeHandle),
7768
7769 VirtualOverrideThunk(CallOffset, Box<Encoding>),
7771
7772 VirtualOverrideThunkCovariant(CallOffset, CallOffset, Box<Encoding>),
7774
7775 Guard(Name),
7777
7778 GuardTemporary(Name, usize),
7781
7782 ConstructionVtable(TypeHandle, usize, TypeHandle),
7784
7785 TypeinfoFunction(TypeHandle),
7787
7788 TlsInit(Name),
7790
7791 TlsWrapper(Name),
7793
7794 JavaResource(Vec<ResourceName>),
7796
7797 TransactionClone(Box<Encoding>),
7799
7800 NonTransactionClone(Box<Encoding>),
7802}
7803
7804impl Parse for SpecialName {
7805 fn parse<'a, 'b>(
7806 ctx: &'a ParseContext,
7807 subs: &'a mut SubstitutionTable,
7808 input: IndexStr<'b>,
7809 ) -> Result<(SpecialName, IndexStr<'b>)> {
7810 try_begin_parse!("SpecialName", ctx, input);
7811
7812 let (head, tail) = match input.try_split_at(2) {
7813 None => return Err(error::Error::UnexpectedEnd),
7814 Some((head, tail)) => (head, tail),
7815 };
7816
7817 match head.as_ref() {
7818 b"TV" => {
7819 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7820 Ok((SpecialName::VirtualTable(ty), tail))
7821 }
7822 b"TT" => {
7823 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7824 Ok((SpecialName::Vtt(ty), tail))
7825 }
7826 b"TI" => {
7827 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7828 Ok((SpecialName::Typeinfo(ty), tail))
7829 }
7830 b"TS" => {
7831 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7832 Ok((SpecialName::TypeinfoName(ty), tail))
7833 }
7834 b"Tc" => {
7835 let (first, tail) = CallOffset::parse(ctx, subs, tail)?;
7836 let (second, tail) = CallOffset::parse(ctx, subs, tail)?;
7837 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7838 Ok((
7839 SpecialName::VirtualOverrideThunkCovariant(first, second, Box::new(base)),
7840 tail,
7841 ))
7842 }
7843 b"Th" | b"Tv" => {
7844 let tail = consume(b"T", input).unwrap();
7847 let (offset, tail) = CallOffset::parse(ctx, subs, tail)?;
7848 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7849 Ok((
7850 SpecialName::VirtualOverrideThunk(offset, Box::new(base)),
7851 tail,
7852 ))
7853 }
7854 b"TC" => {
7855 let (ty1, tail) = TypeHandle::parse(ctx, subs, tail)?;
7856 let (n, tail) = parse_number(10, false, tail)?;
7857 let tail = consume(b"_", tail)?;
7858 let (ty2, tail) = TypeHandle::parse(ctx, subs, tail)?;
7859 Ok((SpecialName::ConstructionVtable(ty1, n as usize, ty2), tail))
7860 }
7861 b"TF" => {
7862 let (ty, tail) = TypeHandle::parse(ctx, subs, tail)?;
7863 Ok((SpecialName::TypeinfoFunction(ty), tail))
7864 }
7865 b"TH" => {
7866 let (name, tail) = Name::parse(ctx, subs, tail)?;
7867 Ok((SpecialName::TlsInit(name), tail))
7868 }
7869 b"TW" => {
7870 let (name, tail) = Name::parse(ctx, subs, tail)?;
7871 Ok((SpecialName::TlsWrapper(name), tail))
7872 }
7873 b"GV" => {
7874 let (name, tail) = Name::parse(ctx, subs, tail)?;
7875 Ok((SpecialName::Guard(name), tail))
7876 }
7877 b"GR" => {
7878 let (name, tail) = Name::parse(ctx, subs, tail)?;
7879 let (idx, tail) = if let Ok(tail) = consume(b"_", tail) {
7880 (0, tail)
7881 } else {
7882 let (idx, tail) = SeqId::parse(ctx, subs, tail)?;
7883 let tail = consume(b"_", tail)?;
7884 (idx.0 + 1, tail)
7885 };
7886 Ok((SpecialName::GuardTemporary(name, idx), tail))
7887 }
7888 b"Gr" => {
7889 let (resource_name_len, tail) = parse_number(10, false, tail)?;
7890 if resource_name_len == 0 {
7891 return Err(error::Error::UnexpectedText);
7892 }
7893
7894 let (head, tail) = match tail.try_split_at(resource_name_len as _) {
7895 Some((head, tail)) => (head, tail),
7896 None => return Err(error::Error::UnexpectedEnd),
7897 };
7898
7899 let head = consume(b"_", head)?;
7900
7901 let (resource_names, empty) = zero_or_more::<ResourceName>(ctx, subs, head)?;
7902 if !empty.is_empty() {
7903 return Err(error::Error::UnexpectedText);
7904 }
7905
7906 Ok((SpecialName::JavaResource(resource_names), tail))
7907 }
7908 b"GT" => {
7909 match tail.next_or(error::Error::UnexpectedEnd)? {
7910 (b'n', tail) => {
7911 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7912 Ok((SpecialName::NonTransactionClone(Box::new(base)), tail))
7913 }
7914 (b't', tail) | (_, tail) => {
7917 let (base, tail) = Encoding::parse(ctx, subs, tail)?;
7918 Ok((SpecialName::TransactionClone(Box::new(base)), tail))
7919 }
7920 }
7921 }
7922 _ => Err(error::Error::UnexpectedText),
7923 }
7924 }
7925}
7926
7927impl<'subs, W> Demangle<'subs, W> for SpecialName
7928where
7929 W: 'subs + DemangleWrite,
7930{
7931 fn demangle<'prev, 'ctx>(
7932 &'subs self,
7933 ctx: &'ctx mut DemangleContext<'subs, W>,
7934 scope: Option<ArgScopeStack<'prev, 'subs>>,
7935 ) -> fmt::Result {
7936 let ctx = try_begin_demangle!(self, ctx, scope);
7937
7938 match *self {
7939 SpecialName::VirtualTable(ref ty) => {
7940 write!(ctx, "{{vtable(")?;
7941 ctx.push_demangle_node(DemangleNodeType::VirtualTable);
7942 ty.demangle(ctx, scope)?;
7943 ctx.pop_demangle_node();
7944 write!(ctx, ")}}")?;
7945 Ok(())
7946 }
7947 SpecialName::Vtt(ref ty) => {
7948 write!(ctx, "{{vtt(")?;
7949 ty.demangle(ctx, scope)?;
7950 write!(ctx, ")}}")?;
7951 Ok(())
7952 }
7953 SpecialName::Typeinfo(ref ty) => {
7954 write!(ctx, "typeinfo for ")?;
7955 ty.demangle(ctx, scope)
7956 }
7957 SpecialName::TypeinfoName(ref ty) => {
7958 write!(ctx, "typeinfo name for ")?;
7959 ty.demangle(ctx, scope)
7960 }
7961 SpecialName::VirtualOverrideThunk(ref offset, ref encoding) => {
7962 write!(ctx, "{{virtual override thunk(")?;
7963 offset.demangle(ctx, scope)?;
7964 write!(ctx, ", ")?;
7965 encoding.demangle(ctx, scope)?;
7966 write!(ctx, ")}}")?;
7967 Ok(())
7968 }
7969 SpecialName::VirtualOverrideThunkCovariant(
7970 ref this_offset,
7971 ref result_offset,
7972 ref encoding,
7973 ) => {
7974 write!(ctx, "{{virtual override thunk(")?;
7975 this_offset.demangle(ctx, scope)?;
7976 write!(ctx, ", ")?;
7977 result_offset.demangle(ctx, scope)?;
7978 write!(ctx, ", ")?;
7979 encoding.demangle(ctx, scope)?;
7980 write!(ctx, ")}}")?;
7981 Ok(())
7982 }
7983 SpecialName::Guard(ref name) => {
7984 write!(ctx, "guard variable for ")?;
7985 name.demangle(ctx, scope)
7986 }
7987 SpecialName::GuardTemporary(ref name, n) => {
7988 write!(ctx, "reference temporary #{} for ", n)?;
7989 name.demangle(ctx, scope)
7990 }
7991 SpecialName::ConstructionVtable(ref ty1, _, ref ty2) => {
7992 write!(ctx, "construction vtable for ")?;
7993 ty1.demangle(ctx, scope)?;
7994 write!(ctx, "-in-")?;
7995 ty2.demangle(ctx, scope)
7996 }
7997 SpecialName::TypeinfoFunction(ref ty) => {
7998 write!(ctx, "typeinfo fn for ")?;
7999 ty.demangle(ctx, scope)
8000 }
8001 SpecialName::TlsInit(ref name) => {
8002 write!(ctx, "TLS init function for ")?;
8003 name.demangle(ctx, scope)
8004 }
8005 SpecialName::TlsWrapper(ref name) => {
8006 write!(ctx, "TLS wrapper function for ")?;
8007 name.demangle(ctx, scope)
8008 }
8009 SpecialName::TransactionClone(ref encoding) => {
8010 write!(ctx, "transaction clone for ")?;
8011 encoding.demangle(ctx, scope)
8012 }
8013 SpecialName::NonTransactionClone(ref encoding) => {
8014 write!(ctx, "non-transaction clone for ")?;
8015 encoding.demangle(ctx, scope)
8016 }
8017 SpecialName::JavaResource(ref names) => {
8018 write!(ctx, "java resource ")?;
8019 for name in names {
8020 name.demangle(ctx, scope)?;
8021 }
8022 Ok(())
8023 }
8024 }
8025 }
8026}
8027
8028#[derive(Clone, Debug, PartialEq, Eq)]
8030pub struct ResourceName {
8031 start: usize,
8032 end: usize,
8033}
8034
8035impl Parse for ResourceName {
8036 fn parse<'a, 'b>(
8037 ctx: &'a ParseContext,
8038 _subs: &'a mut SubstitutionTable,
8039 input: IndexStr<'b>,
8040 ) -> Result<(ResourceName, IndexStr<'b>)> {
8041 try_begin_parse!("ResourceName", ctx, input);
8042
8043 if input.is_empty() {
8044 return Err(error::Error::UnexpectedEnd);
8045 }
8046
8047 let mut end = input
8048 .as_ref()
8049 .iter()
8050 .map(|&c| c as char)
8051 .take_while(|&c| c != '$' || c.is_digit(36))
8052 .count();
8053
8054 if end == 0 {
8055 return Err(error::Error::UnexpectedText);
8056 }
8057
8058 if input.range_from(end..).peek() == Some(b'$') {
8059 match input.range_from(end..).peek_second() {
8060 Some(b'S') | Some(b'_') | Some(b'$') => end += 2,
8061 _ => return Err(error::Error::UnexpectedText),
8062 }
8063 }
8064
8065 let tail = input.range_from(end..);
8066
8067 let resource_name = ResourceName {
8068 start: input.index(),
8069 end: tail.index(),
8070 };
8071
8072 Ok((resource_name, tail))
8073 }
8074}
8075
8076impl<'subs, W> Demangle<'subs, W> for ResourceName
8077where
8078 W: 'subs + DemangleWrite,
8079{
8080 #[inline]
8081 fn demangle<'prev, 'ctx>(
8082 &'subs self,
8083 ctx: &'ctx mut DemangleContext<'subs, W>,
8084 scope: Option<ArgScopeStack<'prev, 'subs>>,
8085 ) -> fmt::Result {
8086 let ctx = try_begin_demangle!(self, ctx, scope);
8087
8088 let mut i = self.start;
8089 while i < self.end {
8090 let ch = ctx.input[i];
8091 if ch == b'$' {
8092 i += 1;
8094 match ctx.input[i] {
8095 b'S' => write!(ctx, "{}", '/')?,
8096 b'_' => write!(ctx, "{}", '.')?,
8097 b'$' => write!(ctx, "{}", '$')?,
8098 _ => {
8099 }
8101 }
8102 } else {
8103 write!(ctx, "{}", ch as char)?;
8104 }
8105 i += 1;
8106 }
8107
8108 Ok(())
8109 }
8110}
8111
8112#[derive(Clone, Debug, PartialEq, Eq)]
8120pub struct SubobjectExpr {
8121 ty: TypeHandle,
8122 expr: Box<Expression>,
8123 offset: isize,
8124}
8125
8126impl Parse for SubobjectExpr {
8127 fn parse<'a, 'b>(
8128 ctx: &'a ParseContext,
8129 subs: &'a mut SubstitutionTable,
8130 input: IndexStr<'b>,
8131 ) -> Result<(SubobjectExpr, IndexStr<'b>)> {
8132 try_begin_parse!("SubobjectExpr", ctx, input);
8133
8134 let (ty, tail) = TypeHandle::parse(ctx, subs, input)?;
8135 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
8136 let (offset, tail) = parse_number(10, true, tail).unwrap_or((0, tail));
8137
8138 let tail = consume(b"E", tail)?;
8140 Ok((
8141 SubobjectExpr {
8142 ty: ty,
8143 expr: Box::new(expr),
8144 offset: offset,
8145 },
8146 tail,
8147 ))
8148 }
8149}
8150
8151impl<'subs, W> Demangle<'subs, W> for SubobjectExpr
8152where
8153 W: 'subs + DemangleWrite,
8154{
8155 #[inline]
8156 fn demangle<'prev, 'ctx>(
8157 &'subs self,
8158 ctx: &'ctx mut DemangleContext<'subs, W>,
8159 scope: Option<ArgScopeStack<'prev, 'subs>>,
8160 ) -> fmt::Result {
8161 let ctx = try_begin_demangle!(self, ctx, scope);
8162
8163 self.expr.demangle(ctx, scope)?;
8164 write!(ctx, ".<")?;
8165 self.ty.demangle(ctx, scope)?;
8166 write!(ctx, " at offset {}>", self.offset)
8167 }
8168}
8169
8170#[derive(Clone, Debug, PartialEq, Eq)]
8183pub enum FoldExpr {
8184 UnaryLeft(SimpleOperatorName, Box<Expression>),
8186 UnaryRight(SimpleOperatorName, Box<Expression>),
8188 BinaryLeft(SimpleOperatorName, Box<Expression>, Box<Expression>),
8190 BinaryRight(SimpleOperatorName, Box<Expression>, Box<Expression>),
8192}
8193
8194impl Parse for FoldExpr {
8195 fn parse<'a, 'b>(
8196 ctx: &'a ParseContext,
8197 subs: &'a mut SubstitutionTable,
8198 input: IndexStr<'b>,
8199 ) -> Result<(FoldExpr, IndexStr<'b>)> {
8200 try_begin_parse!("FoldExpr", ctx, input);
8201
8202 let tail = consume(b"f", input)?;
8203 if let Ok(tail) = consume(b"l", tail) {
8204 let (operator, tail) = SimpleOperatorName::parse(ctx, subs, tail)?;
8205 if operator.arity() != 2 {
8207 return Err(error::Error::UnexpectedText);
8208 }
8209 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
8210 return Ok((FoldExpr::UnaryLeft(operator, Box::new(expr)), tail));
8211 }
8212 if let Ok(tail) = consume(b"r", tail) {
8213 let (operator, tail) = SimpleOperatorName::parse(ctx, subs, tail)?;
8214 if operator.arity() != 2 {
8216 return Err(error::Error::UnexpectedText);
8217 }
8218 let (expr, tail) = Expression::parse(ctx, subs, tail)?;
8219 return Ok((FoldExpr::UnaryRight(operator, Box::new(expr)), tail));
8220 }
8221 if let Ok(tail) = consume(b"L", tail) {
8222 let (operator, tail) = SimpleOperatorName::parse(ctx, subs, tail)?;
8223 if operator.arity() != 2 {
8225 return Err(error::Error::UnexpectedText);
8226 }
8227 let (expr1, tail) = Expression::parse(ctx, subs, tail)?;
8228 let (expr2, tail) = Expression::parse(ctx, subs, tail)?;
8229 return Ok((
8230 FoldExpr::BinaryLeft(operator, Box::new(expr1), Box::new(expr2)),
8231 tail,
8232 ));
8233 }
8234 if let Ok(tail) = consume(b"R", tail) {
8235 let (operator, tail) = SimpleOperatorName::parse(ctx, subs, tail)?;
8236 if operator.arity() != 2 {
8238 return Err(error::Error::UnexpectedText);
8239 }
8240 let (expr1, tail) = Expression::parse(ctx, subs, tail)?;
8241 let (expr2, tail) = Expression::parse(ctx, subs, tail)?;
8242 return Ok((
8243 FoldExpr::BinaryRight(operator, Box::new(expr1), Box::new(expr2)),
8244 tail,
8245 ));
8246 }
8247
8248 Err(error::Error::UnexpectedText)
8249 }
8250}
8251
8252impl<'subs, W> Demangle<'subs, W> for FoldExpr
8253where
8254 W: 'subs + DemangleWrite,
8255{
8256 #[inline]
8257 fn demangle<'prev, 'ctx>(
8258 &'subs self,
8259 ctx: &'ctx mut DemangleContext<'subs, W>,
8260 scope: Option<ArgScopeStack<'prev, 'subs>>,
8261 ) -> fmt::Result {
8262 let ctx = try_begin_demangle!(self, ctx, scope);
8263
8264 match self {
8265 FoldExpr::UnaryLeft(ref operator, ref expr) => {
8266 write!(ctx, "(...")?;
8267 operator.demangle(ctx, scope)?;
8268 expr.demangle_as_subexpr(ctx, scope)?;
8269 write!(ctx, ")")
8270 }
8271 FoldExpr::UnaryRight(ref operator, ref expr) => {
8272 write!(ctx, "(")?;
8273 expr.demangle_as_subexpr(ctx, scope)?;
8274 operator.demangle(ctx, scope)?;
8275 write!(ctx, "...)")
8276 }
8277 FoldExpr::BinaryLeft(ref operator, ref expr1, ref expr2)
8278 | FoldExpr::BinaryRight(ref operator, ref expr1, ref expr2) => {
8279 write!(ctx, "(")?;
8280 expr1.demangle_as_subexpr(ctx, scope)?;
8281 operator.demangle(ctx, scope)?;
8282 write!(ctx, "...")?;
8283 operator.demangle(ctx, scope)?;
8284 expr2.demangle_as_subexpr(ctx, scope)?;
8285 write!(ctx, ")")
8286 }
8287 }
8288 }
8289}
8290
8291#[inline]
8296fn consume<'a>(expected: &[u8], input: IndexStr<'a>) -> Result<IndexStr<'a>> {
8297 match input.try_split_at(expected.len()) {
8298 Some((head, tail)) if head == expected => Ok(tail),
8299 Some(_) => Err(error::Error::UnexpectedText),
8300 None => Err(error::Error::UnexpectedEnd),
8301 }
8302}
8303
8304fn one_or_more<'a, 'b, P>(
8305 ctx: &'a ParseContext,
8306 subs: &'a mut SubstitutionTable,
8307 input: IndexStr<'b>,
8308) -> Result<(Vec<P>, IndexStr<'b>)>
8309where
8310 P: Parse,
8311{
8312 let (first, mut tail) = P::parse(ctx, subs, input)?;
8313 let mut results = vec![first];
8314 loop {
8315 if let Ok((parsed, tail_tail)) = try_recurse!(P::parse(ctx, subs, tail)) {
8316 results.push(parsed);
8317 tail = tail_tail;
8318 } else {
8319 return Ok((results, tail));
8320 }
8321 }
8322}
8323
8324fn zero_or_more<'a, 'b, P>(
8325 ctx: &'a ParseContext,
8326 subs: &'a mut SubstitutionTable,
8327 input: IndexStr<'b>,
8328) -> Result<(Vec<P>, IndexStr<'b>)>
8329where
8330 P: Parse,
8331{
8332 let mut tail = input;
8333 let mut results = vec![];
8334 loop {
8335 if let Ok((parsed, tail_tail)) = try_recurse!(P::parse(ctx, subs, tail)) {
8336 results.push(parsed);
8337 tail = tail_tail;
8338 } else {
8339 return Ok((results, tail));
8340 }
8341 }
8342}
8343
8344#[allow(unsafe_code)]
8347fn parse_number(base: u32, allow_signed: bool, mut input: IndexStr) -> Result<(isize, IndexStr)> {
8348 if input.is_empty() {
8349 return Err(error::Error::UnexpectedEnd);
8350 }
8351
8352 let num_is_negative = if allow_signed && input.as_ref()[0] == b'n' {
8353 input = input.range_from(1..);
8354
8355 if input.is_empty() {
8356 return Err(error::Error::UnexpectedEnd);
8357 }
8358
8359 true
8360 } else {
8361 false
8362 };
8363
8364 let num_numeric = input
8365 .as_ref()
8366 .iter()
8367 .map(|&c| c as char)
8368 .take_while(|c| c.is_digit(base) && (c.is_numeric() || c.is_uppercase()))
8369 .count();
8370 if num_numeric == 0 {
8371 return Err(error::Error::UnexpectedText);
8372 }
8373
8374 let (head, tail) = input.split_at(num_numeric);
8375 let head = head.as_ref();
8376
8377 if num_numeric > 1 && head[0] == b'0' {
8378 return Err(error::Error::UnexpectedText);
8381 }
8382
8383 let head = unsafe {
8384 str::from_utf8_unchecked(head)
8387 };
8388
8389 let mut number = isize::from_str_radix(head, base).map_err(|_| error::Error::Overflow)?;
8390 if num_is_negative {
8391 number = -number;
8392 }
8393
8394 Ok((number, tail))
8395}
8396
8397#[cfg(test)]
8398mod tests {
8399 use super::{
8400 AbiTag, AbiTags, ArrayType, BareFunctionType, BaseUnresolvedName, BuiltinType, CallOffset,
8401 ClassEnumType, ClosureTypeName, CtorDtorName, CvQualifiers, DataMemberPrefix, Decltype,
8402 DestructorName, Discriminator, Encoding, ExceptionSpec, ExprPrimary, Expression, FoldExpr,
8403 FunctionParam, FunctionType, GlobalCtorDtor, Identifier, Initializer, LambdaSig, LocalName,
8404 MangledName, MemberName, Name, NestedName, NonSubstitution, Number, NvOffset, OperatorName,
8405 ParametricBuiltinType, Parse, ParseContext, PointerToMemberType, Prefix, PrefixHandle,
8406 RefQualifier, ResourceName, SeqId, SimpleId, SimpleOperatorName, SourceName, SpecialName,
8407 StandardBuiltinType, SubobjectExpr, Substitution, TemplateArg, TemplateArgs, TemplateParam,
8408 TemplateTemplateParam, TemplateTemplateParamHandle, Type, TypeHandle, UnnamedTypeName,
8409 UnqualifiedName, UnresolvedName, UnresolvedQualifierLevel, UnresolvedType,
8410 UnresolvedTypeHandle, UnscopedName, UnscopedTemplateName, UnscopedTemplateNameHandle,
8411 VOffset, VectorType, WellKnownComponent,
8412 };
8413
8414 use crate::error::Error;
8415 use crate::index_str::IndexStr;
8416 use crate::subs::{Substitutable, SubstitutionTable};
8417 use alloc::boxed::Box;
8418 use alloc::string::String;
8419 use core::fmt::Debug;
8420 use core::iter::FromIterator;
8421
8422 fn assert_parse_ok<P, S1, S2, I1, I2>(
8423 production: &'static str,
8424 subs: S1,
8425 input: I1,
8426 expected: P,
8427 expected_tail: I2,
8428 expected_new_subs: S2,
8429 ) where
8430 P: Debug + Parse + PartialEq,
8431 S1: AsRef<[Substitutable]>,
8432 S2: AsRef<[Substitutable]>,
8433 I1: AsRef<[u8]>,
8434 I2: AsRef<[u8]>,
8435 {
8436 let ctx = ParseContext::new(Default::default());
8437 let input = input.as_ref();
8438 let expected_tail = expected_tail.as_ref();
8439
8440 let expected_subs = SubstitutionTable::from_iter(
8441 subs.as_ref()
8442 .iter()
8443 .cloned()
8444 .chain(expected_new_subs.as_ref().iter().cloned()),
8445 );
8446 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
8447
8448 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
8449 Err(error) => panic!(
8450 "Parsing {:?} as {} failed: {}",
8451 String::from_utf8_lossy(input),
8452 production,
8453 error
8454 ),
8455 Ok((value, tail)) => {
8456 if value != expected {
8457 panic!(
8458 "Parsing {:?} as {} produced\n\n{:#?}\n\nbut we expected\n\n{:#?}",
8459 String::from_utf8_lossy(input),
8460 production,
8461 value,
8462 expected
8463 );
8464 }
8465 if tail != expected_tail {
8466 panic!(
8467 "Parsing {:?} as {} left a tail of {:?}, expected {:?}",
8468 String::from_utf8_lossy(input),
8469 production,
8470 tail,
8471 String::from_utf8_lossy(expected_tail)
8472 );
8473 }
8474 if subs[..] != expected_subs[..] {
8475 panic!(
8476 "Parsing {:?} as {} produced a substitutions table of\n\n\
8477 {:#?}\n\n\
8478 but we expected\n\n\
8479 {:#?}",
8480 String::from_utf8_lossy(input),
8481 production,
8482 subs,
8483 expected_subs
8484 );
8485 }
8486 }
8487 }
8488
8489 log!("=== assert_parse_ok PASSED ====================================");
8490 }
8491
8492 fn simple_assert_parse_ok<P, I1, I2>(
8493 production: &'static str,
8494 input: I1,
8495 expected: P,
8496 expected_tail: I2,
8497 ) where
8498 P: Debug + Parse + PartialEq,
8499 I1: AsRef<[u8]>,
8500 I2: AsRef<[u8]>,
8501 {
8502 assert_parse_ok::<P, _, _, _, _>(production, [], input, expected, expected_tail, []);
8503 }
8504
8505 fn assert_parse_err<P, S, I>(production: &'static str, subs: S, input: I, expected_error: Error)
8506 where
8507 P: Debug + Parse + PartialEq,
8508 S: AsRef<[Substitutable]>,
8509 I: AsRef<[u8]>,
8510 {
8511 let input = input.as_ref();
8512 let ctx = ParseContext::new(Default::default());
8513 let mut subs = SubstitutionTable::from_iter(subs.as_ref().iter().cloned());
8514
8515 match P::parse(&ctx, &mut subs, IndexStr::from(input)) {
8516 Err(ref error) if *error == expected_error => {}
8517 Err(ref error) => {
8518 panic!(
8519 "Parsing {:?} as {} produced an error of kind {:?}, but we expected kind {:?}",
8520 String::from_utf8_lossy(input),
8521 production,
8522 error,
8523 expected_error
8524 );
8525 }
8526 Ok((value, tail)) => {
8527 panic!(
8528 "Parsing {:?} as {} produced value\
8529 \n\n\
8530 {:#?}\
8531 \n\n\
8532 and tail {:?}, but we expected error kind {:?}",
8533 String::from_utf8_lossy(input),
8534 production,
8535 value,
8536 tail,
8537 expected_error
8538 );
8539 }
8540 }
8541
8542 log!("=== assert_parse_err PASSED ===================================");
8543 }
8544
8545 fn simple_assert_parse_err<P, I>(production: &'static str, input: I, expected_error: Error)
8546 where
8547 P: Debug + Parse + PartialEq,
8548 I: AsRef<[u8]>,
8549 {
8550 assert_parse_err::<P, _, _>(production, [], input, expected_error);
8551 }
8552
8553 #[test]
8554 fn recursion_limit() {
8555 let mut mangled = String::new();
8559 for _ in 0..10_000 {
8560 mangled.push('P');
8561 }
8562 mangled += "c";
8563
8564 simple_assert_parse_err::<TypeHandle, _>("TypeHandle", mangled, Error::TooMuchRecursion);
8565 }
8566
8567 macro_rules! assert_parse {
8568 ( $production:ident {
8569 $( with subs $subs:expr => {
8570 Ok => {
8571 $( $input:expr => {
8572 $expected:expr ,
8573 $expected_tail:expr ,
8574 $expected_new_subs:expr
8575 } )*
8576 }
8577 Err => {
8578 $( $error_input:expr => $error:expr , )*
8579 }
8580 } )*
8581 } ) => {
8582 $( $(
8583 assert_parse_ok::<$production, _, _, _, _>(stringify!($production),
8584 $subs,
8585 $input,
8586 $expected,
8587 $expected_tail,
8588 $expected_new_subs);
8589 )* )*
8590
8591 $( $(
8592 assert_parse_err::<$production, _, _>(stringify!($production),
8593 $subs,
8594 $error_input,
8595 $error);
8596 )* )*
8597 };
8598
8599 ( $production:ident {
8600 Ok => {
8601 $( $input:expr => {
8602 $expected:expr ,
8603 $expected_tail:expr
8604 } )*
8605 }
8606 Err => {
8607 $( $error_input:expr => $error:expr , )*
8608 }
8609 } ) => {
8610 $(
8611 simple_assert_parse_ok::<$production, _, _>(stringify!($production),
8612 $input,
8613 $expected,
8614 $expected_tail);
8615 )*
8616
8617
8618 $(
8619 simple_assert_parse_err::<$production, _>(stringify!($production),
8620 $error_input,
8621 $error);
8622 )*
8623 };
8624 }
8625
8626 #[test]
8627 fn parse_mangled_name() {
8628 assert_parse!(MangledName {
8629 Ok => {
8630 b"_Z3foo..." => {
8631 MangledName::Encoding(
8632 Encoding::Data(
8633 Name::Unscoped(
8634 UnscopedName::Unqualified(
8635 UnqualifiedName::Source(
8636 SourceName(Identifier {
8637 start: 3,
8638 end: 6,
8639 }),
8640 AbiTags::default())))), vec![]),
8641 b"..."
8642 }
8643 b"_GLOBAL__I__Z3foo..." => {
8644 MangledName::GlobalCtorDtor(
8645 GlobalCtorDtor::Ctor(
8646 Box::new(
8647 MangledName::Encoding(
8648 Encoding::Data(
8649 Name::Unscoped(
8650 UnscopedName::Unqualified(
8651 UnqualifiedName::Source(
8652 SourceName(
8653 Identifier {
8654 start: 14,
8655 end: 17,
8656 }),
8657 AbiTags::default())))), vec![])))),
8658 b"..."
8659 }
8660 }
8661 Err => {
8662 b"_Y" => Error::UnexpectedText,
8663 b"_Z" => Error::UnexpectedEnd,
8664 b"_" => Error::UnexpectedEnd,
8665 b"" => Error::UnexpectedEnd,
8666 b"_GLOBAL_" => Error::UnexpectedEnd,
8667 }
8668 });
8669 }
8670
8671 #[test]
8672 fn parse_encoding() {
8673 assert_parse!(Encoding {
8674 with subs [] => {
8675 Ok => {
8676 b"3fooi..." => {
8677 Encoding::Function(
8678 Name::Unscoped(
8679 UnscopedName::Unqualified(
8680 UnqualifiedName::Source(
8681 SourceName(Identifier {
8682 start: 1,
8683 end: 4,
8684 }),
8685 AbiTags::default()))),
8686 BareFunctionType(vec![
8687 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
8688 ])),
8689 b"...",
8690 []
8691 }
8692 b"3foo..." => {
8693 Encoding::Data(
8694 Name::Unscoped(
8695 UnscopedName::Unqualified(
8696 UnqualifiedName::Source(
8697 SourceName(Identifier {
8698 start: 1,
8699 end: 4,
8700 }),
8701 AbiTags::default())))),
8702 b"...",
8703 []
8704 }
8705 b"GV3abc..." => {
8706 Encoding::Special(
8707 SpecialName::Guard(
8708 Name::Unscoped(
8709 UnscopedName::Unqualified(
8710 UnqualifiedName::Source(
8711 SourceName(Identifier {
8712 start: 3,
8713 end: 6,
8714 }),
8715 AbiTags::default()))))),
8716 b"...",
8717 []
8718 }
8719 }
8720 Err => {
8721 b"zzz" => Error::UnexpectedText,
8722 b"" => Error::UnexpectedEnd,
8723 }
8724 }
8725 });
8726 }
8727
8728 #[test]
8729 fn parse_global_ctor_dtor() {
8730 assert_parse!(GlobalCtorDtor {
8731 Ok => {
8732 b"_I__Z3foo..." => {
8733 GlobalCtorDtor::Ctor(
8734 Box::new(
8735 MangledName::Encoding(
8736 Encoding::Data(
8737 Name::Unscoped(
8738 UnscopedName::Unqualified(
8739 UnqualifiedName::Source(
8740 SourceName(
8741 Identifier {
8742 start: 6,
8743 end: 9,
8744 }),
8745 AbiTags::default())))), vec![]))),
8746 b"..."
8747 }
8748 b".I__Z3foo..." => {
8749 GlobalCtorDtor::Ctor(
8750 Box::new(
8751 MangledName::Encoding(
8752 Encoding::Data(
8753 Name::Unscoped(
8754 UnscopedName::Unqualified(
8755 UnqualifiedName::Source(
8756 SourceName(
8757 Identifier {
8758 start: 6,
8759 end: 9,
8760 }),
8761 AbiTags::default())))), vec![]))),
8762 b"..."
8763 }
8764 b"$I__Z3foo..." => {
8765 GlobalCtorDtor::Ctor(
8766 Box::new(
8767 MangledName::Encoding(
8768 Encoding::Data(
8769 Name::Unscoped(
8770 UnscopedName::Unqualified(
8771 UnqualifiedName::Source(
8772 SourceName(
8773 Identifier {
8774 start: 6,
8775 end: 9,
8776 }),
8777 AbiTags::default())))), vec![]))),
8778 b"..."
8779 }
8780 b"_D__Z3foo..." => {
8781 GlobalCtorDtor::Dtor(
8782 Box::new(
8783 MangledName::Encoding(
8784 Encoding::Data(
8785 Name::Unscoped(
8786 UnscopedName::Unqualified(
8787 UnqualifiedName::Source(
8788 SourceName(
8789 Identifier {
8790 start: 6,
8791 end: 9,
8792 }),
8793 AbiTags::default())))), vec![]))),
8794 b"..."
8795 }
8796 b".D__Z3foo..." => {
8797 GlobalCtorDtor::Dtor(
8798 Box::new(
8799 MangledName::Encoding(
8800 Encoding::Data(
8801 Name::Unscoped(
8802 UnscopedName::Unqualified(
8803 UnqualifiedName::Source(
8804 SourceName(
8805 Identifier {
8806 start: 6,
8807 end: 9,
8808 }),
8809 AbiTags::default())))), vec![]))),
8810 b"..."
8811 }
8812 b"$D__Z3foo..." => {
8813 GlobalCtorDtor::Dtor(
8814 Box::new(
8815 MangledName::Encoding(
8816 Encoding::Data(
8817 Name::Unscoped(
8818 UnscopedName::Unqualified(
8819 UnqualifiedName::Source(
8820 SourceName(
8821 Identifier {
8822 start: 6,
8823 end: 9,
8824 }),
8825 AbiTags::default())))), vec![]))),
8826 b"..."
8827 }
8828 }
8829 Err => {
8830 b"_I" => Error::UnexpectedEnd,
8831 b"_" => Error::UnexpectedEnd,
8832 b"" => Error::UnexpectedEnd,
8833 b"blag" => Error::UnexpectedText,
8834 b"_J" => Error::UnexpectedText,
8835 b"_IJ" => Error::UnexpectedText,
8836 }
8837 });
8838 }
8839
8840 #[test]
8841 fn parse_name() {
8842 assert_parse!(Name {
8843 with subs [
8844 Substitutable::Prefix(
8845 Prefix::Unqualified(
8846 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
8847 AbiTags::default()))),
8848 Substitutable::Prefix(
8849 Prefix::Nested(PrefixHandle::BackReference(0),
8850 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
8851 AbiTags::default()))),
8852 ] => {
8853 Ok => {
8854 b"NS0_3abcE..." => {
8855 Name::Nested(NestedName::Unqualified(CvQualifiers::default(),
8856 None,
8857 Some(PrefixHandle::BackReference(1)),
8858 UnqualifiedName::Source(SourceName(Identifier {
8859 start: 5,
8860 end: 8,
8861 }), AbiTags::default()))),
8862 b"...",
8863 []
8864 }
8865 b"3abc..." => {
8866 Name::Unscoped(
8867 UnscopedName::Unqualified(
8868 UnqualifiedName::Source(
8869 SourceName(Identifier {
8870 start: 1,
8871 end: 4,
8872 }),
8873 AbiTags::default()))),
8874 b"...",
8875 []
8876 }
8877 b"dlIcE..." => {
8878 Name::UnscopedTemplate(
8879 UnscopedTemplateNameHandle::BackReference(2),
8880 TemplateArgs(vec![
8881 TemplateArg::Type(
8882 TypeHandle::Builtin(
8883 BuiltinType::Standard(StandardBuiltinType::Char)))
8884 ])),
8885 b"...",
8886 [
8887 Substitutable::UnscopedTemplateName(
8888 UnscopedTemplateName(
8889 UnscopedName::Unqualified(
8890 UnqualifiedName::Operator(
8891 OperatorName::Simple(
8892 SimpleOperatorName::Delete),
8893 AbiTags::default())))),
8894 ]
8895 }
8896 b"Z3abcEs..." => {
8897 Name::Local(
8898 LocalName::Relative(
8899 Box::new(Encoding::Data(
8900 Name::Unscoped(
8901 UnscopedName::Unqualified(
8902 UnqualifiedName::Source(
8903 SourceName(Identifier {
8904 start: 2,
8905 end: 5,
8906 }),
8907 AbiTags::default()))))),
8908 None,
8909 None)),
8910 b"...",
8911 []
8912 }
8913 }
8914 Err => {
8915 b"zzz" => Error::UnexpectedText,
8916 b"" => Error::UnexpectedEnd,
8917 }
8918 }
8919 });
8920 }
8921
8922 #[test]
8923 fn parse_unscoped_template_name_handle() {
8924 assert_parse!(UnscopedTemplateNameHandle {
8925 with subs [
8926 Substitutable::UnscopedTemplateName(
8927 UnscopedTemplateName(
8928 UnscopedName::Unqualified(
8929 UnqualifiedName::Operator(
8930 OperatorName::Simple(
8931 SimpleOperatorName::New),
8932 AbiTags::default())))),
8933 ] => {
8934 Ok => {
8935 b"S_..." => {
8936 UnscopedTemplateNameHandle::BackReference(0),
8937 b"...",
8938 []
8939 }
8940 b"dl..." => {
8941 UnscopedTemplateNameHandle::BackReference(1),
8942 b"...",
8943 [
8944 Substitutable::UnscopedTemplateName(
8945 UnscopedTemplateName(
8946 UnscopedName::Unqualified(
8947 UnqualifiedName::Operator(
8948 OperatorName::Simple(
8949 SimpleOperatorName::Delete),
8950 AbiTags::default()))))
8951 ]
8952 }
8953 }
8954 Err => {
8955 b"zzzz" => Error::UnexpectedText,
8956 b"" => Error::UnexpectedEnd,
8957 }
8958 }
8959 });
8960 }
8961
8962 #[test]
8963 fn parse_nested_name() {
8964 assert_parse!(NestedName {
8967 with subs [
8968 Substitutable::Prefix(
8969 Prefix::Unqualified(
8970 UnqualifiedName::Operator(
8971 OperatorName::Simple(
8972 SimpleOperatorName::New),
8973 AbiTags::default()))),
8974 ] => {
8975 Ok => {
8976 b"NKOS_3abcE..." => {
8977 NestedName::Unqualified(
8978 CvQualifiers {
8979 restrict: false,
8980 volatile: false,
8981 const_: true,
8982 },
8983 Some(RefQualifier::RValueRef),
8984 Some(PrefixHandle::BackReference(0)),
8985 UnqualifiedName::Source(
8986 SourceName(Identifier {
8987 start: 6,
8988 end: 9,
8989 }),
8990 AbiTags::default())),
8991 b"...",
8992 []
8993 }
8994 b"NOS_3abcE..." => {
8995 NestedName::Unqualified(
8996 CvQualifiers {
8997 restrict: false,
8998 volatile: false,
8999 const_: false,
9000 },
9001 Some(RefQualifier::RValueRef),
9002 Some(PrefixHandle::BackReference(0)),
9003 UnqualifiedName::Source(
9004 SourceName(Identifier {
9005 start: 5,
9006 end: 8,
9007 }), AbiTags::default())),
9008 b"...",
9009 []
9010 }
9011 b"NS_3abcE..." => {
9012 NestedName::Unqualified(
9013 CvQualifiers {
9014 restrict: false,
9015 volatile: false,
9016 const_: false,
9017 },
9018 None,
9019 Some(PrefixHandle::BackReference(0)),
9020 UnqualifiedName::Source(
9021 SourceName(Identifier {
9022 start: 4,
9023 end: 7,
9024 }), AbiTags::default())),
9025 b"...",
9026 []
9027 }
9028 b"NK1fE..." => {
9029 NestedName::Unqualified(
9030 CvQualifiers {
9031 restrict: false,
9032 volatile: false,
9033 const_: true,
9034 },
9035 None,
9036 None,
9037 UnqualifiedName::Source(
9038 SourceName(Identifier {
9039 start: 3,
9040 end: 4,
9041 }),
9042 AbiTags::default())),
9043 b"...",
9044 []
9045 }
9046 b"NKOS_3abcIJEEE..." => {
9047 NestedName::Template(
9048 CvQualifiers {
9049 restrict: false,
9050 volatile: false,
9051 const_: true,
9052 },
9053 Some(RefQualifier::RValueRef),
9054 PrefixHandle::NonSubstitution(NonSubstitution(0))),
9055 b"...",
9056 [
9057 Substitutable::Prefix(
9058 Prefix::Nested(
9059 PrefixHandle::BackReference(0),
9060 UnqualifiedName::Source(
9061 SourceName(Identifier {
9062 start: 6,
9063 end: 9,
9064 }),
9065 AbiTags::default()))),
9066 ]
9067 }
9068 b"NOS_3abcIJEEE..." => {
9069 NestedName::Template(
9070 CvQualifiers {
9071 restrict: false,
9072 volatile: false,
9073 const_: false,
9074 },
9075 Some(RefQualifier::RValueRef),
9076 PrefixHandle::NonSubstitution(NonSubstitution(0))),
9077 b"...",
9078 [
9079 Substitutable::Prefix(
9080 Prefix::Nested(
9081 PrefixHandle::BackReference(0),
9082 UnqualifiedName::Source(
9083 SourceName(Identifier {
9084 start: 5,
9085 end: 8,
9086 }),
9087 AbiTags::default()))),
9088 ]
9089 }
9090 b"NS_3abcIJEEE..." => {
9091 NestedName::Template(
9092 CvQualifiers {
9093 restrict: false,
9094 volatile: false,
9095 const_: false,
9096 },
9097 None,
9098 PrefixHandle::NonSubstitution(NonSubstitution(0))),
9099 b"...",
9100 [
9101 Substitutable::Prefix(
9102 Prefix::Nested(
9103 PrefixHandle::BackReference(0),
9104 UnqualifiedName::Source(
9105 SourceName(Identifier {
9106 start: 4,
9107 end: 7,
9108 }),
9109 AbiTags::default()))),
9110 ]
9111 }
9112 }
9113 Err => {
9114 b"NS_DttrEE..." => Error::UnexpectedText,
9116
9117 b"zzz" => Error::UnexpectedText,
9118 b"Nzzz" => Error::UnexpectedText,
9119 b"NKzzz" => Error::UnexpectedText,
9120 b"NKOzzz" => Error::UnexpectedText,
9121 b"NKO3abczzz" => Error::UnexpectedText,
9122 b"NKO3abc3abczzz" => Error::UnexpectedText,
9123 b"" => Error::UnexpectedEnd,
9124 b"N" => Error::UnexpectedEnd,
9125 b"NK" => Error::UnexpectedEnd,
9126 b"NKO" => Error::UnexpectedEnd,
9127 b"NKO3abc" => Error::UnexpectedEnd,
9128 b"NKO3abc3abc" => Error::UnexpectedEnd,
9129 }
9130 }
9131 });
9132 }
9133
9134 #[test]
9135 fn parse_prefix_handle() {
9136 assert_parse!(PrefixHandle {
9144 with subs [
9145 Substitutable::Prefix(
9146 Prefix::Unqualified(
9147 UnqualifiedName::Operator(
9148 OperatorName::Simple(
9149 SimpleOperatorName::New),
9150 AbiTags::default()))),
9151 ] => {
9152 Ok => {
9153 b"3foo..." => {
9154 PrefixHandle::BackReference(1),
9155 b"...",
9156 [
9157 Substitutable::Prefix(
9158 Prefix::Unqualified(
9159 UnqualifiedName::Source(
9160 SourceName(Identifier {
9161 start: 1,
9162 end: 4,
9163 }),
9164 AbiTags::default())))
9165 ]
9166 }
9167 b"3abc3def..." => {
9168 PrefixHandle::BackReference(2),
9169 b"...",
9170 [
9171 Substitutable::Prefix(
9172 Prefix::Unqualified(
9173 UnqualifiedName::Source(
9174 SourceName(Identifier {
9175 start: 1,
9176 end: 4,
9177 }),
9178 AbiTags::default()))),
9179 Substitutable::Prefix(
9180 Prefix::Nested(
9181 PrefixHandle::BackReference(1),
9182 UnqualifiedName::Source(
9183 SourceName(Identifier {
9184 start: 5,
9185 end: 8,
9186 }),
9187 AbiTags::default()))),
9188 ]
9189 }
9190 b"3fooIJEE..." => {
9191 PrefixHandle::BackReference(2),
9192 b"...",
9193 [
9194 Substitutable::Prefix(
9195 Prefix::Unqualified(
9196 UnqualifiedName::Source(
9197 SourceName(Identifier {
9198 start: 1,
9199 end: 4,
9200 }),
9201 AbiTags::default()))),
9202 Substitutable::Prefix(
9203 Prefix::Template(PrefixHandle::BackReference(1),
9204 TemplateArgs(vec![
9205 TemplateArg::ArgPack(vec![]),
9206 ])))
9207 ]
9208 }
9209 b"T_..." => {
9210 PrefixHandle::BackReference(1),
9211 b"...",
9212 [
9213 Substitutable::Prefix(Prefix::TemplateParam(TemplateParam(0))),
9214 ]
9215 }
9216 b"DTtrE..." => {
9217 PrefixHandle::BackReference(1),
9218 b"...",
9219 [
9220 Substitutable::Prefix(
9221 Prefix::Decltype(
9222 Decltype::Expression(Expression::Rethrow))),
9223 ]
9224 }
9225 b"3abc3defM..." => {
9226 PrefixHandle::BackReference(2),
9227 b"...",
9228 [
9229 Substitutable::Prefix(
9230 Prefix::Unqualified(
9231 UnqualifiedName::Source(
9232 SourceName(Identifier {
9233 start: 1,
9234 end: 4,
9235 }),
9236 AbiTags::default()))),
9237 Substitutable::Prefix(
9238 Prefix::DataMember(
9239 PrefixHandle::BackReference(1),
9240 DataMemberPrefix(
9241 SourceName(Identifier {
9242 start: 5,
9243 end: 8,
9244 })))),
9245 ]
9246 }
9247 b"S_..." => {
9248 PrefixHandle::BackReference(0),
9249 b"...",
9250 []
9251 }
9252 b"3abc3defE..." => {
9254 PrefixHandle::NonSubstitution(NonSubstitution(0)),
9255 b"E...",
9256 [
9257 Substitutable::Prefix(
9258 Prefix::Unqualified(
9259 UnqualifiedName::Source(
9260 SourceName(Identifier {
9261 start: 1,
9262 end: 4,
9263 }),
9264 AbiTags::default()))),
9265 ]
9266 }
9267 }
9268 Err => {
9269 b"zzz" => Error::UnexpectedText,
9270 b"" => Error::UnexpectedEnd,
9271 }
9272 }
9273 });
9274 }
9275
9276 #[test]
9277 fn parse_type_handle() {
9278 assert_parse!(TypeHandle {
9279 with subs [
9280 Substitutable::Type(
9281 Type::PointerTo(
9282 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9283 ] => {
9284 Ok => {
9285 b"S_..." => {
9286 TypeHandle::BackReference(0),
9287 b"...",
9288 []
9289 }
9290 b"c..." => {
9291 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
9292 b"...",
9293 []
9294 }
9295 b"FS_E..." => {
9296 TypeHandle::BackReference(1),
9297 b"...",
9298 [
9299 Substitutable::Type(
9300 Type::Function(FunctionType {
9301 cv_qualifiers: CvQualifiers {
9302 restrict: false,
9303 volatile: false,
9304 const_: false,
9305 },
9306 exception_spec: None,
9307 transaction_safe: false,
9308 extern_c: false,
9309 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9310 ref_qualifier: None,
9311 })),
9312 ]
9313 }
9314 b"A_S_..." => {
9315 TypeHandle::BackReference(1),
9316 b"...",
9317 [
9318 Substitutable::Type(
9319 Type::Array(ArrayType::NoDimension(TypeHandle::BackReference(0)))),
9320 ]
9321 }
9322 b"MS_S_..." => {
9323 TypeHandle::BackReference(1),
9324 b"...",
9325 [
9326 Substitutable::Type(
9327 Type::PointerToMember(
9328 PointerToMemberType(TypeHandle::BackReference(0),
9329 TypeHandle::BackReference(0)))),
9330 ]
9331 }
9332 b"T_..." => {
9333 TypeHandle::BackReference(1),
9334 b"...",
9335 [
9336 Substitutable::Type(Type::TemplateParam(TemplateParam(0))),
9337 ]
9338 }
9339 b"T_IS_E..." => {
9340 TypeHandle::BackReference(2),
9341 b"...",
9342 [
9343 Substitutable::TemplateTemplateParam(
9344 TemplateTemplateParam(TemplateParam(0))),
9345 Substitutable::Type(
9346 Type::TemplateTemplate(
9347 TemplateTemplateParamHandle::BackReference(1),
9348 TemplateArgs(vec![
9349 TemplateArg::Type(TypeHandle::BackReference(0))
9350 ]))),
9351 ]
9352 }
9353 b"DTtrE..." => {
9354 TypeHandle::BackReference(1),
9355 b"...",
9356 [
9357 Substitutable::Type(
9358 Type::Decltype(Decltype::Expression(Expression::Rethrow))),
9359 ]
9360 }
9361 b"KS_..." => {
9362 TypeHandle::BackReference(1),
9363 b"...",
9364 [
9365 Substitutable::Type(Type::Qualified(CvQualifiers {
9366 restrict: false,
9367 volatile: false,
9368 const_: true,
9369 }, TypeHandle::BackReference(0)))
9370 ]
9371 }
9372 b"PS_..." => {
9373 TypeHandle::BackReference(1),
9374 b"...",
9375 [
9376 Substitutable::Type(Type::PointerTo(TypeHandle::BackReference(0)))
9377 ]
9378 }
9379 b"RS_..." => {
9380 TypeHandle::BackReference(1),
9381 b"...",
9382 [
9383 Substitutable::Type(Type::LvalueRef(TypeHandle::BackReference(0)))
9384 ]
9385 }
9386 b"OS_..." => {
9387 TypeHandle::BackReference(1),
9388 b"...",
9389 [
9390 Substitutable::Type(Type::RvalueRef(TypeHandle::BackReference(0)))
9391 ]
9392 }
9393 b"CS_..." => {
9394 TypeHandle::BackReference(1),
9395 b"...",
9396 [
9397 Substitutable::Type(Type::Complex(TypeHandle::BackReference(0)))
9398 ]
9399 }
9400 b"GS_..." => {
9401 TypeHandle::BackReference(1),
9402 b"...",
9403 [
9404 Substitutable::Type(Type::Imaginary(TypeHandle::BackReference(0)))
9405 ]
9406 }
9407 b"U3abcS_..." => {
9408 TypeHandle::BackReference(1),
9409 b"...",
9410 [
9411 Substitutable::Type(
9412 Type::VendorExtension(
9413 SourceName(Identifier {
9414 start: 2,
9415 end: 5,
9416 }),
9417 None,
9418 TypeHandle::BackReference(0)))
9419 ]
9420 }
9421 b"U3abcIS_ES_..." => {
9422 TypeHandle::BackReference(1),
9423 b"...",
9424 [
9425 Substitutable::Type(
9426 Type::VendorExtension(
9427 SourceName(Identifier {
9428 start: 2,
9429 end: 5,
9430 }),
9431 Some(TemplateArgs(vec![
9432 TemplateArg::Type(TypeHandle::BackReference(0))
9433 ])),
9434 TypeHandle::BackReference(0)))
9435 ]
9436 }
9437 b"DpS_..." => {
9438 TypeHandle::BackReference(1),
9439 b"...",
9440 [
9441 Substitutable::Type(
9442 Type::PackExpansion(TypeHandle::BackReference(0))),
9443 ]
9444 }
9445 b"3abc..." => {
9446 TypeHandle::BackReference(1),
9447 b"...",
9448 [
9449 Substitutable::Type(
9450 Type::ClassEnum(
9451 ClassEnumType::Named(
9452 Name::Unscoped(
9453 UnscopedName::Unqualified(
9454 UnqualifiedName::Source(
9455 SourceName(Identifier {
9456 start: 1,
9457 end: 4,
9458 }),
9459 AbiTags::default()))))))
9460 ]
9461 }
9462 }
9463 Err => {
9464 b"P" => Error::UnexpectedEnd,
9465 b"R" => Error::UnexpectedEnd,
9466 b"O" => Error::UnexpectedEnd,
9467 b"C" => Error::UnexpectedEnd,
9468 b"G" => Error::UnexpectedEnd,
9469 b"Dp" => Error::UnexpectedEnd,
9470 b"D" => Error::UnexpectedEnd,
9471 b"P" => Error::UnexpectedEnd,
9472 b"UlvE_" => Error::UnexpectedText,
9473 b"" => Error::UnexpectedEnd,
9474 }
9475 }
9476 });
9477 }
9478
9479 #[test]
9480 fn parse_exception_spec() {
9481 assert_parse!(ExceptionSpec {
9482 Ok => {
9483 b"Do..." => {
9484 ExceptionSpec::NoExcept,
9485 b"..."
9486 }
9487 b"DOtrE..." => {
9488 ExceptionSpec::Computed(Expression::Rethrow),
9489 b"..."
9490 }
9491 }
9492 Err => {
9493 b"DOtre" => Error::UnexpectedText,
9494 b"DOE" => Error::UnexpectedText,
9495 b"D" => Error::UnexpectedEnd,
9496 b"" => Error::UnexpectedEnd,
9497 }
9498 });
9499 }
9500
9501 #[test]
9502 fn parse_function_type() {
9503 assert_parse!(FunctionType {
9504 with subs [
9505 Substitutable::Type(
9506 Type::PointerTo(
9507 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9508 ] => {
9509 Ok => {
9510 b"KDxFYS_RE..." => {
9511 FunctionType {
9512 cv_qualifiers: CvQualifiers {
9513 restrict: false,
9514 volatile: false,
9515 const_: true,
9516 },
9517 exception_spec: None,
9518 transaction_safe: true,
9519 extern_c: true,
9520 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9521 ref_qualifier: Some(RefQualifier::LValueRef),
9522 },
9523 b"...",
9524 []
9525 }
9526 b"DxFYS_RE..." => {
9527 FunctionType {
9528 cv_qualifiers: CvQualifiers {
9529 restrict: false,
9530 volatile: false,
9531 const_: false,
9532 },
9533 exception_spec: None,
9534 transaction_safe: true,
9535 extern_c: true,
9536 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9537 ref_qualifier: Some(RefQualifier::LValueRef),
9538 },
9539 b"...",
9540 []
9541 }
9542 b"FYS_RE..." => {
9543 FunctionType {
9544 cv_qualifiers: CvQualifiers {
9545 restrict: false,
9546 volatile: false,
9547 const_: false,
9548 },
9549 exception_spec: None,
9550 transaction_safe: false,
9551 extern_c: true,
9552 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9553 ref_qualifier: Some(RefQualifier::LValueRef),
9554 },
9555 b"...",
9556 []
9557 }
9558 b"FS_RE..." => {
9559 FunctionType {
9560 cv_qualifiers: CvQualifiers {
9561 restrict: false,
9562 volatile: false,
9563 const_: false,
9564 },
9565 exception_spec: None,
9566 transaction_safe: false,
9567 extern_c: false,
9568 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9569 ref_qualifier: Some(RefQualifier::LValueRef),
9570 },
9571 b"...",
9572 []
9573 }
9574 b"FS_E..." => {
9575 FunctionType {
9576 cv_qualifiers: CvQualifiers {
9577 restrict: false,
9578 volatile: false,
9579 const_: false,
9580 },
9581 exception_spec: None,
9582 transaction_safe: false,
9583 extern_c: false,
9584 bare: BareFunctionType(vec![TypeHandle::BackReference(0)]),
9585 ref_qualifier: None,
9586 },
9587 b"...",
9588 []
9589 }
9590 }
9591 Err => {
9592 b"DFYS_E" => Error::UnexpectedText,
9593 b"KKFS_E" => Error::UnexpectedText,
9594 b"FYS_..." => Error::UnexpectedText,
9595 b"FYS_" => Error::UnexpectedEnd,
9596 b"F" => Error::UnexpectedEnd,
9597 b"" => Error::UnexpectedEnd,
9598 }
9599 }
9600 });
9601 }
9602
9603 #[test]
9604 fn parse_bare_function_type() {
9605 assert_parse!(BareFunctionType {
9606 with subs [
9607 Substitutable::Type(
9608 Type::PointerTo(
9609 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)))),
9610 ] => {
9611 Ok => {
9612 b"S_S_..." => {
9613 BareFunctionType(vec![
9614 TypeHandle::BackReference(0),
9615 TypeHandle::BackReference(0),
9616 ]),
9617 b"...",
9618 []
9619 }
9620 }
9621 Err => {
9622 b"" => Error::UnexpectedEnd,
9623 }
9624 }
9625 });
9626 }
9627
9628 #[test]
9629 fn parse_decltype() {
9630 assert_parse!(Decltype {
9631 Ok => {
9632 b"DTtrE..." => {
9633 Decltype::Expression(Expression::Rethrow),
9634 b"..."
9635 }
9636 b"DttrE..." => {
9637 Decltype::IdExpression(Expression::Rethrow),
9638 b"..."
9639 }
9640 }
9641 Err => {
9642 b"Dtrtz" => Error::UnexpectedText,
9643 b"DTrtz" => Error::UnexpectedText,
9644 b"Dz" => Error::UnexpectedText,
9645 b"Dtrt" => Error::UnexpectedText,
9646 b"DTrt" => Error::UnexpectedText,
9647 b"Dt" => Error::UnexpectedEnd,
9648 b"DT" => Error::UnexpectedEnd,
9649 b"D" => Error::UnexpectedEnd,
9650 b"" => Error::UnexpectedEnd,
9651 }
9652 });
9653 }
9654
9655 #[test]
9656 fn parse_class_enum_type() {
9657 assert_parse!(ClassEnumType {
9658 Ok => {
9659 b"3abc..." => {
9660 ClassEnumType::Named(
9661 Name::Unscoped(
9662 UnscopedName::Unqualified(
9663 UnqualifiedName::Source(
9664 SourceName(Identifier {
9665 start: 1,
9666 end: 4,
9667 }),
9668 AbiTags::default())))),
9669 b"..."
9670 }
9671 b"Ts3abc..." => {
9672 ClassEnumType::ElaboratedStruct(
9673 Name::Unscoped(
9674 UnscopedName::Unqualified(
9675 UnqualifiedName::Source(
9676 SourceName(Identifier {
9677 start: 3,
9678 end: 6,
9679 }),
9680 AbiTags::default())))),
9681 b"..."
9682 }
9683 b"Tu3abc..." => {
9684 ClassEnumType::ElaboratedUnion(
9685 Name::Unscoped(
9686 UnscopedName::Unqualified(
9687 UnqualifiedName::Source(
9688 SourceName(Identifier {
9689 start: 3,
9690 end: 6,
9691 }),
9692 AbiTags::default())))),
9693 b"..."
9694 }
9695 b"Te3abc..." => {
9696 ClassEnumType::ElaboratedEnum(
9697 Name::Unscoped(
9698 UnscopedName::Unqualified(
9699 UnqualifiedName::Source(
9700 SourceName(Identifier {
9701 start: 3,
9702 end: 6,
9703 }),
9704 AbiTags::default())))),
9705 b"..."
9706 }
9707 }
9708 Err => {
9709 b"zzz" => Error::UnexpectedText,
9710 b"Tzzz" => Error::UnexpectedText,
9711 b"T" => Error::UnexpectedEnd,
9712 b"" => Error::UnexpectedEnd,
9713 }
9714 });
9715 }
9716
9717 #[test]
9718 fn parse_array_type() {
9719 assert_parse!(ArrayType {
9720 with subs [
9721 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9722 ] => {
9723 Ok => {
9724 b"A10_S_..." => {
9725 ArrayType::DimensionNumber(10, TypeHandle::BackReference(0)),
9726 b"...",
9727 []
9728 }
9729 b"A10_Sb..." => {
9730 ArrayType::DimensionNumber(10,
9731 TypeHandle::WellKnown(
9732 WellKnownComponent::StdString1)),
9733 b"...",
9734 []
9735 }
9736 b"Atr_S_..." => {
9737 ArrayType::DimensionExpression(Expression::Rethrow,
9738 TypeHandle::BackReference(0)),
9739 b"...",
9740 []
9741 }
9742 b"A_S_..." => {
9743 ArrayType::NoDimension(TypeHandle::BackReference(0)),
9744 b"...",
9745 []
9746 }
9747 }
9748 Err => {
9749 b"A10_" => Error::UnexpectedEnd,
9750 b"A10" => Error::UnexpectedEnd,
9751 b"A" => Error::UnexpectedEnd,
9752 b"" => Error::UnexpectedEnd,
9753 b"A10_..." => Error::UnexpectedText,
9754 b"A10..." => Error::UnexpectedText,
9755 b"A..." => Error::UnexpectedText,
9756 b"..." => Error::UnexpectedText,
9757 }
9758 }
9759 });
9760 }
9761
9762 #[test]
9763 fn parse_vector_type() {
9764 assert_parse!(VectorType {
9765 with subs [
9766 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9767 ] => {
9768 Ok => {
9769 b"Dv10_S_..." => {
9770 VectorType::DimensionNumber(10, TypeHandle::BackReference(0)),
9771 b"...",
9772 []
9773 }
9774 b"Dv10_Sb..." => {
9775 VectorType::DimensionNumber(10,
9776 TypeHandle::WellKnown(
9777 WellKnownComponent::StdString1)),
9778 b"...",
9779 []
9780 }
9781 b"Dvtr_S_..." => {
9782 VectorType::DimensionExpression(Expression::Rethrow,
9783 TypeHandle::BackReference(0)),
9784 b"...",
9785 []
9786 }
9787 }
9788 Err => {
9789 b"Dq" => Error::UnexpectedText,
9790 b"Dv" => Error::UnexpectedEnd,
9791 b"Dv42_" => Error::UnexpectedEnd,
9792 b"Dv42_..." => Error::UnexpectedText,
9793 b"Dvtr_" => Error::UnexpectedEnd,
9794 b"Dvtr_..." => Error::UnexpectedText,
9795 b"" => Error::UnexpectedEnd,
9796 b"..." => Error::UnexpectedText,
9797 }
9798 }
9799 });
9800 }
9801
9802 #[test]
9803 fn parse_pointer_to_member_type() {
9804 assert_parse!(PointerToMemberType {
9805 with subs [
9806 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9807 ] => {
9808 Ok => {
9809 b"MS_S_..." => {
9810 PointerToMemberType(TypeHandle::BackReference(0),
9811 TypeHandle::BackReference(0)),
9812 b"...",
9813 []
9814 }
9815 }
9816 Err => {
9817 b"MS_S" => Error::UnexpectedEnd,
9818 b"MS_" => Error::UnexpectedEnd,
9819 b"MS" => Error::UnexpectedEnd,
9820 b"M" => Error::UnexpectedEnd,
9821 b"" => Error::UnexpectedEnd,
9822 b"MS_..." => Error::UnexpectedText,
9823 b"M..." => Error::UnexpectedText,
9824 b"..." => Error::UnexpectedText,
9825 }
9826 }
9827 });
9828 }
9829
9830 #[test]
9831 fn parse_template_template_param_handle() {
9832 assert_parse!(TemplateTemplateParamHandle {
9833 with subs [
9834 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(0)))
9835 ] => {
9836 Ok => {
9837 b"S_..." => {
9838 TemplateTemplateParamHandle::BackReference(0),
9839 b"...",
9840 []
9841 }
9842 b"T1_..." => {
9843 TemplateTemplateParamHandle::BackReference(1),
9844 b"...",
9845 [
9846 Substitutable::TemplateTemplateParam(TemplateTemplateParam(TemplateParam(2)))
9847 ]
9848 }
9849 }
9850 Err => {
9851 b"S" => Error::UnexpectedText,
9852 b"T" => Error::UnexpectedEnd,
9853 b"" => Error::UnexpectedEnd,
9854 b"S..." => Error::UnexpectedText,
9855 b"T..." => Error::UnexpectedText,
9856 b"..." => Error::UnexpectedText,
9857 }
9858 }
9859 });
9860 }
9861
9862 #[test]
9863 fn parse_template_args() {
9864 assert_parse!(TemplateArgs {
9865 with subs [
9866 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9867 ] => {
9868 Ok => {
9869 b"IS_E..." => {
9870 TemplateArgs(vec![TemplateArg::Type(TypeHandle::BackReference(0))]),
9871 b"...",
9872 []
9873 }
9874 b"IS_S_S_S_E..." => {
9875 TemplateArgs(vec![
9876 TemplateArg::Type(TypeHandle::BackReference(0)),
9877 TemplateArg::Type(TypeHandle::BackReference(0)),
9878 TemplateArg::Type(TypeHandle::BackReference(0)),
9879 TemplateArg::Type(TypeHandle::BackReference(0)),
9880 ]),
9881 b"...",
9882 []
9883 }
9884 }
9885 Err => {
9886 b"zzz" => Error::UnexpectedText,
9887 b"IE" => Error::UnexpectedText,
9888 b"IS_" => Error::UnexpectedEnd,
9889 b"I" => Error::UnexpectedEnd,
9890 b"" => Error::UnexpectedEnd,
9891 }
9892 }
9893 });
9894 }
9895
9896 #[test]
9897 fn parse_template_arg() {
9898 assert_parse!(TemplateArg {
9899 with subs [
9900 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
9901 ] => {
9902 Ok => {
9903 b"S_..." => {
9904 TemplateArg::Type(TypeHandle::BackReference(0)),
9905 b"...",
9906 []
9907 }
9908 b"XtrE..." => {
9909 TemplateArg::Expression(Expression::Rethrow),
9910 b"...",
9911 []
9912 }
9913 b"XsrS_1QE..." => {
9914 TemplateArg::Expression(
9915 Expression::UnresolvedName(
9916 UnresolvedName::Nested1(
9917 UnresolvedTypeHandle::BackReference(0),
9918 vec![],
9919 BaseUnresolvedName::Name(
9920 SimpleId(
9921 SourceName(Identifier {
9922 start: 6,
9923 end: 7
9924 }),
9925 None
9926 )
9927 )
9928 )
9929 )
9930 ),
9931 b"...",
9932 []
9933 }
9934 b"XsrS_1QIlEE..." => {
9935 TemplateArg::Expression(
9936 Expression::UnresolvedName(
9937 UnresolvedName::Nested1(
9938 UnresolvedTypeHandle::BackReference(0),
9939 vec![],
9940 BaseUnresolvedName::Name(
9941 SimpleId(
9942 SourceName(Identifier {
9943 start: 6,
9944 end: 7
9945 }),
9946 Some(
9947 TemplateArgs(
9948 vec![
9949 TemplateArg::Type(
9950 TypeHandle::Builtin(
9951 BuiltinType::Standard(
9952 StandardBuiltinType::Long
9953 )
9954 )
9955 )
9956 ]
9957 )
9958 )
9959 )
9960 )
9961 )
9962 )
9963 ),
9964 b"...",
9965 []
9966 }
9967 b"LS_E..." => {
9968 TemplateArg::SimpleExpression(
9969 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3)),
9970 b"...",
9971 []
9972 }
9973 b"JE..." => {
9974 TemplateArg::ArgPack(vec![]),
9975 b"...",
9976 []
9977 }
9978 b"JS_XtrELS_EJEE..." => {
9979 TemplateArg::ArgPack(vec![
9980 TemplateArg::Type(TypeHandle::BackReference(0)),
9981 TemplateArg::Expression(Expression::Rethrow),
9982 TemplateArg::SimpleExpression(
9983 ExprPrimary::Literal(TypeHandle::BackReference(0), 10, 10)),
9984 TemplateArg::ArgPack(vec![]),
9985 ]),
9986 b"...",
9987 []
9988 }
9989 }
9990 Err => {
9991 b"..." => Error::UnexpectedText,
9992 b"X..." => Error::UnexpectedText,
9993 b"J..." => Error::UnexpectedText,
9994 b"JS_..." => Error::UnexpectedText,
9995 b"JS_" => Error::UnexpectedEnd,
9996 b"X" => Error::UnexpectedEnd,
9997 b"J" => Error::UnexpectedEnd,
9998 b"" => Error::UnexpectedEnd,
9999 }
10000 }
10001 });
10002 }
10003
10004 #[test]
10005 fn parse_expression() {
10006 assert_parse!(Expression {
10007 with subs [
10008 Substitutable::Type(
10009 Type::PointerTo(TypeHandle::Builtin(
10010 BuiltinType::Standard(StandardBuiltinType::Int)))),
10011 ] => {
10012 Ok => {
10013 b"psLS_1E..." => {
10014 Expression::Unary(OperatorName::Simple(SimpleOperatorName::UnaryPlus),
10015 Box::new(Expression::Primary(
10016 ExprPrimary::Literal(
10017 TypeHandle::BackReference(0),
10018 5,
10019 6)))),
10020 b"...",
10021 []
10022 }
10023 b"rsLS_1ELS_1E..." => {
10024 Expression::Binary(OperatorName::Simple(SimpleOperatorName::Shr),
10025 Box::new(Expression::Primary(
10026 ExprPrimary::Literal(
10027 TypeHandle::BackReference(0),
10028 5,
10029 6))),
10030 Box::new(Expression::Primary(
10031 ExprPrimary::Literal(
10032 TypeHandle::BackReference(0),
10033 10,
10034 11)))),
10035 b"...",
10036 []
10037 }
10038 b"quLS_1ELS_2ELS_3E..." => {
10039 Expression::Ternary(OperatorName::Simple(SimpleOperatorName::Question),
10040 Box::new(Expression::Primary(
10041 ExprPrimary::Literal(
10042 TypeHandle::BackReference(0),
10043 5,
10044 6))),
10045 Box::new(Expression::Primary(
10046 ExprPrimary::Literal(
10047 TypeHandle::BackReference(0),
10048 10,
10049 11))),
10050 Box::new(Expression::Primary(
10051 ExprPrimary::Literal(
10052 TypeHandle::BackReference(0),
10053 15,
10054 16)))),
10055 b"...",
10056 []
10057 }
10058 b"pp_LS_1E..." => {
10059 Expression::PrefixInc(
10060 Box::new(Expression::Primary(
10061 ExprPrimary::Literal(
10062 TypeHandle::BackReference(0),
10063 6,
10064 7)))),
10065 b"...",
10066 []
10067 }
10068 b"mm_LS_1E..." => {
10069 Expression::PrefixDec(
10070 Box::new(Expression::Primary(
10071 ExprPrimary::Literal(
10072 TypeHandle::BackReference(0),
10073 6,
10074 7)))),
10075 b"...",
10076 []
10077 }
10078 b"clLS_1EE..." => {
10079 Expression::Call(
10080 Box::new(Expression::Primary(
10081 ExprPrimary::Literal(
10082 TypeHandle::BackReference(0),
10083 5,
10084 6))),
10085 vec![]),
10086 b"...",
10087 []
10088 }
10089 b"cvS_LS_1E..." => {
10091 Expression::ConversionOne(
10092 TypeHandle::BackReference(0),
10093 Box::new(Expression::Primary(
10094 ExprPrimary::Literal(
10095 TypeHandle::BackReference(0),
10096 7,
10097 8)))),
10098 b"...",
10099 []
10100 }
10101 b"cvS__LS_1ELS_1EE..." => {
10102 Expression::ConversionMany(
10103 TypeHandle::BackReference(0),
10104 vec![
10105 Expression::Primary(
10106 ExprPrimary::Literal(
10107 TypeHandle::BackReference(0),
10108 8,
10109 9)),
10110 Expression::Primary(
10111 ExprPrimary::Literal(
10112 TypeHandle::BackReference(0),
10113 13,
10114 14)),
10115 ]),
10116 b"...",
10117 []
10118 }
10119 b"tlS_LS_1ELS_1EE..." => {
10120 Expression::ConversionBraced(
10121 TypeHandle::BackReference(0),
10122 vec![
10123 Expression::Primary(
10124 ExprPrimary::Literal(
10125 TypeHandle::BackReference(0),
10126 7,
10127 8)),
10128 Expression::Primary(
10129 ExprPrimary::Literal(
10130 TypeHandle::BackReference(0),
10131 12,
10132 13)),
10133 ]),
10134 b"...",
10135 []
10136 }
10137 b"ilLS_1EE..." => {
10138 Expression::BracedInitList(
10139 vec![Expression::Primary(
10140 ExprPrimary::Literal(
10141 TypeHandle::BackReference(0),
10142 5,
10143 6))]),
10144 b"...",
10145 []
10146 }
10147 b"ilE..." => {
10148 Expression::BracedInitList(vec![]),
10149 b"...",
10150 []
10151 }
10152 b"gsnwLS_1E_S_E..." => {
10153 Expression::GlobalNew(
10154 vec![
10155 Expression::Primary(
10156 ExprPrimary::Literal(
10157 TypeHandle::BackReference(0),
10158 7,
10159 8))
10160 ],
10161 TypeHandle::BackReference(0),
10162 None),
10163 b"...",
10164 []
10165 }
10166 b"nwLS_1E_S_E..." => {
10167 Expression::New(
10168 vec![
10169 Expression::Primary(
10170 ExprPrimary::Literal(
10171 TypeHandle::BackReference(0),
10172 5,
10173 6))
10174 ],
10175 TypeHandle::BackReference(0),
10176 None),
10177 b"...",
10178 []
10179 }
10180 b"gsnwLS_1E_S_piE..." => {
10181 Expression::GlobalNew(
10182 vec![
10183 Expression::Primary(
10184 ExprPrimary::Literal(
10185 TypeHandle::BackReference(0),
10186 7,
10187 8))
10188 ],
10189 TypeHandle::BackReference(0),
10190 Some(Initializer(vec![]))),
10191 b"...",
10192 []
10193 }
10194 b"nwLS_1E_S_piE..." => {
10195 Expression::New(
10196 vec![
10197 Expression::Primary(
10198 ExprPrimary::Literal(
10199 TypeHandle::BackReference(0),
10200 5,
10201 6))
10202 ],
10203 TypeHandle::BackReference(0),
10204 Some(Initializer(vec![]))),
10205 b"...",
10206 []
10207 }
10208 b"gsnaLS_1E_S_E..." => {
10209 Expression::GlobalNewArray(
10210 vec![
10211 Expression::Primary(
10212 ExprPrimary::Literal(
10213 TypeHandle::BackReference(0),
10214 7,
10215 8))
10216 ],
10217 TypeHandle::BackReference(0),
10218 None),
10219 b"...",
10220 []
10221 }
10222 b"naLS_1E_S_E..." => {
10223 Expression::NewArray(
10224 vec![
10225 Expression::Primary(
10226 ExprPrimary::Literal(
10227 TypeHandle::BackReference(0),
10228 5,
10229 6))
10230 ],
10231 TypeHandle::BackReference(0),
10232 None),
10233 b"...",
10234 []
10235 }
10236 b"gsnaLS_1E_S_piE..." => {
10237 Expression::GlobalNewArray(
10238 vec![
10239 Expression::Primary(
10240 ExprPrimary::Literal(
10241 TypeHandle::BackReference(0),
10242 7,
10243 8))
10244 ],
10245 TypeHandle::BackReference(0),
10246 Some(Initializer(vec![]))),
10247 b"...",
10248 []
10249 }
10250 b"naLS_1E_S_piE..." => {
10251 Expression::NewArray(
10252 vec![
10253 Expression::Primary(
10254 ExprPrimary::Literal(
10255 TypeHandle::BackReference(0),
10256 5,
10257 6))
10258 ],
10259 TypeHandle::BackReference(0),
10260 Some(Initializer(vec![]))),
10261 b"...",
10262 []
10263 }
10264 b"gsdlLS_1E..." => {
10265 Expression::GlobalDelete(
10266 Box::new(Expression::Primary(
10267 ExprPrimary::Literal(
10268 TypeHandle::BackReference(0),
10269 7,
10270 8)))),
10271 b"...",
10272 []
10273 }
10274 b"dlLS_1E..." => {
10275 Expression::Delete(
10276 Box::new(Expression::Primary(
10277 ExprPrimary::Literal(
10278 TypeHandle::BackReference(0),
10279 5,
10280 6)))),
10281 b"...",
10282 []
10283 }
10284 b"gsdaLS_1E..." => {
10286 Expression::GlobalDeleteArray(
10287 Box::new(Expression::Primary(
10288 ExprPrimary::Literal(
10289 TypeHandle::BackReference(0),
10290 7,
10291 8)))),
10292 b"...",
10293 []
10294 }
10295 b"daLS_1E..." => {
10296 Expression::DeleteArray(
10297 Box::new(Expression::Primary(
10298 ExprPrimary::Literal(
10299 TypeHandle::BackReference(0),
10300 5,
10301 6)))),
10302 b"...",
10303 []
10304 }
10305 b"dcS_LS_1E..." => {
10306 Expression::DynamicCast(
10307 TypeHandle::BackReference(0),
10308 Box::new(Expression::Primary(
10309 ExprPrimary::Literal(
10310 TypeHandle::BackReference(0),
10311 7,
10312 8)))),
10313 b"...",
10314 []
10315 }
10316 b"scS_LS_1E..." => {
10317 Expression::StaticCast(
10318 TypeHandle::BackReference(0),
10319 Box::new(Expression::Primary(
10320 ExprPrimary::Literal(
10321 TypeHandle::BackReference(0),
10322 7,
10323 8)))),
10324 b"...",
10325 []
10326 }
10327 b"ccS_LS_1E..." => {
10328 Expression::ConstCast(
10329 TypeHandle::BackReference(0),
10330 Box::new(Expression::Primary(
10331 ExprPrimary::Literal(
10332 TypeHandle::BackReference(0),
10333 7,
10334 8)))),
10335 b"...",
10336 []
10337 }
10338 b"rcS_LS_1E..." => {
10339 Expression::ReinterpretCast(
10340 TypeHandle::BackReference(0),
10341 Box::new(Expression::Primary(
10342 ExprPrimary::Literal(
10343 TypeHandle::BackReference(0),
10344 7,
10345 8)))),
10346 b"...",
10347 []
10348 }
10349 b"tiS_..." => {
10350 Expression::TypeidType(TypeHandle::BackReference(0)),
10351 b"...",
10352 []
10353 }
10354 b"teLS_1E..." => {
10355 Expression::TypeidExpr(
10356 Box::new(Expression::Primary(
10357 ExprPrimary::Literal(
10358 TypeHandle::BackReference(0),
10359 5,
10360 6)))),
10361 b"...",
10362 []
10363 }
10364 b"stS_..." => {
10365 Expression::SizeofType(TypeHandle::BackReference(0)),
10366 b"...",
10367 []
10368 }
10369 b"szLS_1E..." => {
10370 Expression::SizeofExpr(
10371 Box::new(Expression::Primary(
10372 ExprPrimary::Literal(
10373 TypeHandle::BackReference(0),
10374 5,
10375 6)))),
10376 b"...",
10377 []
10378 }
10379 b"atS_..." => {
10380 Expression::AlignofType(TypeHandle::BackReference(0)),
10381 b"...",
10382 []
10383 }
10384 b"azLS_1E..." => {
10385 Expression::AlignofExpr(
10386 Box::new(Expression::Primary(
10387 ExprPrimary::Literal(
10388 TypeHandle::BackReference(0),
10389 5,
10390 6)))),
10391 b"...",
10392 []
10393 }
10394 b"nxLS_1E..." => {
10395 Expression::Noexcept(
10396 Box::new(Expression::Primary(
10397 ExprPrimary::Literal(
10398 TypeHandle::BackReference(0),
10399 5,
10400 6)))),
10401 b"...",
10402 []
10403 }
10404 b"T_..." => {
10405 Expression::TemplateParam(TemplateParam(0)),
10406 b"...",
10407 []
10408 }
10409 b"fp_..." => {
10410 Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0))),
10411 b"...",
10412 []
10413 }
10414 b"fL1pK_..." => {
10415 Expression::FunctionParam(FunctionParam(1, CvQualifiers {
10416 restrict: false,
10417 volatile: false,
10418 const_: true,
10419 }, Some(0))),
10420 b"...",
10421 []
10422 }
10423 b"dtT_3abc..." => {
10424 Expression::Member(
10425 Box::new(Expression::TemplateParam(TemplateParam(0))),
10426 MemberName(
10427 Name::Unscoped(
10428 UnscopedName::Unqualified(
10429 UnqualifiedName::Source(
10430 SourceName(
10431 Identifier {
10432 start: 5,
10433 end: 8,
10434 }),
10435 AbiTags::default()))))),
10436 b"...",
10437 []
10438 }
10439 b"ptT_3abc..." => {
10440 Expression::DerefMember(
10441 Box::new(Expression::TemplateParam(TemplateParam(0))),
10442 MemberName(
10443 Name::Unscoped(
10444 UnscopedName::Unqualified(
10445 UnqualifiedName::Source(
10446 SourceName(
10447 Identifier {
10448 start: 5,
10449 end: 8,
10450 }),
10451 AbiTags::default()))))),
10452 b"...",
10453 []
10454 }
10455 b"dtfp_clI3abcE..." => {
10456 Expression::Member(
10457 Box::new(Expression::FunctionParam(FunctionParam(0, CvQualifiers::default(), Some(0)))),
10458 MemberName(
10459 Name::UnscopedTemplate(
10460 UnscopedTemplateNameHandle::NonSubstitution(NonSubstitution(0)),
10461 TemplateArgs(vec![
10462 TemplateArg::Type(
10463 TypeHandle::BackReference(1))])))),
10464 b"...",
10465 [
10466 Substitutable::Type(
10467 Type::ClassEnum(
10468 ClassEnumType::Named(
10469 Name::Unscoped(
10470 UnscopedName::Unqualified(
10471 UnqualifiedName::Source(
10472 SourceName(
10473 Identifier {
10474 start: 9,
10475 end: 12
10476 }),
10477 AbiTags::default()))))))
10478 ]
10479 }
10480 b"dsT_T_..." => {
10482 Expression::PointerToMember(
10483 Box::new(Expression::TemplateParam(TemplateParam(0))),
10484 Box::new(Expression::TemplateParam(TemplateParam(0)))),
10485 b"...",
10486 []
10487 }
10488 b"sZT_..." => {
10489 Expression::SizeofTemplatePack(TemplateParam(0)),
10490 b"...",
10491 []
10492 }
10493 b"sZfp_..." => {
10494 Expression::SizeofFunctionPack(
10495 FunctionParam(0, CvQualifiers::default(), Some(0))),
10496 b"...",
10497 []
10498 }
10499 b"sPE..." => {
10500 Expression::SizeofCapturedTemplatePack(vec![]),
10501 b"...",
10502 []
10503 }
10504 b"spT_..." => {
10505 Expression::PackExpansion(
10506 Box::new(Expression::TemplateParam(TemplateParam(0)))),
10507 b"...",
10508 []
10509 }
10510 b"flplT_..." => {
10511 Expression::Fold(
10512 FoldExpr::UnaryLeft(
10513 SimpleOperatorName::Add,
10514 Box::new(Expression::TemplateParam(TemplateParam(0))),
10515 )
10516 ),
10517 b"...",
10518 []
10519 }
10520 b"fraaT_..." => {
10521 Expression::Fold(
10522 FoldExpr::UnaryRight(
10523 SimpleOperatorName::LogicalAnd,
10524 Box::new(Expression::TemplateParam(TemplateParam(0))),
10525 )
10526 ),
10527 b"...",
10528 []
10529 }
10530 b"fRoospT_spT0_..." => {
10531 Expression::Fold(
10532 FoldExpr::BinaryRight(
10533 SimpleOperatorName::LogicalOr,
10534 Box::new(Expression::PackExpansion(
10535 Box::new(Expression::TemplateParam(TemplateParam(0))))),
10536 Box::new(Expression::PackExpansion(
10537 Box::new(Expression::TemplateParam(TemplateParam(1))))),
10538 )
10539 ),
10540 b"...",
10541 []
10542 }
10543 b"twT_..." => {
10544 Expression::Throw(Box::new(Expression::TemplateParam(TemplateParam(0)))),
10545 b"...",
10546 []
10547 }
10548 b"tr..." => {
10549 Expression::Rethrow,
10550 b"...",
10551 []
10552 }
10553 b"3abc..." => {
10554 Expression::UnresolvedName(
10555 UnresolvedName::Name(
10556 BaseUnresolvedName::Name(
10557 SimpleId(
10558 SourceName(Identifier {
10559 start: 1,
10560 end: 4,
10561 }),
10562 None)))),
10563 b"...",
10564 []
10565 }
10566 b"L_Z3abcE..." => {
10567 Expression::Primary(
10568 ExprPrimary::External(
10569 MangledName::Encoding(
10570 Encoding::Data(
10571 Name::Unscoped(
10572 UnscopedName::Unqualified(
10573 UnqualifiedName::Source(
10574 SourceName(Identifier {
10575 start: 4,
10576 end: 7,
10577 }),
10578 AbiTags::default())))), vec![]))),
10579 b"...",
10580 []
10581 }
10582 b"cldtdefpT4TypeadsrT_5EnterE..." => {
10584 Expression::Call(
10585 Box::new(Expression::Member(
10586 Box::new(Expression::Unary(OperatorName::Simple(SimpleOperatorName::Deref),
10587 Box::new(Expression::FunctionParam(
10588 FunctionParam(0,
10589 CvQualifiers::default(),
10590 None)
10591 ))
10592 )),
10593 MemberName(
10594 Name::Unscoped(
10595 UnscopedName::Unqualified(
10596 UnqualifiedName::Source(
10597 SourceName(Identifier {
10598 start: 10,
10599 end: 14,
10600 }),
10601 AbiTags::default()))
10602 )
10603 )
10604 )),
10605 vec![Expression::Unary(OperatorName::Simple(SimpleOperatorName::AddressOf),
10606 Box::new(Expression::UnresolvedName(
10607 UnresolvedName::Nested1(
10608 UnresolvedTypeHandle::BackReference(1),
10609 vec![],
10610 BaseUnresolvedName::Name(
10611 SimpleId(
10612 SourceName(Identifier {
10613 start: 21,
10614 end: 26
10615 }
10616 ),
10617 None
10618 )
10619 )
10620 ))))]
10621 ),
10622 b"...",
10623 [
10624 Substitutable::UnresolvedType(UnresolvedType::Template(TemplateParam(0), None))
10625 ]
10626 }
10627 }
10628 Err => {
10629 b"dtStfp_clI3abcE..." => Error::UnexpectedText,
10630 b"flpsT_..." => Error::UnexpectedText,
10632 }
10633 }
10634 });
10635 }
10636
10637 #[test]
10638 fn parse_unresolved_name() {
10639 assert_parse!(UnresolvedName {
10640 with subs [
10641 Substitutable::UnresolvedType(
10642 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10643 ] => {
10644 Ok => {
10645 b"gs3abc..." => {
10646 UnresolvedName::Global(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10647 start: 3,
10648 end: 6,
10649 }), None))),
10650 b"...",
10651 []
10652 }
10653 b"3abc..." => {
10654 UnresolvedName::Name(BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10655 start: 1,
10656 end: 4,
10657 }), None))),
10658 b"...",
10659 []
10660 }
10661 b"srS_3abc..." => {
10662 UnresolvedName::Nested1(UnresolvedTypeHandle::BackReference(0),
10663 vec![],
10664 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10665 start: 5,
10666 end: 8,
10667 }), None))),
10668 b"...",
10669 []
10670 }
10671 b"srNS_3abc3abcE3abc..." => {
10672 UnresolvedName::Nested1(
10673 UnresolvedTypeHandle::BackReference(0),
10674 vec![
10675 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10676 start: 6,
10677 end: 9,
10678 }), None)),
10679 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10680 start: 10,
10681 end: 13,
10682 }), None)),
10683 ],
10684 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10685 start: 15,
10686 end: 18,
10687 }), None))),
10688 b"...",
10689 []
10690 }
10691 b"gssr3abcE3abc..." => {
10692 UnresolvedName::GlobalNested2(
10693 vec![
10694 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10695 start: 5,
10696 end: 8,
10697 }), None)),
10698 ],
10699 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10700 start: 10,
10701 end: 13,
10702 }), None))),
10703 b"...",
10704 []
10705 }
10706 b"sr3abcE3abc..." => {
10707 UnresolvedName::Nested2(
10708 vec![
10709 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10710 start: 3,
10711 end: 6,
10712 }), None)),
10713 ],
10714 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10715 start: 8,
10716 end: 11,
10717 }), None))),
10718 b"...",
10719 []
10720 }
10721 }
10722 Err => {
10723 b"zzzzzz" => Error::UnexpectedText,
10724 b"gszzz" => Error::UnexpectedText,
10725 b"gssrzzz" => Error::UnexpectedText,
10726 b"srNzzz" => Error::UnexpectedText,
10727 b"srzzz" => Error::UnexpectedText,
10728 b"srN3abczzzz" => Error::UnexpectedText,
10729 b"srN3abcE" => Error::UnexpectedText,
10730 b"srN3abc" => Error::UnexpectedText,
10731 b"srN" => Error::UnexpectedEnd,
10732 b"sr" => Error::UnexpectedEnd,
10733 b"gssr" => Error::UnexpectedEnd,
10734 b"gs" => Error::UnexpectedEnd,
10735 b"" => Error::UnexpectedEnd,
10736 }
10737 }
10738 });
10739 }
10740
10741 #[test]
10742 fn parse_unresolved_type_handle() {
10743 assert_parse!(UnresolvedTypeHandle {
10744 with subs [
10745 Substitutable::UnresolvedType(
10746 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10747 ] => {
10748 Ok => {
10749 b"S_..." => {
10750 UnresolvedTypeHandle::BackReference(0),
10751 b"...",
10752 []
10753 }
10754 b"T_..." => {
10755 UnresolvedTypeHandle::BackReference(1),
10756 b"...",
10757 [
10758 Substitutable::UnresolvedType(
10759 UnresolvedType::Template(TemplateParam(0), None)),
10760 ]
10761 }
10762 b"T_IS_E..." => {
10763 UnresolvedTypeHandle::BackReference(1),
10764 b"...",
10765 [
10766 Substitutable::UnresolvedType(
10767 UnresolvedType::Template(TemplateParam(0), Some(TemplateArgs(vec![
10768 TemplateArg::Type(TypeHandle::BackReference(0))
10769 ])))),
10770 ]
10771 }
10772 b"DTtrE..." => {
10773 UnresolvedTypeHandle::BackReference(1),
10774 b"...",
10775 [
10776 Substitutable::UnresolvedType(
10777 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow)))
10778 ]
10779
10780 }
10781 }
10782 Err => {
10783 b"zzzzzzz" => Error::UnexpectedText,
10784 b"" => Error::UnexpectedEnd,
10785 }
10786 }
10787 });
10788 }
10789
10790 #[test]
10791 fn parse_unresolved_qualifier_level() {
10792 assert_parse!(UnresolvedQualifierLevel {
10793 with subs [
10794 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10795 ] => {
10796 Ok => {
10797 b"3abc..." => {
10798 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10799 start: 1,
10800 end: 4,
10801 }), None)),
10802 b"...",
10803 []
10804 }
10805 b"3abcIS_E..." => {
10806 UnresolvedQualifierLevel(SimpleId(SourceName(Identifier {
10807 start: 1,
10808 end: 4,
10809 }), Some(TemplateArgs(vec![
10810 TemplateArg::Type(TypeHandle::BackReference(0))
10811 ])))),
10812 b"...",
10813 []
10814 }
10815 }
10816 Err => {
10817 b"zzz" => Error::UnexpectedText,
10818 b"" => Error::UnexpectedEnd,
10819 }
10820 }
10821 });
10822 }
10823
10824 #[test]
10825 fn parse_simple_id() {
10826 assert_parse!(SimpleId {
10827 with subs [
10828 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10829 ] => {
10830 Ok => {
10831 b"3abc..." => {
10832 SimpleId(SourceName(Identifier {
10833 start: 1,
10834 end: 4,
10835 }), None),
10836 b"...",
10837 []
10838 }
10839 b"3abcIS_E..." => {
10840 SimpleId(SourceName(Identifier {
10841 start: 1,
10842 end: 4,
10843 }), Some(TemplateArgs(vec![
10844 TemplateArg::Type(TypeHandle::BackReference(0))
10845 ]))),
10846 b"...",
10847 []
10848 }
10849 }
10850 Err => {
10851 b"zzz" => Error::UnexpectedText,
10852 b"" => Error::UnexpectedEnd,
10853 }
10854 }
10855 });
10856 }
10857
10858 #[test]
10859 fn parse_base_unresolved_name() {
10860 assert_parse!(BaseUnresolvedName {
10861 with subs [
10862 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10863 ] => {
10864 Ok => {
10865 b"3abc..." => {
10866 BaseUnresolvedName::Name(SimpleId(SourceName(Identifier {
10867 start: 1,
10868 end: 4,
10869 }), None)),
10870 b"...",
10871 []
10872 }
10873 b"onnw..." => {
10874 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New), None),
10875 b"...",
10876 []
10877 }
10878 b"onnwIS_E..." => {
10879 BaseUnresolvedName::Operator(OperatorName::Simple(SimpleOperatorName::New),
10880 Some(TemplateArgs(vec![
10881 TemplateArg::Type(TypeHandle::BackReference(0))
10882 ]))),
10883 b"...",
10884 []
10885 }
10886 b"dn3abc..." => {
10887 BaseUnresolvedName::Destructor(DestructorName::Name(SimpleId(SourceName(Identifier {
10888 start: 3,
10889 end: 6,
10890 }), None))),
10891 b"...",
10892 []
10893 }
10894 }
10895 Err => {
10896 b"ozzz" => Error::UnexpectedText,
10897 b"dzzz" => Error::UnexpectedText,
10898 b"dn" => Error::UnexpectedEnd,
10899 b"on" => Error::UnexpectedEnd,
10900 b"" => Error::UnexpectedEnd,
10901 }
10902 }
10903 });
10904 }
10905
10906 #[test]
10907 fn parse_destructor_name() {
10908 assert_parse!(DestructorName {
10909 with subs [
10910 Substitutable::UnresolvedType(
10911 UnresolvedType::Decltype(Decltype::Expression(Expression::Rethrow))),
10912 ] => {
10913 Ok => {
10914 b"S_..." => {
10915 DestructorName::Unresolved(UnresolvedTypeHandle::BackReference(0)),
10916 b"...",
10917 []
10918 }
10919 b"3abc..." => {
10920 DestructorName::Name(SimpleId(SourceName(Identifier {
10921 start: 1,
10922 end: 4,
10923 }), None)),
10924 b"...",
10925 []
10926 }
10927 }
10928 Err => {
10929 b"zzz" => Error::UnexpectedText,
10930 b"" => Error::UnexpectedEnd,
10931 }
10932 }
10933 });
10934 }
10935
10936 #[test]
10937 fn parse_expr_primary() {
10938 assert_parse!(ExprPrimary {
10939 with subs [
10940 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
10941 ] => {
10942 Ok => {
10943 b"LS_12345E..." => {
10944 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 8),
10945 b"...",
10946 []
10947 }
10948 b"LS_E..." => {
10949 ExprPrimary::Literal(TypeHandle::BackReference(0), 3, 3),
10950 b"...",
10951 []
10952 }
10953 b"L_Z3abcE..." => {
10954 ExprPrimary::External(
10955 MangledName::Encoding(
10956 Encoding::Data(
10957 Name::Unscoped(
10958 UnscopedName::Unqualified(
10959 UnqualifiedName::Source(
10960 SourceName(Identifier {
10961 start: 4,
10962 end: 7,
10963 }),
10964 AbiTags::default())))), vec![])),
10965 b"...",
10966 []
10967 }
10968 }
10969 Err => {
10970 b"zzz" => Error::UnexpectedText,
10971 b"LS_zzz" => Error::UnexpectedEnd,
10972 b"LS_12345" => Error::UnexpectedEnd,
10973 b"LS_" => Error::UnexpectedEnd,
10974 b"L" => Error::UnexpectedEnd,
10975 b"" => Error::UnexpectedEnd,
10976 }
10977 }
10978 });
10979 }
10980
10981 #[test]
10982 fn parse_initializer() {
10983 assert_parse!(Initializer {
10984 Ok => {
10985 b"piE..." => {
10986 Initializer(vec![]),
10987 b"..."
10988 }
10989 b"pitrtrtrE..." => {
10990 Initializer(vec![
10991 Expression::Rethrow,
10992 Expression::Rethrow,
10993 Expression::Rethrow,
10994 ]),
10995 b"..."
10996 }
10997 }
10998 Err => {
10999 b"pirtrtrt..." => Error::UnexpectedText,
11000 b"pi..." => Error::UnexpectedText,
11001 b"..." => Error::UnexpectedText,
11002 b"pirt" => Error::UnexpectedText,
11003 b"pi" => Error::UnexpectedEnd,
11004 b"p" => Error::UnexpectedEnd,
11005 b"" => Error::UnexpectedEnd,
11006 }
11007 });
11008 }
11009
11010 #[test]
11011 fn parse_local_name() {
11012 assert_parse!(LocalName {
11013 Ok => {
11014 b"Z3abcE3def_0..." => {
11015 LocalName::Relative(
11016 Box::new(Encoding::Data(
11017 Name::Unscoped(
11018 UnscopedName::Unqualified(
11019 UnqualifiedName::Source(
11020 SourceName(Identifier {
11021 start: 2,
11022 end: 5,
11023 }),
11024 AbiTags::default()))))),
11025 Some(Box::new(Name::Unscoped(
11026 UnscopedName::Unqualified(
11027 UnqualifiedName::Source(
11028 SourceName(Identifier {
11029 start: 7,
11030 end: 10,
11031 }),
11032 AbiTags::default()))))),
11033 Some(Discriminator(0))),
11034 b"..."
11035 }
11036 b"Z3abcE3def..." => {
11037 LocalName::Relative(
11038 Box::new(Encoding::Data(
11039 Name::Unscoped(
11040 UnscopedName::Unqualified(
11041 UnqualifiedName::Source(
11042 SourceName(Identifier {
11043 start: 2,
11044 end: 5,
11045 }),
11046 AbiTags::default()))))),
11047 Some(Box::new(Name::Unscoped(
11048 UnscopedName::Unqualified(
11049 UnqualifiedName::Source(
11050 SourceName(Identifier {
11051 start: 7,
11052 end: 10,
11053 }),
11054 AbiTags::default()))))),
11055 None),
11056 b"..."
11057 }
11058 b"Z3abcEs_0..." => {
11059 LocalName::Relative(
11060 Box::new(Encoding::Data(
11061 Name::Unscoped(
11062 UnscopedName::Unqualified(
11063 UnqualifiedName::Source(
11064 SourceName(Identifier {
11065 start: 2,
11066 end: 5,
11067 }),
11068 AbiTags::default()))))),
11069 None,
11070 Some(Discriminator(0))),
11071 b"..."
11072 }
11073 b"Z3abcEs..." => {
11074 LocalName::Relative(
11075 Box::new(Encoding::Data(
11076 Name::Unscoped(
11077 UnscopedName::Unqualified(
11078 UnqualifiedName::Source(
11079 SourceName(Identifier {
11080 start: 2,
11081 end: 5,
11082 }),
11083 AbiTags::default()))))),
11084 None,
11085 None),
11086 b"..."
11087 }
11088 b"Z3abcEd1_3abc..." => {
11089 LocalName::Default(
11090 Box::new(Encoding::Data(
11091 Name::Unscoped(
11092 UnscopedName::Unqualified(
11093 UnqualifiedName::Source(
11094 SourceName(Identifier {
11095 start: 2,
11096 end: 5,
11097 }),
11098 AbiTags::default()))))),
11099 Some(1),
11100 Box::new(Name::Unscoped(
11101 UnscopedName::Unqualified(
11102 UnqualifiedName::Source(
11103 SourceName(Identifier {
11104 start: 10,
11105 end: 13,
11106 }),
11107 AbiTags::default()))))),
11108 b"..."
11109 }
11110 b"Z3abcEd_3abc..." => {
11111 LocalName::Default(
11112 Box::new(Encoding::Data(
11113 Name::Unscoped(
11114 UnscopedName::Unqualified(
11115 UnqualifiedName::Source(
11116 SourceName(Identifier {
11117 start: 2,
11118 end: 5,
11119 }),
11120 AbiTags::default()))))),
11121 None,
11122 Box::new(Name::Unscoped(
11123 UnscopedName::Unqualified(
11124 UnqualifiedName::Source(
11125 SourceName(Identifier {
11126 start: 9,
11127 end: 12,
11128 }), AbiTags::default()))))),
11129 b"..."
11130 }
11131 }
11132 Err => {
11133 b"A" => Error::UnexpectedText,
11134 b"Z1a" => Error::UnexpectedEnd,
11135 b"Z1aE" => Error::UnexpectedEnd,
11136 b"Z" => Error::UnexpectedEnd,
11137 b"" => Error::UnexpectedEnd,
11138 }
11139 });
11140 }
11141
11142 #[test]
11143 fn parse_closure_type_name() {
11144 assert_parse!(ClosureTypeName {
11145 Ok => {
11146 b"UlvE_..." => {
11147 ClosureTypeName(LambdaSig(vec![]), None),
11148 b"..."
11149 }
11150 b"UlvE36_..." => {
11151 ClosureTypeName(LambdaSig(vec![]), Some(36)),
11152 b"..."
11153 }
11154 }
11155 Err => {
11156 b"UlvE36zzz" => Error::UnexpectedText,
11157 b"UlvEzzz" => Error::UnexpectedText,
11158 b"Ulvzzz" => Error::UnexpectedText,
11159 b"zzz" => Error::UnexpectedText,
11160 b"UlvE10" => Error::UnexpectedEnd,
11161 b"UlvE" => Error::UnexpectedEnd,
11162 b"Ulv" => Error::UnexpectedEnd,
11163 b"Ul" => Error::UnexpectedEnd,
11164 b"U" => Error::UnexpectedEnd,
11165 b"" => Error::UnexpectedEnd,
11166 }
11167 });
11168 }
11169
11170 #[test]
11171 fn parse_lambda_sig() {
11172 assert_parse!(LambdaSig {
11173 with subs [
11174 Substitutable::Type(
11175 Type::PointerTo(
11176 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Bool))))
11177 ] => {
11178 Ok => {
11179 b"v..." => {
11180 LambdaSig(vec![]),
11181 b"...",
11182 []
11183 }
11184 b"S_S_S_..." => {
11185 LambdaSig(vec![
11186 TypeHandle::BackReference(0),
11187 TypeHandle::BackReference(0),
11188 TypeHandle::BackReference(0),
11189 ]),
11190 b"...",
11191 []
11192 }
11193 }
11194 Err => {
11195 b"..." => Error::UnexpectedText,
11196 b"S" => Error::UnexpectedEnd,
11197 b"" => Error::UnexpectedEnd,
11198 }
11199 }
11200 });
11201 }
11202
11203 #[test]
11204 fn parse_substitution() {
11205 assert_parse!(Substitution {
11206 with subs [
11207 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
11208 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow))),
11209 Substitutable::Type(Type::Decltype(Decltype::Expression(Expression::Rethrow)))
11210 ] => {
11211 Ok => {
11212 b"S_..." => {
11213 Substitution::BackReference(0),
11214 b"...",
11215 []
11216 }
11217 b"S1_..." => {
11218 Substitution::BackReference(2),
11219 b"...",
11220 []
11221 }
11222 b"St..." => {
11223 Substitution::WellKnown(WellKnownComponent::Std),
11224 b"...",
11225 []
11226 }
11227 b"Sa..." => {
11228 Substitution::WellKnown(WellKnownComponent::StdAllocator),
11229 b"...",
11230 []
11231 }
11232 b"Sb..." => {
11233 Substitution::WellKnown(WellKnownComponent::StdString1),
11234 b"...",
11235 []
11236 }
11237 b"Ss..." => {
11238 Substitution::WellKnown(WellKnownComponent::StdString2),
11239 b"...",
11240 []
11241 }
11242 b"Si..." => {
11243 Substitution::WellKnown(WellKnownComponent::StdIstream),
11244 b"...",
11245 []
11246 }
11247 b"So..." => {
11248 Substitution::WellKnown(WellKnownComponent::StdOstream),
11249 b"...",
11250 []
11251 }
11252 b"Sd..." => {
11253 Substitution::WellKnown(WellKnownComponent::StdIostream),
11254 b"...",
11255 []
11256 }
11257 }
11258 Err => {
11259 b"S999_" => Error::BadBackReference,
11260 b"Sz" => Error::UnexpectedText,
11261 b"zzz" => Error::UnexpectedText,
11262 b"S1" => Error::UnexpectedEnd,
11263 b"S" => Error::UnexpectedEnd,
11264 b"" => Error::UnexpectedEnd,
11265 }
11266 }
11267 });
11268 }
11269
11270 #[test]
11271 fn parse_special_name() {
11272 assert_parse!(SpecialName {
11273 Ok => {
11274 b"TVi..." => {
11275 SpecialName::VirtualTable(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11276 b"..."
11277 }
11278 b"TTi..." => {
11279 SpecialName::Vtt(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11280 b"..."
11281 }
11282 b"TIi..." => {
11283 SpecialName::Typeinfo(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11284 b"..."
11285 }
11286 b"TSi..." => {
11287 SpecialName::TypeinfoName(TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11288 b"..."
11289 }
11290 b"Tv42_36_3abc..." => {
11291 SpecialName::VirtualOverrideThunk(
11292 CallOffset::Virtual(VOffset(42, 36)),
11293 Box::new(Encoding::Data(
11294 Name::Unscoped(
11295 UnscopedName::Unqualified(
11296 UnqualifiedName::Source(
11297 SourceName(Identifier {
11298 start: 9,
11299 end: 12,
11300 }), AbiTags::default())))))),
11301 b"..."
11302 }
11303 b"Tcv42_36_v42_36_3abc..." => {
11304 SpecialName::VirtualOverrideThunkCovariant(
11305 CallOffset::Virtual(VOffset(42, 36)),
11306 CallOffset::Virtual(VOffset(42, 36)),
11307 Box::new(Encoding::Data(
11308 Name::Unscoped(
11309 UnscopedName::Unqualified(
11310 UnqualifiedName::Source(
11311 SourceName(Identifier {
11312 start: 17,
11313 end: 20,
11314 }), AbiTags::default())))))),
11315 b"..."
11316 }
11317 b"GV3abc..." => {
11318 SpecialName::Guard(
11319 Name::Unscoped(
11320 UnscopedName::Unqualified(
11321 UnqualifiedName::Source(
11322 SourceName(Identifier {
11323 start: 3,
11324 end: 6,
11325 }), AbiTags::default())))),
11326 b"..."
11327 }
11328 b"GR3abc_..." => {
11329 SpecialName::GuardTemporary(
11330 Name::Unscoped(
11331 UnscopedName::Unqualified(
11332 UnqualifiedName::Source(
11333 SourceName(Identifier {
11334 start: 3,
11335 end: 6,
11336 }),
11337 AbiTags::default()))),
11338 0),
11339 b"..."
11340 }
11341 b"GR3abc0_..." => {
11342 SpecialName::GuardTemporary(
11343 Name::Unscoped(
11344 UnscopedName::Unqualified(
11345 UnqualifiedName::Source(
11346 SourceName(Identifier {
11347 start: 3,
11348 end: 6,
11349 }),
11350 AbiTags::default()))),
11351 1),
11352 b"..."
11353 }
11354 b"Gr4_abc..." => {
11355 SpecialName::JavaResource(vec![ResourceName {
11356 start: 4,
11357 end: 7,
11358 }]),
11359 b"..."
11360 }
11361 b"TCc7_i..." => {
11362 SpecialName::ConstructionVtable(
11363 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Char)),
11364 7,
11365 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))
11366 ),
11367 b"..."
11368 }
11369 b"TFi..." => {
11370 SpecialName::TypeinfoFunction(
11371 TypeHandle::Builtin(BuiltinType::Standard(StandardBuiltinType::Int))),
11372 b"..."
11373 }
11374 b"TH4name..." => {
11375 SpecialName::TlsInit(
11376 Name::Unscoped(
11377 UnscopedName::Unqualified(
11378 UnqualifiedName::Source(
11379 SourceName(Identifier { start: 3, end: 7 }),
11380 AbiTags::default())))),
11381 b"..."
11382 }
11383 b"TW4name..." => {
11384 SpecialName::TlsWrapper(
11385 Name::Unscoped(
11386 UnscopedName::Unqualified(
11387 UnqualifiedName::Source(
11388 SourceName(Identifier { start: 3, end: 7 }),
11389 AbiTags::default())))),
11390 b"..."
11391 }
11392 }
11393 Err => {
11394 b"TZ" => Error::UnexpectedText,
11395 b"GZ" => Error::UnexpectedText,
11396 b"GR3abcz" => Error::UnexpectedText,
11397 b"GR3abc0z" => Error::UnexpectedText,
11398 b"T" => Error::UnexpectedEnd,
11399 b"G" => Error::UnexpectedEnd,
11400 b"" => Error::UnexpectedEnd,
11401 b"GR3abc" => Error::UnexpectedEnd,
11402 b"GR3abc0" => Error::UnexpectedEnd,
11403 b"TCcn7_i..." => Error::UnexpectedText,
11405 b"Gr3abc0" => Error::UnexpectedText,
11406 }
11407 });
11408 }
11409
11410 #[test]
11411 fn parse_function_param() {
11412 assert_parse!(FunctionParam {
11413 Ok => {
11414 b"fpK_..." => {
11415 FunctionParam(0,
11416 CvQualifiers {
11417 restrict: false,
11418 volatile: false,
11419 const_: true,
11420 },
11421 Some(0)),
11422 b"..."
11423 }
11424 b"fL1pK_..." => {
11425 FunctionParam(1,
11426 CvQualifiers {
11427 restrict: false,
11428 volatile: false,
11429 const_: true,
11430 },
11431 Some(0)),
11432 b"..."
11433 }
11434 b"fpK3_..." => {
11435 FunctionParam(0,
11436 CvQualifiers {
11437 restrict: false,
11438 volatile: false,
11439 const_: true,
11440 },
11441 Some(4)),
11442 b"..."
11443 }
11444 b"fL1pK4_..." => {
11445 FunctionParam(1,
11446 CvQualifiers {
11447 restrict: false,
11448 volatile: false,
11449 const_: true,
11450 },
11451 Some(5)),
11452 b"..."
11453 }
11454 }
11455 Err => {
11456 b"fz" => Error::UnexpectedText,
11457 b"fLp_" => Error::UnexpectedText,
11458 b"fpL_" => Error::UnexpectedText,
11459 b"fL1pK4z" => Error::UnexpectedText,
11460 b"fL1pK4" => Error::UnexpectedEnd,
11461 b"fL1p" => Error::UnexpectedEnd,
11462 b"fL1" => Error::UnexpectedEnd,
11463 b"fL" => Error::UnexpectedEnd,
11464 b"f" => Error::UnexpectedEnd,
11465 b"" => Error::UnexpectedEnd,
11466 }
11467 });
11468 }
11469
11470 #[test]
11471 fn parse_discriminator() {
11472 assert_parse!(Discriminator {
11473 Ok => {
11474 b"_0..." => {
11475 Discriminator(0),
11476 b"..."
11477 }
11478 b"_9..." => {
11479 Discriminator(9),
11480 b"..."
11481 }
11482 b"__99_..." => {
11483 Discriminator(99),
11484 b"..."
11485 }
11486 }
11487 Err => {
11488 b"_n1" => Error::UnexpectedText,
11489 b"__99..." => Error::UnexpectedText,
11490 b"__99" => Error::UnexpectedEnd,
11491 b"..." => Error::UnexpectedText,
11492 }
11493 });
11494 }
11495
11496 #[test]
11497 fn parse_data_member_prefix() {
11498 assert_parse!(DataMemberPrefix {
11499 Ok => {
11500 b"3fooM..." => {
11501 DataMemberPrefix(SourceName(Identifier {
11502 start: 1,
11503 end: 4,
11504 })),
11505 b"..."
11506 }
11507 }
11508 Err => {
11509 b"zzz" => Error::UnexpectedText,
11510 b"1" => Error::UnexpectedEnd,
11511 b"" => Error::UnexpectedEnd,
11512 }
11513 });
11514 }
11515
11516 #[test]
11517 fn parse_ref_qualifier() {
11518 assert_parse!(RefQualifier {
11519 Ok => {
11520 b"R..." => {
11521 RefQualifier::LValueRef,
11522 b"..."
11523 }
11524 b"O..." => {
11525 RefQualifier::RValueRef,
11526 b"..."
11527 }
11528 }
11529 Err => {
11530 b"..." => Error::UnexpectedText,
11531 b"" => Error::UnexpectedEnd,
11532 }
11533 });
11534 }
11535
11536 #[test]
11537 fn parse_cv_qualifiers() {
11538 assert_parse!(CvQualifiers {
11539 Ok => {
11540 b"" => {
11541 CvQualifiers { restrict: false, volatile: false, const_: false },
11542 b""
11543 }
11544 b"..." => {
11545 CvQualifiers { restrict: false, volatile: false, const_: false },
11546 b"..."
11547 }
11548 b"r..." => {
11549 CvQualifiers { restrict: true, volatile: false, const_: false },
11550 b"..."
11551 }
11552 b"rV..." => {
11553 CvQualifiers { restrict: true, volatile: true, const_: false },
11554 b"..."
11555 }
11556 b"rVK..." => {
11557 CvQualifiers { restrict: true, volatile: true, const_: true },
11558 b"..."
11559 }
11560 b"V" => {
11561 CvQualifiers { restrict: false, volatile: true, const_: false },
11562 b""
11563 }
11564 b"VK" => {
11565 CvQualifiers { restrict: false, volatile: true, const_: true },
11566 b""
11567 }
11568 b"K..." => {
11569 CvQualifiers { restrict: false, volatile: false, const_: true },
11570 b"..."
11571 }
11572 }
11573 Err => {
11574 }
11576 });
11577 }
11578
11579 #[test]
11580 fn parse_builtin_type() {
11581 assert_parse!(BuiltinType {
11582 Ok => {
11583 b"c..." => {
11584 BuiltinType::Standard(StandardBuiltinType::Char),
11585 b"..."
11586 }
11587 b"c" => {
11588 BuiltinType::Standard(StandardBuiltinType::Char),
11589 b""
11590 }
11591 b"u3abc..." => {
11592 BuiltinType::Extension(SourceName(Identifier {
11593 start: 2,
11594 end: 5,
11595 })),
11596 b"..."
11597 }
11598 b"DF16b..." => {
11599 BuiltinType::Standard(StandardBuiltinType::BFloat16),
11600 b"..."
11601 }
11602 }
11603 Err => {
11604 b"." => Error::UnexpectedText,
11605 b"" => Error::UnexpectedEnd,
11606 }
11607 });
11608 }
11609
11610 #[test]
11611 fn parse_parametric_builtin_type() {
11612 assert_parse!(BuiltinType {
11613 Ok => {
11614 b"DB8_..." => {
11615 BuiltinType::Parametric(ParametricBuiltinType::SignedBitInt(8)),
11616 b"..."
11617 }
11618 b"DUsZT_" => {
11619 BuiltinType::Parametric(ParametricBuiltinType::UnsignedBitIntExpression(Box::new(Expression::SizeofTemplatePack(TemplateParam(0))))),
11620 b""
11621 }
11622 b"DF128_..." => {
11623 BuiltinType::Parametric(ParametricBuiltinType::FloatN(128)),
11624 b"..."
11625 }
11626 b"DF256x..." => {
11627 BuiltinType::Parametric(ParametricBuiltinType::FloatNx(256)),
11628 b"..."
11629 }
11630 }
11631 Err => {
11632 b"DB100000000000000000000000_" => Error::Overflow,
11633 b"DFsZT_" => Error::UnexpectedText,
11634 b"DB" => Error::UnexpectedEnd,
11635 b"DB32" => Error::UnexpectedEnd,
11636 }
11637 });
11638 }
11639
11640 #[test]
11641 fn parse_template_param() {
11642 assert_parse!(TemplateParam {
11643 Ok => {
11644 b"T_..." => {
11645 TemplateParam(0),
11646 b"..."
11647 }
11648 b"T3_..." => {
11649 TemplateParam(4),
11650 b"..."
11651 }
11652 }
11653 Err => {
11654 b"wtf" => Error::UnexpectedText,
11655 b"Twtf" => Error::UnexpectedText,
11656 b"T3wtf" => Error::UnexpectedText,
11657 b"T" => Error::UnexpectedEnd,
11658 b"T3" => Error::UnexpectedEnd,
11659 b"" => Error::UnexpectedEnd,
11660 }
11661 });
11662 }
11663
11664 #[test]
11665 fn parse_unscoped_name() {
11666 assert_parse!(UnscopedName {
11667 Ok => {
11668 b"St5hello..." => {
11669 UnscopedName::Std(UnqualifiedName::Source(SourceName(Identifier {
11670 start: 3,
11671 end: 8,
11672 }),
11673 AbiTags::default())),
11674 b"..."
11675 }
11676 b"5hello..." => {
11677 UnscopedName::Unqualified(UnqualifiedName::Source(SourceName(Identifier {
11678 start: 1,
11679 end: 6,
11680 }), AbiTags::default())),
11681 b"..."
11682 }
11683 }
11684 Err => {
11685 b"St..." => Error::UnexpectedText,
11686 b"..." => Error::UnexpectedText,
11687 b"" => Error::UnexpectedEnd,
11688 }
11689 });
11690 }
11691
11692 #[test]
11693 fn parse_unqualified_name() {
11694 assert_parse!(UnqualifiedName {
11701 Ok => {
11702 b"qu.." => {
11703 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question), AbiTags::default()),
11704 b".."
11705 }
11706 b"onqu.." => {
11707 UnqualifiedName::Operator(OperatorName::Simple(SimpleOperatorName::Question), AbiTags::default()),
11708 b".."
11709 }
11710 b"C1.." => {
11711 UnqualifiedName::CtorDtor(CtorDtorName::CompleteConstructor(None), AbiTags::default()),
11712 b".."
11713 }
11714 b"10abcdefghij..." => {
11715 UnqualifiedName::Source(SourceName(Identifier {
11716 start: 2,
11717 end: 12,
11718 }), AbiTags::default()),
11719 b"..."
11720 }
11721 b"UllE_..." => {
11722 UnqualifiedName::ClosureType(
11723 ClosureTypeName(
11724 LambdaSig(vec![
11725 TypeHandle::Builtin(
11726 BuiltinType::Standard(
11727 StandardBuiltinType::Long))
11728 ]),
11729 None),
11730 AbiTags::default()),
11731 b"..."
11732 }
11733 b"Ut5_..." => {
11734 UnqualifiedName::UnnamedType(UnnamedTypeName(Some(5)), AbiTags::default()),
11735 b"..."
11736 }
11737 b"L3foo_0..." => {
11738 UnqualifiedName::LocalSourceName(
11739 SourceName(Identifier {
11740 start: 2,
11741 end: 5
11742 }),
11743 Some(Discriminator(0)),
11744 AbiTags::default(),
11745 ),
11746 "..."
11747 }
11748 b"L3foo..." => {
11749 UnqualifiedName::LocalSourceName(
11750 SourceName(Identifier {
11751 start: 2,
11752 end: 5
11753 }),
11754 None,
11755 AbiTags::default(),
11756 ),
11757 "..."
11758 }
11759 b"quB1Q.." => {
11760 UnqualifiedName::Operator(
11761 OperatorName::Simple(SimpleOperatorName::Question),
11762 AbiTags(vec![AbiTag(
11763 SourceName(
11764 Identifier {
11765 start: 4,
11766 end: 5,
11767 },
11768 ),
11769 )])
11770 ),
11771 b".."
11772 }
11773 b"C1B1Q.." => {
11774 UnqualifiedName::CtorDtor(
11775 CtorDtorName::CompleteConstructor(None),
11776 AbiTags(vec![AbiTag(
11777 SourceName(
11778 Identifier {
11779 start: 4,
11780 end: 5,
11781 },
11782 ),
11783 )])
11784 ),
11785 b".."
11786 }
11787 b"10abcdefghijB1QB2lp..." => {
11788 UnqualifiedName::Source(
11789 SourceName(Identifier {
11790 start: 2,
11791 end: 12,
11792 }),
11793 AbiTags(vec![
11794 AbiTag(
11795 SourceName(
11796 Identifier {
11797 start: 14,
11798 end: 15,
11799 },
11800 ),
11801 ),
11802 AbiTag(
11803 SourceName(
11804 Identifier {
11805 start: 17,
11806 end: 19,
11807 },
11808 ),
11809 ),
11810 ])
11811 ),
11812 b"..."
11813 }
11814 b"UllE_B1Q..." => {
11815 UnqualifiedName::ClosureType(
11816 ClosureTypeName(
11817 LambdaSig(vec![
11818 TypeHandle::Builtin(
11819 BuiltinType::Standard(
11820 StandardBuiltinType::Long))
11821 ]),
11822 None),
11823 AbiTags(vec![AbiTag(
11824 SourceName(
11825 Identifier {
11826 start: 7,
11827 end: 8,
11828 },
11829 ),
11830 )])
11831 ),
11832 b"..."
11833 }
11834 b"Ut5_B1QB2lp..." => {
11835 UnqualifiedName::UnnamedType(
11836 UnnamedTypeName(Some(5)),
11837 AbiTags(vec![
11838 AbiTag(
11839 SourceName(
11840 Identifier {
11841 start: 6,
11842 end: 7,
11843 },
11844 ),
11845 ),
11846 AbiTag(
11847 SourceName(
11848 Identifier {
11849 start: 9,
11850 end: 11,
11851 },
11852 ),
11853 ),
11854 ])
11855 ),
11856 b"..."
11857 }
11858 b"L3foo_0B1Q..." => {
11859 UnqualifiedName::LocalSourceName(
11860 SourceName(Identifier {
11861 start: 2,
11862 end: 5
11863 }),
11864 Some(Discriminator(0)),
11865 AbiTags(vec![AbiTag(
11866 SourceName(
11867 Identifier {
11868 start: 9,
11869 end: 10,
11870 },
11871 ),
11872 )])
11873 ),
11874 "..."
11875 }
11876 b"L3fooB1QB2lp..." => {
11877 UnqualifiedName::LocalSourceName(
11878 SourceName(Identifier {
11879 start: 2,
11880 end: 5
11881 }),
11882 None,
11883 AbiTags(vec![
11884 AbiTag(
11885 SourceName(
11886 Identifier {
11887 start: 7,
11888 end: 8,
11889 },
11890 ),
11891 ),
11892 AbiTag(
11893 SourceName(
11894 Identifier {
11895 start: 10,
11896 end: 12,
11897 },
11898 ),
11899 )
11900 ])
11901 ),
11902 "..."
11903 }
11904 }
11905 Err => {
11906 b"zzz" => Error::UnexpectedText,
11907 b"Uq" => Error::UnexpectedText,
11908 b"C" => Error::UnexpectedEnd,
11909 b"" => Error::UnexpectedEnd,
11910 }
11911 });
11912 }
11913
11914 #[test]
11915 fn parse_unnamed_type_name() {
11916 assert_parse!(UnnamedTypeName {
11917 Ok => {
11918 b"Ut_abc" => {
11919 UnnamedTypeName(None),
11920 b"abc"
11921 }
11922 b"Ut42_abc" => {
11923 UnnamedTypeName(Some(42)),
11924 b"abc"
11925 }
11926 b"Ut42_" => {
11927 UnnamedTypeName(Some(42)),
11928 b""
11929 }
11930 }
11931 Err => {
11932 b"ut_" => Error::UnexpectedText,
11933 b"u" => Error::UnexpectedEnd,
11934 b"Ut" => Error::UnexpectedEnd,
11935 b"Ut._" => Error::UnexpectedText,
11936 b"Ut42" => Error::UnexpectedEnd,
11937 }
11938 });
11939 }
11940
11941 #[test]
11942 fn parse_identifier() {
11943 assert_parse!(Identifier {
11944 Ok => {
11945 b"1abc" => {
11946 Identifier { start: 0, end: 4 },
11947 b""
11948 }
11949 b"_Az1\0\0\0" => {
11950 Identifier { start: 0, end: 4 },
11951 b"\0\0\0"
11952 }
11953 b"$_0\0\0\0" => {
11954 Identifier { start: 0, end: 3 },
11955 b"\0\0\0"
11956 }
11957 }
11958 Err => {
11959 b"\0\0\0" => Error::UnexpectedText,
11960 b"" => Error::UnexpectedEnd,
11961 }
11962 });
11963 }
11964
11965 #[test]
11966 fn parse_source_name() {
11967 assert_parse!(SourceName {
11968 Ok => {
11969 b"1abc" => {
11970 SourceName(Identifier { start: 1, end: 2 }),
11971 b"bc"
11972 }
11973 b"10abcdefghijklm" => {
11974 SourceName(Identifier { start: 2, end: 12 }),
11975 b"klm"
11976 }
11977 }
11978 Err => {
11979 b"0abc" => Error::UnexpectedText,
11980 b"n1abc" => Error::UnexpectedText,
11981 b"10abcdef" => Error::UnexpectedEnd,
11982 b"" => Error::UnexpectedEnd,
11983 }
11984 });
11985 }
11986
11987 #[test]
11988 fn parse_number() {
11989 assert_parse!(Number {
11990 Ok => {
11991 b"n2n3" => {
11992 -2,
11993 b"n3"
11994 }
11995 b"12345abcdef" => {
11996 12345,
11997 b"abcdef"
11998 }
11999 b"0abcdef" => {
12000 0,
12001 b"abcdef"
12002 }
12003 b"42" => {
12004 42,
12005 b""
12006 }
12007 }
12008 Err => {
12009 b"001" => Error::UnexpectedText,
12010 b"wutang" => Error::UnexpectedText,
12011 b"n" => Error::UnexpectedEnd,
12012 b"" => Error::UnexpectedEnd,
12013 }
12014 });
12015 }
12016
12017 #[test]
12018 fn parse_call_offset() {
12019 assert_parse!(CallOffset {
12020 Ok => {
12021 b"hn42_..." => {
12022 CallOffset::NonVirtual(NvOffset(-42)),
12023 b"..."
12024 }
12025 b"vn42_36_..." => {
12026 CallOffset::Virtual(VOffset(-42, 36)),
12027 b"..."
12028 }
12029 }
12030 Err => {
12031 b"h1..." => Error::UnexpectedText,
12032 b"v1_1..." => Error::UnexpectedText,
12033 b"hh" => Error::UnexpectedText,
12034 b"vv" => Error::UnexpectedText,
12035 b"z" => Error::UnexpectedText,
12036 b"" => Error::UnexpectedEnd,
12037 }
12038 });
12039 }
12040
12041 #[test]
12042 fn parse_v_offset() {
12043 assert_parse!(VOffset {
12044 Ok => {
12045 b"n2_n3abcdef" => {
12046 VOffset(-2, -3),
12047 b"abcdef"
12048 }
12049 b"12345_12345abcdef" => {
12050 VOffset(12345, 12345),
12051 b"abcdef"
12052 }
12053 b"0_0abcdef" => {
12054 VOffset(0, 0),
12055 b"abcdef"
12056 }
12057 b"42_n3" => {
12058 VOffset(42, -3),
12059 b""
12060 }
12061 }
12062 Err => {
12063 b"001" => Error::UnexpectedText,
12064 b"1_001" => Error::UnexpectedText,
12065 b"wutang" => Error::UnexpectedText,
12066 b"n_" => Error::UnexpectedText,
12067 b"1_n" => Error::UnexpectedEnd,
12068 b"1_" => Error::UnexpectedEnd,
12069 b"n" => Error::UnexpectedEnd,
12070 b"" => Error::UnexpectedEnd,
12071 }
12072 });
12073 }
12074
12075 #[test]
12076 fn parse_nv_offset() {
12077 assert_parse!(NvOffset {
12078 Ok => {
12079 b"n2n3" => {
12080 NvOffset(-2),
12081 b"n3"
12082 }
12083 b"12345abcdef" => {
12084 NvOffset(12345),
12085 b"abcdef"
12086 }
12087 b"0abcdef" => {
12088 NvOffset(0),
12089 b"abcdef"
12090 }
12091 b"42" => {
12092 NvOffset(42),
12093 b""
12094 }
12095 }
12096 Err => {
12097 b"001" => Error::UnexpectedText,
12098 b"wutang" => Error::UnexpectedText,
12099 b"" => Error::UnexpectedEnd,
12100 }
12101 });
12102 }
12103
12104 #[test]
12105 fn parse_seq_id() {
12106 assert_parse!(SeqId {
12107 Ok => {
12108 b"1_" => {
12109 SeqId(1),
12110 b"_"
12111 }
12112 b"42" => {
12113 SeqId(146),
12114 b""
12115 }
12116 b"ABCabc" => {
12117 SeqId(13368),
12118 b"abc"
12119 }
12120 }
12121 Err => {
12122 b"abc" => Error::UnexpectedText,
12123 b"001" => Error::UnexpectedText,
12124 b"wutang" => Error::UnexpectedText,
12125 b"" => Error::UnexpectedEnd,
12126 }
12127 });
12128 }
12129
12130 #[test]
12131 fn parse_ctor_dtor_name() {
12132 assert_parse!(CtorDtorName {
12133 Ok => {
12134 b"D0" => {
12135 CtorDtorName::DeletingDestructor,
12136 b""
12137 }
12138 b"C101" => {
12139 CtorDtorName::CompleteConstructor(None),
12140 b"01"
12141 }
12142 }
12143 Err => {
12144 b"gayagaya" => Error::UnexpectedText,
12145 b"C" => Error::UnexpectedEnd,
12146 b"" => Error::UnexpectedEnd,
12147 }
12148 });
12149 }
12150
12151 #[test]
12152 fn parse_operator_name() {
12153 assert_parse!(OperatorName {
12154 Ok => {
12155 b"qu..." => {
12156 OperatorName::Simple(SimpleOperatorName::Question),
12157 b"..."
12158 }
12159 b"cvi..." => {
12160 OperatorName::Conversion(
12161 TypeHandle::Builtin(
12162 BuiltinType::Standard(
12163 StandardBuiltinType::Int))),
12164 b"..."
12165 }
12166 b"li3Foo..." => {
12167 OperatorName::Literal(SourceName(Identifier {
12168 start: 3,
12169 end: 6,
12170 })),
12171 b"..."
12172 }
12173 b"v33Foo..." => {
12174 OperatorName::VendorExtension(3, SourceName(Identifier {
12175 start: 3,
12176 end: 6
12177 })),
12178 b"..."
12179 }
12180 }
12181 Err => {
12182 b"cv" => Error::UnexpectedEnd,
12183 b"li3ab" => Error::UnexpectedEnd,
12184 b"li" => Error::UnexpectedEnd,
12185 b"v33ab" => Error::UnexpectedEnd,
12186 b"v3" => Error::UnexpectedEnd,
12187 b"v" => Error::UnexpectedEnd,
12188 b"" => Error::UnexpectedEnd,
12189 b"q" => Error::UnexpectedText,
12190 b"c" => Error::UnexpectedText,
12191 b"l" => Error::UnexpectedText,
12192 b"zzz" => Error::UnexpectedText,
12193 }
12194 });
12195 }
12196
12197 #[test]
12198 fn parse_simple_operator_name() {
12199 assert_parse!(SimpleOperatorName {
12200 Ok => {
12201 b"qu" => {
12202 SimpleOperatorName::Question,
12203 b""
12204 }
12205 b"quokka" => {
12206 SimpleOperatorName::Question,
12207 b"okka"
12208 }
12209 }
12210 Err => {
12211 b"bu-buuuu" => Error::UnexpectedText,
12212 b"q" => Error::UnexpectedEnd,
12213 b"" => Error::UnexpectedEnd,
12214 }
12215 });
12216 }
12217
12218 #[test]
12219 fn parse_subobject_expr() {
12220 assert_parse!(SubobjectExpr {
12221 with subs [] => {
12222 Ok => {
12223 "PKcL_Z3FooEE..." => {
12224 SubobjectExpr {
12225 ty: TypeHandle::BackReference(1),
12226 expr: Box::new(Expression::Primary(
12227 ExprPrimary::External(
12228 MangledName::Encoding(
12229 Encoding::Data(
12230 Name::Unscoped(
12231 UnscopedName::Unqualified(
12232 UnqualifiedName::Source(
12233 SourceName(
12234 Identifier {
12235 start: 7,
12236 end: 10,
12237 }
12238 ),
12239 AbiTags::default()
12240 )
12241 )
12242 )
12243 ),
12244 vec![]
12245 )
12246 )
12247 )),
12248 offset: 0,
12249 },
12250 b"...",
12251 [
12252 Substitutable::Type(
12253 Type::Qualified(
12254 CvQualifiers {
12255 restrict: false,
12256 volatile: false,
12257 const_: true,
12258 },
12259 TypeHandle::Builtin(
12260 BuiltinType::Standard(
12261 StandardBuiltinType::Char,
12262 ),
12263 ),
12264 )
12265 ),
12266 Substitutable::Type(
12267 Type::PointerTo(
12268 TypeHandle::BackReference(
12269 0,
12270 ),
12271 ),
12272 )
12273 ]
12274 }
12275 }
12276 Err => {
12277 "" => Error::UnexpectedEnd,
12278 "" => Error::UnexpectedEnd,
12279 }
12280 }
12281 });
12282 }
12283}