#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unsafe_code)]
#![allow(unknown_lints)]
#![allow(inline_always)]
#[macro_use]
mod logging;
pub mod ast;
pub mod error;
mod index_str;
mod subs;
use ast::{Demangle, Parse, ParseContext};
use error::{Error, Result};
use index_str::IndexStr;
use std::fmt;
use std::io;
#[derive(Clone, Copy, Debug, Default)]
pub struct DemangleOptions {
pub no_params: bool,
}
pub type OwnedSymbol = Symbol<Vec<u8>>;
pub type BorrowedSymbol<'a> = Symbol<&'a [u8]>;
#[derive(Clone, Debug, PartialEq)]
pub struct Symbol<T> {
raw: T,
substitutions: subs::SubstitutionTable,
parsed: ast::MangledName,
}
impl<T> Symbol<T>
where T: AsRef<[u8]>
{
pub fn new(raw: T) -> Result<Symbol<T>> {
let mut substitutions = subs::SubstitutionTable::new();
let parsed = {
let ctx = ParseContext::default();
let input = IndexStr::new(raw.as_ref());
let (parsed, tail) = try!(ast::MangledName::parse(&ctx, &mut substitutions, input));
debug_assert!(ctx.recursion_level() == 0);
if tail.is_empty() {
parsed
} else {
return Err(Error::UnexpectedText.into());
}
};
let symbol = Symbol {
raw: raw,
substitutions: substitutions,
parsed: parsed,
};
if cfg!(feature = "logging") {
println!("Successfully parsed '{}' as
AST = {:#?}
substitutions = {:#?}",
String::from_utf8_lossy(symbol.raw.as_ref()),
symbol.parsed,
symbol.substitutions);
}
Ok(symbol)
}
pub fn demangle(&self, options: &DemangleOptions) -> io::Result<String> {
let mut out = vec![];
{
let mut ctx = ast::DemangleContext::new(&self.substitutions,
self.raw.as_ref(),
options,
&mut out);
try!(self.parsed.demangle(&mut ctx, None));
}
Ok(String::from_utf8(out).unwrap())
}
}
impl<T> Symbol<T> {
pub fn with_tail(input: &[u8]) -> Result<(BorrowedSymbol, &[u8])> {
let mut substitutions = subs::SubstitutionTable::new();
let ctx = ParseContext::default();
let idx_str = IndexStr::new(input);
let (parsed, tail) = try!(ast::MangledName::parse(&ctx, &mut substitutions, idx_str));
debug_assert!(ctx.recursion_level() == 0);
let symbol = Symbol {
raw: input,
substitutions: substitutions,
parsed: parsed,
};
if cfg!(feature = "logging") {
println!("Successfully parsed '{}' as
AST = {:#?}
substitutions = {:#?}",
String::from_utf8_lossy(symbol.raw.as_ref()),
symbol.parsed,
symbol.substitutions);
}
Ok((symbol, tail.into()))
}
}
impl<T> fmt::Display for Symbol<T>
where T: AsRef<[u8]>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut out = vec![];
{
let options = DemangleOptions::default();
let mut ctx = ast::DemangleContext::new(&self.substitutions,
self.raw.as_ref(),
&options,
&mut out);
try!(self.parsed.demangle(&mut ctx, None).map_err(|_| fmt::Error));
}
write!(f, "{}", String::from_utf8_lossy(&out))
}
}