use log::warn;
use symbolic::common::{Language, Name};
use symbolic::demangle::Demangle;
use std::collections::HashMap;
use crate::common;
#[derive(Debug, Default)]
pub struct InlineOrigins<'a> {
demangled_names: Vec<String>,
index_for_mangled_name: HashMap<Name<'a>, u32>,
}
impl<'a> InlineOrigins<'a> {
pub fn get_id(&mut self, name: &Name<'a>) -> u32 {
if let Some(index) = self.index_for_mangled_name.get(name) {
return *index;
}
let s = Self::demangle_and_sanitize(name);
let index = self.demangled_names.len() as u32;
self.demangled_names.push(s);
self.index_for_mangled_name.insert(name.clone(), index);
index
}
pub fn get_list(self) -> Vec<String> {
self.demangled_names
}
fn demangle_and_sanitize(name: &Name) -> String {
let mut name = Self::demangle(name);
name.retain(|c| !c.is_ascii_control());
name
}
fn demangle(name: &Name) -> String {
let name = common::fix_symbol_name(name);
if let Language::C = name.language() {
return name.as_str().to_string();
}
match name.demangle(common::demangle_options()) {
Some(demangled) => demangled,
None => {
let aname = name.as_str();
warn!("Didn't manage to demangle {:?}", name);
aname.to_string()
}
}
}
}
pub fn merge_inline_origins(left: &mut Vec<String>, right: Vec<String>) -> Vec<u32> {
if right.is_empty() {
return Vec::new();
}
if left.is_empty() {
let count = right.len() as u32;
*left = right;
return (0..count).collect();
}
let count = right.len() as u32;
let offset = left.len() as u32;
left.extend(right.into_iter());
(offset..(offset + count)).collect()
}
#[cfg(test)]
mod test {
use symbolic::common::{Language, Name, NameMangling};
use super::InlineOrigins;
#[test]
fn test_demangle() {
let mut inline_origins = InlineOrigins::default();
let _ = inline_origins.get_id(&Name::new(
"_ZL15draw_depth_spanIjEvjPT_R11DepthCursor",
NameMangling::Mangled,
Language::Cpp,
));
assert_eq!(
inline_origins.get_list(),
vec![
"draw_depth_span<unsigned int>(unsigned int, unsigned int*, DepthCursor&)"
.to_string()
]
);
}
#[test]
fn test_bad_chars() {
let mut inline_origins = InlineOrigins::default();
let _ = inline_origins.get_id(&Name::new(
"\n\u{fffd}\u{fffd}P\u{fffd}",
NameMangling::Mangled,
Language::Cpp,
));
assert_eq!(
inline_origins.get_list(),
vec!["\u{fffd}\u{fffd}P\u{fffd}".to_string()]
);
}
}