cpp_demangle/
subs.rs

1//! Types dealing with the substitutions table.
2
3use super::DemangleWrite;
4use crate::ast;
5use alloc::vec::Vec;
6use core::fmt;
7use core::iter::FromIterator;
8use core::ops::Deref;
9
10/// An enumeration of all of the types that can end up in the substitution
11/// table.
12#[doc(hidden)]
13#[derive(Clone, Debug, PartialEq, Eq)]
14#[allow(clippy::large_enum_variant)]
15pub enum Substitutable {
16    /// An `<unscoped-template-name>` production.
17    UnscopedTemplateName(ast::UnscopedTemplateName),
18
19    /// A `<type>` production.
20    Type(ast::Type),
21
22    /// A `<template-template-param>` production.
23    TemplateTemplateParam(ast::TemplateTemplateParam),
24
25    /// An `<unresolved-type>` production.
26    UnresolvedType(ast::UnresolvedType),
27
28    /// A `<prefix>` production.
29    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/// The table of substitutable components that we have parsed thus far, and for
72/// which there are potential back-references.
73#[doc(hidden)]
74#[derive(Clone, Default, PartialEq, Eq)]
75pub struct SubstitutionTable {
76    substitutions: Vec<Substitutable>,
77    // There are components which are typically candidates for substitution, but
78    // in some particular circumstances are not. Instances of such components
79    // which are not candidates for substitution end up in this part of the
80    // table. See `<prefix>` parsing for further details.
81    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    /// Construct a new `SubstitutionTable`.
99    pub fn new() -> SubstitutionTable {
100        Default::default()
101    }
102
103    /// Insert a freshly-parsed substitutable component into the table and
104    /// return the index at which it now lives.
105    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    /// Insert a an entity into the table that is not a candidate for
113    /// substitution.
114    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    /// Does this substitution table contain a component at the given index?
121    pub fn contains(&self, idx: usize) -> bool {
122        idx < self.substitutions.len()
123    }
124
125    /// Get the type referenced by the given handle, or None if there is no such
126    /// entry, or there is an entry that is not a type.
127    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    /// Remove the last entry from the substitutions table and return it, or
139    /// `None` if the table is empty.
140    pub fn pop(&mut self) -> Option<Substitutable> {
141        log!("SubstitutionTable::pop @ {}: {:?}", self.len(), self.last());
142        self.substitutions.pop()
143    }
144
145    /// Get the `idx`th entity that is not a candidate for substitution. Panics
146    /// if `idx` is out of bounds.
147    pub fn non_substitution(&self, idx: usize) -> &Substitutable {
148        &self.non_substitutions[idx]
149    }
150
151    /// Get the `idx`th entity that is not a candidate for substitution. Returns
152    /// `None` if `idx` is out of bounds.
153    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}