rustc_demangle/
lib.rs

1extern crate rustc_demangle;
2
3use std::io::Write;
4use std::os::raw::{c_char, c_int};
5
6/// C-style interface for demangling.
7/// Demangles symbol given in `mangled` argument into `out` buffer
8///
9/// Unsafe as it handles buffers by raw pointers.
10///
11/// Returns 0 if `mangled` is not Rust symbol or if `out` buffer is too small
12/// Returns 1 otherwise
13#[no_mangle]
14pub unsafe extern "C" fn rustc_demangle(
15    mangled: *const c_char,
16    out: *mut c_char,
17    out_size: usize,
18) -> c_int {
19    let mangled_str = match std::ffi::CStr::from_ptr(mangled).to_str() {
20        Ok(s) => s,
21        Err(_) => return 0,
22    };
23    match rustc_demangle::try_demangle(mangled_str) {
24        Ok(demangle) => {
25            let mut out_slice = std::slice::from_raw_parts_mut(out as *mut u8, out_size);
26            match write!(out_slice, "{:#}\0", demangle) {
27                Ok(_) => return 1,
28                Err(_) => return 0,
29            }
30        }
31        Err(_) => return 0,
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use std;
38    use std::os::raw::c_char;
39    #[test]
40    fn demangle_c_str_large() {
41        let mangled = "_ZN4testE\0";
42        let mut out_buf: Vec<u8> = vec![42; 8];
43        let res = unsafe {
44            super::rustc_demangle(
45                mangled.as_ptr() as *const c_char,
46                out_buf.as_mut_ptr() as *mut c_char,
47                8,
48            )
49        };
50        assert_eq!(res, 1);
51        let out_str = std::str::from_utf8(&out_buf[..5]).unwrap();
52        assert_eq!(out_str, "test\0");
53    }
54
55    #[test]
56    fn demangle_c_str_exact() {
57        let mangled = "_ZN4testE\0";
58        let mut out_buf: Vec<u8> = vec![42; 8];
59        let res = unsafe {
60            super::rustc_demangle(
61                mangled.as_ptr() as *const c_char,
62                out_buf.as_mut_ptr() as *mut c_char,
63                5,
64            )
65        };
66        assert_eq!(res, 1);
67        let out_str = std::str::from_utf8(&out_buf).unwrap();
68        assert_eq!(out_str, "test\0***");
69    }
70
71    #[test]
72    fn demangle_c_str_small() {
73        let mangled = "_ZN4testE\0";
74        let mut out_buf: Vec<u8> = vec![42; 8];
75        let res = unsafe {
76            super::rustc_demangle(
77                mangled.as_ptr() as *const c_char,
78                out_buf.as_mut_ptr() as *mut c_char,
79                4,
80            )
81        };
82        assert_eq!(res, 0);
83        let out_str = std::str::from_utf8(&out_buf[4..]).unwrap();
84        assert_eq!(out_str, "****");
85    }
86
87    #[test]
88    fn demangle_c_str_smaller() {
89        let mangled = "_ZN4testE\0";
90        let mut out_buf: Vec<u8> = vec![42; 8];
91        let res = unsafe {
92            super::rustc_demangle(
93                mangled.as_ptr() as *const c_char,
94                out_buf.as_mut_ptr() as *mut c_char,
95                3,
96            )
97        };
98        assert_eq!(res, 0);
99        let out_str = std::str::from_utf8(&out_buf[3..]).unwrap();
100        assert_eq!(out_str, "*****");
101    }
102
103    #[test]
104    fn demangle_c_str_zero() {
105        let mangled = "_ZN4testE\0";
106        let mut out_buf: Vec<u8> = vec![42; 8];
107        let res = unsafe {
108            super::rustc_demangle(
109                mangled.as_ptr() as *const c_char,
110                out_buf.as_mut_ptr() as *mut c_char,
111                0,
112            )
113        };
114        assert_eq!(res, 0);
115        let out_str = std::str::from_utf8(&out_buf).unwrap();
116        assert_eq!(out_str, "********");
117    }
118
119    #[test]
120    fn demangle_c_str_not_rust_symbol() {
121        let mangled = "la la la\0";
122        let mut out_buf: Vec<u8> = vec![42; 8];
123        let res = unsafe {
124            super::rustc_demangle(
125                mangled.as_ptr() as *const c_char,
126                out_buf.as_mut_ptr() as *mut c_char,
127                8,
128            )
129        };
130        assert_eq!(res, 0);
131    }
132
133    #[test]
134    fn demangle_c_str_null() {
135        let mangled = "\0";
136        let mut out_buf: Vec<u8> = vec![42; 8];
137        let res = unsafe {
138            super::rustc_demangle(
139                mangled.as_ptr() as *const c_char,
140                out_buf.as_mut_ptr() as *mut c_char,
141                8,
142            )
143        };
144        assert_eq!(res, 0);
145    }
146
147    #[test]
148    fn demangle_c_str_invalid_utf8() {
149        let mangled = [116, 101, 115, 116, 165, 0];
150        let mut out_buf: Vec<u8> = vec![42; 8];
151        let res = unsafe {
152            super::rustc_demangle(
153                mangled.as_ptr() as *const c_char,
154                out_buf.as_mut_ptr() as *mut c_char,
155                8,
156            )
157        };
158        assert_eq!(res, 0);
159    }
160}