1use std::ffi::CString;
6
7use libc::{c_char, c_int};
8
9use crate::{err::BlkidErr, Result};
10
11fn string_shared<F>(string: &str, closure: F) -> Result<String>
13where
14 F: Fn(&CString, &mut Vec<u8>) -> c_int,
15{
16 let mut buffer = vec![0u8; string.len() * 4];
19
20 let cstring = CString::new(string)?;
21 if closure(&cstring, &mut buffer) != 0 {
22 return Err(BlkidErr::InvalidConv);
23 }
24
25 let first_null = buffer
26 .iter()
27 .position(|u| *u == 0)
28 .ok_or_else(|| BlkidErr::Other("No null found in C string".to_string()))?;
29 buffer.truncate(first_null);
30 let buffer_cstring = CString::new(buffer)?;
31 buffer_cstring.into_string().map_err(BlkidErr::IntoString)
32}
33
34pub fn encode_string(string: &str) -> Result<String> {
36 string_shared(string, |cstring, buffer| unsafe {
37 libblkid_rs_sys::blkid_encode_string(
38 cstring.as_ptr(),
39 buffer.as_mut_ptr() as *mut c_char,
40 buffer.len(),
41 )
42 })
43}
44
45pub fn safe_string(string: &str) -> Result<String> {
48 string_shared(string, |cstring, buffer| unsafe {
49 libblkid_rs_sys::blkid_safe_string(
50 cstring.as_ptr(),
51 buffer.as_mut_ptr() as *mut c_char,
52 buffer.len(),
53 )
54 })
55}
56
57#[cfg(test)]
58mod test {
59 use super::*;
60
61 #[test]
62 fn test_encode_string() {
63 let encoded_string = encode_string("\\test string").unwrap();
64 assert_eq!(encoded_string, "\\x5ctest\\x20string");
65 }
66
67 #[test]
68 fn test_safe_string() {
69 let safe_string = safe_string("test string").unwrap();
70 assert_eq!(safe_string, "test_string");
71 }
72}