1use std::ffi::{CStr, CString, NulError};
2use std::os::raw::c_char;
3use std::str::Utf8Error;
4
5pub fn string_to_cstring(string: String) -> Result<CString, NulError> {
6 let result = CString::new(string)?;
7
8 Ok(result)
9}
10
11pub fn cstr_to_string(unsafe_string: *const c_char) -> Result<String, Utf8Error> {
12 let result = unsafe { CStr::from_ptr(unsafe_string) }
13 .to_str()?
14 .to_string();
15
16 Ok(result)
17}
18
19#[cfg(test)]
20mod tests {
21 use super::*;
22 use std::ffi::CString;
23
24 #[test]
25 fn roundtrip_ascii() {
26 let original = String::from("Hello, world!");
27 let cstring = string_to_cstring(original.clone()).unwrap();
28
29 let ptr = cstring.as_ptr();
30 let recovered = cstr_to_string(ptr).unwrap();
31
32 assert_eq!(recovered, original);
33 }
34
35 #[test]
36 fn roundtrip_unicode() {
37 let original = String::from("こんにちは世界");
38 let cstring = string_to_cstring(original.clone()).unwrap();
39
40 let ptr = cstring.as_ptr();
41 let recovered = cstr_to_string(ptr).unwrap();
42
43 assert_eq!(recovered, original);
44 }
45
46 #[test]
47 fn empty_string() {
48 let original = String::new();
49 let cstring = string_to_cstring(original.clone()).unwrap();
50
51 let ptr = cstring.as_ptr();
52 let recovered = cstr_to_string(ptr).unwrap();
53
54 assert_eq!(recovered, original);
55 }
56
57 #[test]
58 fn from_cstring_direct() {
59 let original = "Direct CString".to_string();
60 let cstring = CString::new(original.clone()).unwrap();
61
62 let ptr = cstring.as_ptr();
63 let recovered = cstr_to_string(ptr).unwrap();
64
65 assert_eq!(recovered, original);
66 }
67
68 #[test]
69 fn invalid_utf8_pointer() {
70 let bytes: &[u8] = b"\xff\x00";
71 let ptr = bytes.as_ptr() as *const c_char;
72
73 assert!(cstr_to_string(ptr).is_err());
74 }
75
76 #[test]
77 fn interior_null_byte() {
78 let original = String::from("Hello\0World");
79
80 assert!(string_to_cstring(original).is_err());
81 }
82
83 #[test]
84 fn invalid_utf8_sequence_in_cstr_to_string() {
85 let bytes: &[u8] = b"\xff\x00";
86 let ptr = bytes.as_ptr() as *const c_char;
87
88 assert!(cstr_to_string(ptr).is_err());
89 }
90}