Skip to main content

objdiff_core/diff/
demangler.rs

1use alloc::string::String;
2
3use crate::diff::Demangler;
4
5#[cfg(feature = "demangler")]
6impl Demangler {
7    pub fn demangle(&self, name: &str) -> Option<String> {
8        match self {
9            Demangler::None => None,
10            Demangler::Codewarrior => Self::demangle_codewarrior(name),
11            Demangler::Msvc => Self::demangle_msvc(name),
12            Demangler::Itanium => Self::demangle_itanium(name),
13            Demangler::GnuLegacy => Self::demangle_gnu_legacy(name),
14            Demangler::Auto => {
15                // Try to guess
16                if name.starts_with('?') {
17                    Self::demangle_msvc(name)
18                } else {
19                    Self::demangle_codewarrior(name)
20                        .or_else(|| Self::demangle_gnu_legacy(name))
21                        .or_else(|| Self::demangle_itanium(name))
22                }
23            }
24        }
25    }
26
27    fn demangle_codewarrior(name: &str) -> Option<String> {
28        cwdemangle::demangle(name, &cwdemangle::DemangleOptions::default())
29    }
30
31    fn demangle_msvc(name: &str) -> Option<String> {
32        msvc_demangler::demangle(name, msvc_demangler::DemangleFlags::llvm()).ok()
33    }
34
35    fn demangle_itanium(name: &str) -> Option<String> {
36        let name = name.trim_start_matches('.');
37        cpp_demangle::Symbol::new(name).ok().and_then(|s| s.demangle().ok())
38    }
39
40    fn demangle_gnu_legacy(name: &str) -> Option<String> {
41        let name = name.trim_start_matches('.');
42        gnuv2_demangle::demangle(name, &gnuv2_demangle::DemangleConfig::new()).ok()
43    }
44}
45
46#[cfg(not(feature = "demangler"))]
47impl Demangler {
48    pub fn demangle(&self, _name: &str) -> Option<String> { None }
49}