Skip to content

Commit e8ae32f

Browse files
committed
std based C API
1 parent e7da369 commit e8ae32f

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ documentation = "http://alexcrichton.com/rustc-demangle"
1010
description = """
1111
Rust compiler symbol demangling.
1212
"""
13+
14+
[workspace]
15+
members = ["rustc-demangle-capi"]
16+

rustc-demangle-capi/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "rustc-demangle-capi"
3+
version = "0.1.0"
4+
authors = ["Torste Aikio <[email protected]>"]
5+
6+
[lib]
7+
name = "rustc_demangle"
8+
crate-type = ["staticlib", "cdylib"]
9+
10+
[dependencies]
11+
rustc-demangle = { version = "*", path = ".." }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef RUST_DEMANGLE_H_
2+
#define RUST_DEMANGLE_H_
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
// Demangles symbol given in `mangled` argument into `out` buffer
9+
//
10+
// Returns 0 if `mangled` is not Rust symbol or if `out` buffer is too small
11+
// Returns 1 otherwise
12+
int rustc_demangle(const char *mangled, char *out, size_t out_size);
13+
14+
#ifdef __cplusplus
15+
}
16+
#endif
17+
18+
#endif // RUSTC_DEMANGLE_H_

rustc-demangle-capi/src/lib.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
extern crate rustc_demangle;
2+
3+
use std::os::raw::{c_char,c_int};
4+
use std::io::Write;
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]
14+
pub unsafe extern fn rustc_demangle(mangled: *const c_char, out: *mut c_char, out_size: usize) -> c_int {
15+
let mangled_str = std::ffi::CStr::from_ptr(mangled).to_str();
16+
if mangled_str.is_err() {
17+
return 0;
18+
}
19+
let mangled_str = mangled_str.unwrap();
20+
match rustc_demangle::try_demangle(mangled_str) {
21+
Ok(demangle) => {
22+
let mut out_slice = std::slice::from_raw_parts_mut(out as *mut u8, out_size);
23+
match write!(out_slice, "{:#}\0", demangle) {
24+
Ok(_) => { return 1 },
25+
Err(_) => { return 0 }
26+
}
27+
},
28+
Err(_) => { return 0 }
29+
}
30+
}
31+
32+
#[cfg(test)]
33+
mod tests {
34+
use std::os::raw::c_char;
35+
use std;
36+
#[test]
37+
fn demangle_c_str_large() {
38+
let mangled = "_ZN4testE\0";
39+
let mut out_buf: Vec<u8> = vec![42;8];
40+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
41+
assert_eq!(res, 1);
42+
let out_str = std::str::from_utf8(&out_buf[..5]).unwrap();
43+
assert_eq!(out_str, "test\0");
44+
}
45+
46+
#[test]
47+
fn demangle_c_str_exact() {
48+
let mangled = "_ZN4testE\0";
49+
let mut out_buf: Vec<u8> = vec![42;8];
50+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 5) };
51+
assert_eq!(res, 1);
52+
let out_str = std::str::from_utf8(&out_buf).unwrap();
53+
assert_eq!(out_str, "test\0***");
54+
}
55+
56+
#[test]
57+
fn demangle_c_str_small() {
58+
let mangled = "_ZN4testE\0";
59+
let mut out_buf: Vec<u8> = vec![42;8];
60+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 4) };
61+
assert_eq!(res, 0);
62+
let out_str = std::str::from_utf8(&out_buf[4..]).unwrap();
63+
assert_eq!(out_str, "****");
64+
}
65+
66+
#[test]
67+
fn demangle_c_str_smaller() {
68+
let mangled = "_ZN4testE\0";
69+
let mut out_buf: Vec<u8> = vec![42;8];
70+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 3) };
71+
assert_eq!(res, 0);
72+
let out_str = std::str::from_utf8(&out_buf[3..]).unwrap();
73+
assert_eq!(out_str, "*****");
74+
}
75+
76+
#[test]
77+
fn demangle_c_str_zero() {
78+
let mangled = "_ZN4testE\0";
79+
let mut out_buf: Vec<u8> = vec![42;8];
80+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 0) };
81+
assert_eq!(res, 0);
82+
let out_str = std::str::from_utf8(&out_buf).unwrap();
83+
assert_eq!(out_str, "********");
84+
}
85+
86+
#[test]
87+
fn demangle_c_str_not_rust_symbol() {
88+
let mangled = "la la la\0";
89+
let mut out_buf: Vec<u8> = vec![42;8];
90+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
91+
assert_eq!(res, 0);
92+
}
93+
94+
#[test]
95+
fn demangle_c_str_null() {
96+
let mangled = "\0";
97+
let mut out_buf: Vec<u8> = vec![42;8];
98+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
99+
assert_eq!(res, 0);
100+
}
101+
102+
#[test]
103+
fn demangle_c_str_invalid_utf8() {
104+
let mangled = [116, 101, 115, 116, 165, 0];
105+
let mut out_buf: Vec<u8> = vec![42;8];
106+
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
107+
assert_eq!(res, 0);
108+
}
109+
}

0 commit comments

Comments
 (0)