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 ffi #39

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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 @@ -4,6 +4,6 @@ os:
before_script:
- rustup component add rustfmt-preview
script:
- cargo test --verbose --features serde
- cargo doc --no-deps --features serde
- cargo test --verbose --features serde,cffi
- cargo doc --no-deps --features serde,cffi
- cargo fmt --all -- --check
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@ readme = "README.md"
keywords = ["trie", "patricia", "collection", "generic", "prefix"]
categories = ["data-structures", "text-processing"]


[features]
cffi = ["libc"]


[dependencies]
nibble_vec = "~0.0.3"
"endian-type" = "0.1.2"
serde = { version = "1.0", optional = true }
libc = { version = "0.2", optional = true }

[dev-dependencies]
quickcheck = "0.4"
rand = "0.3"
serde_test = "1.0"

[lib]
crate-type = ["lib", "cdylib"]

[badges]
travis-ci = { repository = "michaelsproul/rust_radix_trie" }
33 changes: 33 additions & 0 deletions src/c_ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use libc::c_char;
use std::ffi::CString;

use super::trie_common::TrieCommon;
use super::Trie;

ffi_fn! {
fn radix_trie_create()-> *mut Trie<CString, usize>{
let trie = Trie::<CString, usize>::new();
return Box::into_raw(Box::new(trie));
}
}

ffi_fn! {
fn radix_trie_free(trie_ptr: *mut Trie<CString, usize>){
unsafe { Box::from_raw(trie_ptr); }
}
}

ffi_fn! {
fn radix_trie_insert(trie_ptr:*mut Trie<CString, usize>, key_ptr:*const c_char, value:usize){
let trie = unsafe { &mut *(trie_ptr) };
let key = unsafe { CString::from_raw(key_ptr as *mut c_char) };
trie.insert(key, value);
}
}

ffi_fn! {
fn radix_trie_len(trie_ptr:*const Trie<CString, usize>)->usize{
let trie = unsafe { &*trie_ptr };
return trie.len();
}
}
14 changes: 13 additions & 1 deletion src/keys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use endian_type::{BigEndian, LittleEndian};
use std::ffi::OsString;
use std::ffi::{CStr, CString, OsString};
use std::path::{Path, PathBuf};
use NibbleVec;

Expand Down Expand Up @@ -100,6 +100,18 @@ impl TrieKey for String {
}
}

impl TrieKey for CStr {
fn encode_bytes(&self) -> Vec<u8> {
return self.to_bytes().to_vec();
}
}

impl TrieKey for CString {
fn encode_bytes(&self) -> Vec<u8> {
return self.to_bytes().to_vec();
}
}

impl TrieKey for str {
fn encode_bytes(&self) -> Vec<u8> {
self.as_bytes().encode_bytes()
Expand Down
13 changes: 11 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! To get started, see the docs for `Trie` below.

// #![deny(warnings)]
// #![warn(missing_docs)]

extern crate endian_type;
Expand All @@ -11,13 +12,21 @@ extern crate quickcheck;
#[cfg(test)]
extern crate rand;

#[macro_use]
mod macros;
Copy link
Owner

Choose a reason for hiding this comment

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

Duplicate, delete

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed


#[cfg(feature = "cffi")]
extern crate libc;
#[cfg(feature = "cffi")]
mod c_ffi;
#[cfg(feature = "cffi")]
pub use c_ffi::*;

pub use keys::TrieKey;
pub use nibble_vec::NibbleVec;
pub use trie_common::TrieCommon;
use trie_node::TrieNode;

#[macro_use]
mod macros;
pub mod iter;
mod keys;
#[cfg(feature = "serde")]
Expand Down
39 changes: 39 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,42 @@ macro_rules! id {
$e
};
}

#[cfg(feature = "cffi")]
// from https://github.com/rust-lang/regex/blob/master/regex-capi/src/macros.rs
macro_rules! ffi_fn {
(fn $name:ident($($arg:ident: $arg_ty:ty),*,) -> $ret:ty $body:block) => {
ffi_fn!(fn $name($($arg: $arg_ty),*) -> $ret $body);
};
(fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block) => {
#[no_mangle]
pub extern fn $name($($arg: $arg_ty),*) -> $ret {
use ::std::io::{self, Write};
use ::std::panic::{self, AssertUnwindSafe};
use ::libc::abort;
match panic::catch_unwind(AssertUnwindSafe(move || $body)) {
Ok(v) => v,
Err(err) => {
let msg = if let Some(&s) = err.downcast_ref::<&str>() {
s.to_owned()
} else if let Some(s) = err.downcast_ref::<String>() {
s.to_owned()
} else {
"UNABLE TO SHOW RESULT OF PANIC.".to_owned()
};
let _ = writeln!(
&mut io::stderr(),
"panic unwind caught, aborting: {:?}",
msg);
unsafe { abort() }
}
}
}
};
(fn $name:ident($($arg:ident: $arg_ty:ty),*,) $body:block) => {
ffi_fn!(fn $name($($arg: $arg_ty),*) -> () $body);
};
(fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block) => {
ffi_fn!(fn $name($($arg: $arg_ty),*) -> () $body);
};
}
22 changes: 22 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ use std::collections::HashSet;
use std::iter::FromIterator;
use {Trie, TrieCommon};

#[cfg(feature = "cffi")]
use c_ffi::*;
#[cfg(feature = "cffi")]
use std::ffi::CString;

const TEST_DATA: [(&'static str, u32); 7] = [
("abcdefgh", 19),
("abcdef", 18),
Expand Down Expand Up @@ -463,3 +468,20 @@ fn test_prefix() {
assert_eq!(second.prefix(), [0x1].as_ref());
assert_eq!(third.prefix(), [0x2].as_ref());
}

#[cfg(feature = "cffi")]
#[test]
fn test_c_ffi_e2e() {
let t = radix_trie_create();
//let key = CString::new("key1").unwrap().as_ptr();
let key1 = CString::new("key1").unwrap().into_raw();
let key2 = CString::new("key2").unwrap().into_raw();

radix_trie_insert(t, key1, 1);
radix_trie_insert(t, key2, 2);

let len = radix_trie_len(t);
assert_eq!(len, 2);

radix_trie_free(t);
}