1extern crate rustc_demangle;
2
3use std::io::Write;
4use std::os::raw::{c_char, c_int};
5
6#[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}