use crate::error::{Error, Result};
use libc::{c_char, c_void};
use std::ffi::CStr;
pub(crate) unsafe fn malloc_copy(bytes: &[u8]) -> Result<*mut c_char> {
let alloc_len = if bytes.is_empty() { 1 } else { bytes.len() };
let buf = libc::malloc(alloc_len) as *mut c_char;
if buf.is_null() {
return Err(Error::Alloc("malloc failed"));
}
if !bytes.is_empty() {
libc::memcpy(
buf as *mut c_void,
bytes.as_ptr() as *const c_void,
bytes.len(),
);
}
Ok(buf)
}
pub(crate) unsafe fn take_c_string(ptr: *mut c_char) -> String {
let c_str = CStr::from_ptr(ptr);
let s = c_str.to_string_lossy().into_owned();
libc::free(ptr as *mut c_void);
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_malloc_copy_normal() {
unsafe {
let data = b"hello world";
let buf = malloc_copy(data).unwrap();
assert!(!buf.is_null());
let slice = std::slice::from_raw_parts(buf as *const u8, data.len());
assert_eq!(slice, data);
libc::free(buf as *mut c_void);
}
}
#[test]
fn test_malloc_copy_empty() {
unsafe {
let data = b"";
let buf = malloc_copy(data).unwrap();
assert!(!buf.is_null());
libc::free(buf as *mut c_void);
}
}
}