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