Skip to main content

libblkid_rs/
encode.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::ffi::CString;
6
7use libc::{c_char, c_int};
8
9use crate::{err::BlkidErr, Result};
10
11// Shared code for encoding methods
12fn string_shared<F>(string: &str, closure: F) -> Result<String>
13where
14    F: Fn(&CString, &mut Vec<u8>) -> c_int,
15{
16    // Per the documentation, the maximum buffer is 4 times
17    // the length of the string.
18    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
34/// Encode potentially unsafe characters in the given `string` parameter.
35pub 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
45/// Generate a safe string that allows ascii, hex-escaping, and utf8. Whitespaces
46/// become `_`.
47pub 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}