ast_demangle/rust_v0/
mod.rs

1//! Tools for demangling symbols using
2//! [Rust v0 syntax](https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html#syntax-of-mangled-names).
3
4pub use self::display::Style as DisplayStyle;
5use std::borrow::Cow;
6use std::fmt::{self, Debug, Display, Formatter, Write};
7use std::rc::Rc;
8
9mod display;
10mod parsers;
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct ParseSymbolError;
14
15#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub struct Symbol<'a> {
17    pub version: Option<u64>,
18    pub path: Rc<Path<'a>>,
19    pub instantiating_crate: Option<Rc<Path<'a>>>,
20    pub vendor_specific_suffix: Option<&'a str>,
21}
22
23impl<'a> Symbol<'a> {
24    /// Returns an object that implements [`Display`] for printing the symbol.
25    #[must_use]
26    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
27        display::display_path(&self.path, style, 0, true)
28    }
29
30    /// Parses `input` with Rust
31    /// [v0 syntax](https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html#syntax-of-mangled-names),
32    /// returns a tuple that contains a [`Symbol`] object and an [`&str`] object containing the suffix that is
33    /// not part of the the Rust v0 syntax.
34    ///
35    /// # Errors
36    ///
37    /// Returns [`ParseSymbolError`] if `input` does not start with a valid prefix with Rust v0 syntax.
38    pub fn parse_from_str(input: &'a str) -> Result<(Self, &'a str), ParseSymbolError> {
39        let input = input
40            .strip_prefix("_R")
41            .or_else(|| input.strip_prefix('R'))
42            .or_else(|| input.strip_prefix("__R"))
43            .ok_or(ParseSymbolError)?;
44
45        parsers::parse_symbol(input).map_err(|()| ParseSymbolError)
46    }
47}
48
49impl Display for Symbol<'_> {
50    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
51        self.display(if f.alternate() {
52            DisplayStyle::Normal
53        } else {
54            DisplayStyle::Long
55        })
56        .fmt(f)
57    }
58}
59
60#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
61pub enum Path<'a> {
62    CrateRoot(Identifier<'a>),
63    InherentImpl {
64        impl_path: ImplPath<'a>,
65        type_: Rc<Type<'a>>,
66    },
67    TraitImpl {
68        impl_path: ImplPath<'a>,
69        type_: Rc<Type<'a>>,
70        trait_: Rc<Path<'a>>,
71    },
72    TraitDefinition {
73        type_: Rc<Type<'a>>,
74        trait_: Rc<Path<'a>>,
75    },
76    Nested {
77        namespace: u8,
78        path: Rc<Path<'a>>,
79        identifier: Identifier<'a>,
80    },
81    Generic {
82        path: Rc<Path<'a>>,
83        generic_args: Vec<GenericArg<'a>>,
84    },
85}
86
87impl Debug for Path<'_> {
88    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
89        struct DebugNamespace(u8);
90
91        impl Debug for DebugNamespace {
92            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
93                f.write_char('b')?;
94                Debug::fmt(&char::from(self.0), f)
95            }
96        }
97
98        match self {
99            Self::CrateRoot(identifier) => f.debug_tuple("CrateRoot").field(identifier).finish(),
100            Self::InherentImpl { impl_path, type_ } => f
101                .debug_struct("InherentImpl")
102                .field("impl_path", impl_path)
103                .field("type_", type_.as_ref())
104                .finish(),
105            Self::TraitImpl {
106                impl_path,
107                type_,
108                trait_,
109            } => f
110                .debug_struct("TraitImpl")
111                .field("impl_path", impl_path)
112                .field("type_", type_.as_ref())
113                .field("trait_", trait_.as_ref())
114                .finish(),
115            Self::TraitDefinition { type_, trait_ } => f
116                .debug_struct("TraitDefinition")
117                .field("type_", type_.as_ref())
118                .field("trait_", trait_.as_ref())
119                .finish(),
120            Self::Nested {
121                namespace,
122                path,
123                identifier,
124            } => f
125                .debug_struct("Nested")
126                .field("namespace", &DebugNamespace(*namespace))
127                .field("path", path.as_ref())
128                .field("identifier", identifier)
129                .finish(),
130            Self::Generic { path, generic_args } => f
131                .debug_struct("Generic")
132                .field("path", path.as_ref())
133                .field("generic_args", &generic_args.as_slice())
134                .finish(),
135        }
136    }
137}
138
139impl Path<'_> {
140    /// Returns an object that implements [`Display`] for printing the path.
141    #[must_use]
142    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
143        display::display_path(self, style, 0, false)
144    }
145}
146
147impl Display for Path<'_> {
148    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
149        self.display(if f.alternate() {
150            DisplayStyle::Normal
151        } else {
152            DisplayStyle::Long
153        })
154        .fmt(f)
155    }
156}
157
158#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
159pub struct ImplPath<'a> {
160    pub disambiguator: u64,
161    pub path: Rc<Path<'a>>,
162}
163
164#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
165pub struct Identifier<'a> {
166    pub disambiguator: u64,
167    pub name: Cow<'a, str>,
168}
169
170impl Identifier<'_> {
171    /// Returns an object that implements [`Display`] for printing the identifier.
172    #[must_use]
173    pub fn display(&self) -> impl Display + '_ {
174        self.name.as_ref()
175    }
176}
177
178impl Display for Identifier<'_> {
179    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
180        self.display().fmt(f)
181    }
182}
183
184#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
185pub enum GenericArg<'a> {
186    Lifetime(u64),
187    Type(Rc<Type<'a>>),
188    Const(Rc<Const<'a>>),
189}
190
191impl GenericArg<'_> {
192    /// Returns an object that implements [`Display`] for printing the generic argument.
193    #[must_use]
194    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
195        display::display_generic_arg(self, style, 0)
196    }
197}
198
199impl Display for GenericArg<'_> {
200    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
201        self.display(if f.alternate() {
202            DisplayStyle::Normal
203        } else {
204            DisplayStyle::Long
205        })
206        .fmt(f)
207    }
208}
209
210#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
211pub enum Type<'a> {
212    Basic(BasicType),
213    Named(Rc<Path<'a>>),
214    Array(Rc<Type<'a>>, Rc<Const<'a>>),
215    Slice(Rc<Type<'a>>),
216    Tuple(Vec<Rc<Type<'a>>>),
217    Ref { lifetime: u64, type_: Rc<Type<'a>> },
218    RefMut { lifetime: u64, type_: Rc<Type<'a>> },
219    PtrConst(Rc<Type<'a>>),
220    PtrMut(Rc<Type<'a>>),
221    Fn(FnSig<'a>),
222    DynTrait { dyn_bounds: DynBounds<'a>, lifetime: u64 },
223}
224
225impl Type<'_> {
226    /// Returns an object that implements [`Display`] for printing the type.
227    #[must_use]
228    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
229        display::display_type(self, style, 0)
230    }
231}
232
233impl Display for Type<'_> {
234    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
235        self.display(if f.alternate() {
236            DisplayStyle::Normal
237        } else {
238            DisplayStyle::Long
239        })
240        .fmt(f)
241    }
242}
243
244#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
245pub enum BasicType {
246    I8,
247    Bool,
248    Char,
249    F64,
250    Str,
251    F32,
252    U8,
253    Isize,
254    Usize,
255    I32,
256    U32,
257    I128,
258    U128,
259    I16,
260    U16,
261    Unit,
262    Ellipsis,
263    I64,
264    U64,
265    Never,
266    Placeholder,
267}
268
269impl BasicType {
270    /// Returns an object that implements [`Display`] for printing the basic type.
271    #[must_use]
272    pub fn display(self) -> impl Display {
273        display::display_basic_type(self)
274    }
275}
276
277impl Display for BasicType {
278    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
279        self.display().fmt(f)
280    }
281}
282
283#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
284pub struct FnSig<'a> {
285    pub bound_lifetimes: u64,
286    pub is_unsafe: bool,
287    pub abi: Option<Abi<'a>>,
288    pub argument_types: Vec<Rc<Type<'a>>>,
289    pub return_type: Rc<Type<'a>>,
290}
291
292impl FnSig<'_> {
293    /// Returns an object that implements [`Display`] for printing the function signature.
294    #[must_use]
295    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
296        display::display_fn_sig(self, style, 0)
297    }
298}
299
300impl Display for FnSig<'_> {
301    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
302        self.display(if f.alternate() {
303            DisplayStyle::Normal
304        } else {
305            DisplayStyle::Long
306        })
307        .fmt(f)
308    }
309}
310
311#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
312pub enum Abi<'a> {
313    C,
314    Named(Cow<'a, str>),
315}
316
317#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
318pub struct DynBounds<'a> {
319    pub bound_lifetimes: u64,
320    pub dyn_traits: Vec<DynTrait<'a>>,
321}
322
323#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
324pub struct DynTrait<'a> {
325    pub path: Rc<Path<'a>>,
326    pub dyn_trait_assoc_bindings: Vec<DynTraitAssocBinding<'a>>,
327}
328
329#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
330pub struct DynTraitAssocBinding<'a> {
331    pub name: Cow<'a, str>,
332    pub type_: Rc<Type<'a>>,
333}
334
335#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
336pub enum Const<'a> {
337    I8(i8),
338    U8(u8),
339    Isize(isize),
340    Usize(usize),
341    I32(i32),
342    U32(u32),
343    I128(i128),
344    U128(u128),
345    I16(i16),
346    U16(u16),
347    I64(i64),
348    U64(u64),
349    Bool(bool),
350    Char(char),
351    Str(String),
352    Ref(Rc<Const<'a>>),
353    RefMut(Rc<Const<'a>>),
354    Array(Vec<Rc<Const<'a>>>),
355    Tuple(Vec<Rc<Const<'a>>>),
356    NamedStruct {
357        path: Rc<Path<'a>>,
358        fields: ConstFields<'a>,
359    },
360    Placeholder,
361}
362
363#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
364pub enum ConstFields<'a> {
365    Unit,
366    Tuple(Vec<Rc<Const<'a>>>),
367    Struct(Vec<(Identifier<'a>, Rc<Const<'a>>)>),
368}
369
370impl Const<'_> {
371    /// Returns an object that implements [`Display`] for printing the constant value.
372    #[must_use]
373    pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
374        display::display_const(self, style, 0, true)
375    }
376}
377
378impl Display for Const<'_> {
379    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
380        self.display(if f.alternate() {
381            DisplayStyle::Normal
382        } else {
383            DisplayStyle::Long
384        })
385        .fmt(f)
386    }
387}