cabocha 0.2.0

Safe Rust wrapper for cabocha a japanese language dependency structure analyzer library
Documentation
use std::ffi::{CStr, CString};
use std::os::raw::*;
use std::{slice, str};

pub fn ptr_to_string(ptr: *const c_char) -> String {
  let strs = if ptr.is_null() {
    ""
  } else {
    let cstr = unsafe { CStr::from_ptr(ptr) };
    if let Ok(s) = str::from_utf8(cstr.to_bytes()) {
      s
    } else {
      ""
    }
  };
  strs.to_string()
}

pub fn ptr_to_vec_string(ptr: *const *const c_char, size: usize) -> Vec<String> {
  let slice = unsafe { slice::from_raw_parts(ptr, size) };
  slice
    .iter()
    .map(|raw_str| ptr_to_string(*raw_str))
    .collect()
}

pub fn str_to_heap_ptr<T: Into<Vec<u8>>>(input: T) -> *mut c_char {
  CString::new(input).unwrap().into_raw()
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_ptr_to_vec_string() {
    let vec_string = vec![String::from("string1"), String::from("string2")];
    let vec_cstring = vec_string
      .iter()
      .map(|arg| CString::new(arg.as_str()).unwrap())
      .collect::<Vec<CString>>();
    let mut vec_ptr = vec_cstring
      .iter()
      .map(|arg| arg.as_ptr())
      .collect::<Vec<*const c_char>>();
    vec_ptr.push(std::ptr::null());
    let ptr: *const *const c_char = vec_ptr.as_ptr();
    let result = ptr_to_vec_string(ptr, vec_string.len());
    assert_eq!(vec_string, result);
  }

  #[test]
  fn test_str_to_heap_ptr_and_ptr_to_string() {
    let string = "string";
    let ptr = str_to_heap_ptr(string);
    let result = ptr_to_string(ptr);
    assert_eq!(string, result);
    unsafe {
      CString::from_raw(ptr);
    }
  }
}