1use super::DemangleWrite;
4use ast;
5use std::fmt;
6use std::iter::FromIterator;
7use std::ops::Deref;
8use vec::Vec;
9
10#[doc(hidden)]
13#[derive(Clone, Debug, PartialEq, Eq)]
14#[allow(clippy::large_enum_variant)]
15pub enum Substitutable {
16 UnscopedTemplateName(ast::UnscopedTemplateName),
18
19 Type(ast::Type),
21
22 TemplateTemplateParam(ast::TemplateTemplateParam),
24
25 UnresolvedType(ast::UnresolvedType),
27
28 Prefix(ast::Prefix),
30}
31
32impl<'subs, W> ast::Demangle<'subs, W> for Substitutable
33where
34 W: 'subs + DemangleWrite,
35{
36 fn demangle<'prev, 'ctx>(
37 &'subs self,
38 ctx: &'ctx mut ast::DemangleContext<'subs, W>,
39 scope: Option<ast::ArgScopeStack<'prev, 'subs>>,
40 ) -> fmt::Result {
41 match *self {
42 Substitutable::UnscopedTemplateName(ref name) => name.demangle(ctx, scope),
43 Substitutable::Type(ref ty) => ty.demangle(ctx, scope),
44 Substitutable::TemplateTemplateParam(ref ttp) => ttp.demangle(ctx, scope),
45 Substitutable::UnresolvedType(ref ty) => ty.demangle(ctx, scope),
46 Substitutable::Prefix(ref prefix) => prefix.demangle(ctx, scope),
47 }
48 }
49}
50
51impl<'a> ast::GetLeafName<'a> for Substitutable {
52 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<ast::LeafName<'a>> {
53 match *self {
54 Substitutable::UnscopedTemplateName(ref name) => name.get_leaf_name(subs),
55 Substitutable::Prefix(ref prefix) => prefix.get_leaf_name(subs),
56 Substitutable::Type(ref ty) => ty.get_leaf_name(subs),
57 _ => None,
58 }
59 }
60}
61
62impl ast::IsCtorDtorConversion for Substitutable {
63 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool {
64 match *self {
65 Substitutable::Prefix(ref prefix) => prefix.is_ctor_dtor_conversion(subs),
66 _ => false,
67 }
68 }
69}
70
71#[doc(hidden)]
74#[derive(Clone, Default, PartialEq, Eq)]
75pub struct SubstitutionTable {
76 substitutions: Vec<Substitutable>,
77 non_substitutions: Vec<Substitutable>,
82}
83
84impl fmt::Debug for SubstitutionTable {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 f.pad("SubstitutionTable ")?;
87 f.debug_map()
88 .entries(self.substitutions.iter().enumerate())
89 .finish()?;
90 f.pad("non_substitutions ")?;
91 f.debug_map()
92 .entries(self.non_substitutions.iter().enumerate())
93 .finish()
94 }
95}
96
97impl SubstitutionTable {
98 pub fn new() -> SubstitutionTable {
100 Default::default()
101 }
102
103 pub fn insert(&mut self, entity: Substitutable) -> usize {
106 let idx = self.substitutions.len();
107 log!("SubstitutionTable::insert @ {}: {:?}", idx, entity);
108 self.substitutions.push(entity);
109 idx
110 }
111
112 pub fn insert_non_substitution(&mut self, entity: Substitutable) -> usize {
115 let idx = self.non_substitutions.len();
116 self.non_substitutions.push(entity);
117 idx
118 }
119
120 pub fn contains(&self, idx: usize) -> bool {
122 idx < self.substitutions.len()
123 }
124
125 pub fn get_type(&self, handle: &ast::TypeHandle) -> Option<&ast::Type> {
128 if let ast::TypeHandle::BackReference(idx) = *handle {
129 self.substitutions.get(idx).and_then(|s| match *s {
130 Substitutable::Type(ref ty) => Some(ty),
131 _ => None,
132 })
133 } else {
134 None
135 }
136 }
137
138 pub fn pop(&mut self) -> Option<Substitutable> {
141 log!("SubstitutionTable::pop @ {}: {:?}", self.len(), self.last());
142 self.substitutions.pop()
143 }
144
145 pub fn non_substitution(&self, idx: usize) -> &Substitutable {
148 &self.non_substitutions[idx]
149 }
150
151 pub fn get_non_substitution(&self, idx: usize) -> Option<&Substitutable> {
154 self.non_substitutions.get(idx)
155 }
156}
157
158impl FromIterator<Substitutable> for SubstitutionTable {
159 fn from_iter<I: IntoIterator<Item = Substitutable>>(iter: I) -> Self {
160 SubstitutionTable {
161 substitutions: Vec::from_iter(iter),
162 non_substitutions: vec![],
163 }
164 }
165}
166
167impl Deref for SubstitutionTable {
168 type Target = [Substitutable];
169
170 fn deref(&self) -> &Self::Target {
171 &self.substitutions[..]
172 }
173}