Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C API wrapper #14

Merged
merged 9 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ sudo: false
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build
- cargo test
- cargo build --all
- cargo test --all
- cargo doc
after_success:
- travis-cargo --only nightly doc-upload
Expand Down
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@ documentation = "http://alexcrichton.com/rustc-demangle"
description = """
Rust compiler symbol demangling.
"""

[workspace]
members = ["rustc-demangle-capi"]

[profile.release]
lto = true
codegen-units = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With lto = true this and incremental = false shouldn't be necessary to specify as well

incremental = false
11 changes: 11 additions & 0 deletions rustc-demangle-capi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "rustc-demangle-capi"
version = "0.1.0"
authors = ["Torste Aikio <zokier@gmail.com>"]

[lib]
name = "rustc_demangle"
crate-type = ["staticlib", "cdylib"]

[dependencies]
rustc-demangle = { version = "*", path = ".." }
18 changes: 18 additions & 0 deletions rustc-demangle-capi/include/rustc_demangle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef RUST_DEMANGLE_H_
#define RUST_DEMANGLE_H_

#ifdef __cplusplus
extern "C" {
#endif

// Demangles symbol given in `mangled` argument into `out` buffer
//
// Returns 0 if `mangled` is not Rust symbol or if `out` buffer is too small
// Returns 1 otherwise
int rustc_demangle(const char *mangled, char *out, size_t out_size);

#ifdef __cplusplus
}
#endif

#endif // RUSTC_DEMANGLE_H_
109 changes: 109 additions & 0 deletions rustc-demangle-capi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
extern crate rustc_demangle;

use std::os::raw::{c_char,c_int};
use std::io::Write;

/// C-style interface for demangling.
/// Demangles symbol given in `mangled` argument into `out` buffer
///
/// Unsafe as it handles buffers by raw pointers.
///
/// Returns 0 if `mangled` is not Rust symbol or if `out` buffer is too small
/// Returns 1 otherwise
#[no_mangle]
pub unsafe extern fn rustc_demangle(mangled: *const c_char, out: *mut c_char, out_size: usize) -> c_int {
let mangled_str = std::ffi::CStr::from_ptr(mangled).to_str();
if mangled_str.is_err() {
return 0;
}
let mangled_str = mangled_str.unwrap();
match rustc_demangle::try_demangle(mangled_str) {
Ok(demangle) => {
let mut out_slice = std::slice::from_raw_parts_mut(out as *mut u8, out_size);
match write!(out_slice, "{:#}\0", demangle) {
Ok(_) => { return 1 },
Err(_) => { return 0 }
}
},
Err(_) => { return 0 }
}
}

#[cfg(test)]
mod tests {
use std::os::raw::c_char;
use std;
#[test]
fn demangle_c_str_large() {
let mangled = "_ZN4testE\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
assert_eq!(res, 1);
let out_str = std::str::from_utf8(&out_buf[..5]).unwrap();
assert_eq!(out_str, "test\0");
}

#[test]
fn demangle_c_str_exact() {
let mangled = "_ZN4testE\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 5) };
assert_eq!(res, 1);
let out_str = std::str::from_utf8(&out_buf).unwrap();
assert_eq!(out_str, "test\0***");
}

#[test]
fn demangle_c_str_small() {
let mangled = "_ZN4testE\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 4) };
assert_eq!(res, 0);
let out_str = std::str::from_utf8(&out_buf[4..]).unwrap();
assert_eq!(out_str, "****");
}

#[test]
fn demangle_c_str_smaller() {
let mangled = "_ZN4testE\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 3) };
assert_eq!(res, 0);
let out_str = std::str::from_utf8(&out_buf[3..]).unwrap();
assert_eq!(out_str, "*****");
}

#[test]
fn demangle_c_str_zero() {
let mangled = "_ZN4testE\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 0) };
assert_eq!(res, 0);
let out_str = std::str::from_utf8(&out_buf).unwrap();
assert_eq!(out_str, "********");
}

#[test]
fn demangle_c_str_not_rust_symbol() {
let mangled = "la la la\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
assert_eq!(res, 0);
}

#[test]
fn demangle_c_str_null() {
let mangled = "\0";
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
assert_eq!(res, 0);
}

#[test]
fn demangle_c_str_invalid_utf8() {
let mangled = [116, 101, 115, 116, 165, 0];
let mut out_buf: Vec<u8> = vec![42;8];
let res = unsafe { super::rustc_demangle(mangled.as_ptr() as *const c_char, out_buf.as_mut_ptr() as *mut c_char, 8) };
assert_eq!(res, 0);
}
}