Skip to main content

cabocha/
utils.rs

1use std::ffi::{CStr, CString};
2use std::os::raw::*;
3use std::{slice, str};
4
5pub fn ptr_to_string(ptr: *const c_char) -> String {
6  let strs = if ptr.is_null() {
7    ""
8  } else {
9    let cstr = unsafe { CStr::from_ptr(ptr) };
10    if let Ok(s) = str::from_utf8(cstr.to_bytes()) {
11      s
12    } else {
13      ""
14    }
15  };
16  strs.to_string()
17}
18
19pub fn ptr_to_vec_string(ptr: *const *const c_char, size: usize) -> Vec<String> {
20  let slice = unsafe { slice::from_raw_parts(ptr, size) };
21  slice
22    .iter()
23    .map(|raw_str| ptr_to_string(*raw_str))
24    .collect()
25}
26
27pub fn str_to_heap_ptr<T: Into<Vec<u8>>>(input: T) -> *mut c_char {
28  CString::new(input).unwrap().into_raw()
29}
30
31#[cfg(test)]
32mod tests {
33  use super::*;
34
35  #[test]
36  fn test_ptr_to_vec_string() {
37    let vec_string = vec![String::from("string1"), String::from("string2")];
38    let vec_cstring = vec_string
39      .iter()
40      .map(|arg| CString::new(arg.as_str()).unwrap())
41      .collect::<Vec<CString>>();
42    let mut vec_ptr = vec_cstring
43      .iter()
44      .map(|arg| arg.as_ptr())
45      .collect::<Vec<*const c_char>>();
46    vec_ptr.push(std::ptr::null());
47    let ptr: *const *const c_char = vec_ptr.as_ptr();
48    let result = ptr_to_vec_string(ptr, vec_string.len());
49    assert_eq!(vec_string, result);
50  }
51
52  #[test]
53  fn test_str_to_heap_ptr_and_ptr_to_string() {
54    let string = "string";
55    let ptr = str_to_heap_ptr(string);
56    let result = ptr_to_string(ptr);
57    assert_eq!(string, result);
58    unsafe {
59      CString::from_raw(ptr);
60    }
61  }
62}