scolapasta_path/platform_string/
unix_wasi.rs

1#![expect(
2    clippy::unnecessary_wraps,
3    reason = "source compatibility with other platforms which may be fallible"
4)]
5
6use std::ffi::{OsStr, OsString};
7#[cfg(unix)]
8use std::os::unix::ffi::{OsStrExt, OsStringExt};
9#[cfg(target_os = "wasi")]
10use std::os::wasi::ffi::{OsStrExt, OsStringExt};
11#[cfg(not(any(unix, target_os = "wasi")))]
12error!("Internal: This module can only be compiled on unix and wasi");
13
14use super::ConvertBytesError;
15
16pub fn bytes_to_os_str(bytes: &[u8]) -> Result<&OsStr, ConvertBytesError> {
17    Ok(OsStr::from_bytes(bytes))
18}
19
20pub fn bytes_to_os_string(bytes: Vec<u8>) -> Result<OsString, ConvertBytesError> {
21    Ok(OsString::from_vec(bytes))
22}
23
24pub fn os_str_to_bytes(os_str: &OsStr) -> Result<&[u8], ConvertBytesError> {
25    Ok(os_str.as_bytes())
26}
27
28pub fn os_string_to_bytes(os_string: OsString) -> Result<Vec<u8>, ConvertBytesError> {
29    Ok(os_string.into_vec())
30}
31
32#[cfg(test)]
33mod tests {
34    use std::ffi::OsString;
35    #[cfg(unix)]
36    use std::os::unix::ffi::OsStringExt;
37    #[cfg(target_os = "wasi")]
38    use std::os::wasi::ffi::OsStringExt;
39    use std::str;
40
41    use super::{bytes_to_os_str, bytes_to_os_string, os_str_to_bytes, os_string_to_bytes};
42
43    #[test]
44    fn utf8_bytes_convert_to_os_str() {
45        let test_cases: &[&[u8]] = &[b"", b"abc", b"abc\0", b"\0abc", b"abc/xyz"];
46        for &bytes in test_cases {
47            bytes_to_os_str(bytes).unwrap();
48            bytes_to_os_string(bytes.to_vec()).unwrap();
49        }
50    }
51
52    #[test]
53    fn invalid_utf8_bytes_convert_to_os_str() {
54        let test_cases: &[&[u8]] = &[b"\xFF", b"\xFE", b"abc/\xFF/\xFE", b"\0\xFF", b"\xFF\0"];
55        for &bytes in test_cases {
56            bytes_to_os_str(bytes).unwrap();
57            bytes_to_os_string(bytes.to_vec()).unwrap();
58        }
59    }
60
61    #[test]
62    fn bytes_os_str_round_trip() {
63        let test_cases: &[&[u8]] = &[b"", b"abc", b"abc\0", b"\0abc", b"abc/xyz"];
64        for &bytes in test_cases {
65            let os_str = bytes_to_os_str(bytes).unwrap();
66            assert_eq!(os_str_to_bytes(os_str).unwrap(), bytes);
67
68            let os_string = bytes_to_os_string(bytes.to_vec()).unwrap();
69            assert_eq!(os_string_to_bytes(os_string).unwrap(), bytes);
70        }
71    }
72
73    #[test]
74    fn invalid_utf8_bytes_os_str_round_trip() {
75        let test_cases: &[&[u8]] = &[b"\xFF", b"\xFE", b"abc/\xFF/\xFE", b"\0\xFF", b"\xFF\0"];
76        for &bytes in test_cases {
77            let os_str = bytes_to_os_str(bytes).unwrap();
78            assert_eq!(os_str_to_bytes(os_str).unwrap(), bytes);
79
80            let os_string = bytes_to_os_string(bytes.to_vec()).unwrap();
81            assert_eq!(os_string_to_bytes(os_string).unwrap(), bytes);
82        }
83    }
84
85    #[test]
86    fn owned_utf8_bytes_convert_to_os_string() {
87        let test_cases: &[&[u8]] = &[b"", b"abc", b"abc\0", b"\0abc", b"abc/xyz"];
88        for &bytes in test_cases {
89            let s = str::from_utf8(bytes).unwrap();
90            let os_string = OsString::from(s.to_owned());
91            os_string_to_bytes(os_string).unwrap();
92        }
93    }
94
95    #[test]
96    fn owned_invalid_utf8_bytes_convert_to_os_string() {
97        let test_cases: &[&[u8]] = &[b"\xFF", b"\xFE", b"abc/\xFF/\xFE", b"\0\xFF", b"\xFF\0"];
98        for &bytes in test_cases {
99            let os_string = OsString::from_vec(bytes.to_owned());
100            os_string_to_bytes(os_string).unwrap();
101        }
102    }
103
104    #[test]
105    fn bytes_os_string_round_trip() {
106        let test_cases: &[&[u8]] = &[b"", b"abc", b"abc\0", b"\0abc", b"abc/xyz"];
107        for &bytes in test_cases {
108            let os_string = bytes_to_os_string(bytes.to_owned()).unwrap();
109            assert_eq!(os_string_to_bytes(os_string).unwrap(), bytes);
110        }
111    }
112
113    #[test]
114    fn invalid_utf8_bytes_os_string_round_trip() {
115        let test_cases: &[&[u8]] = &[b"\xFF", b"\xFE", b"abc/\xFF/\xFE", b"\0\xFF", b"\xFF\0"];
116        for &bytes in test_cases {
117            let os_string = bytes_to_os_string(bytes.to_owned()).unwrap();
118            assert_eq!(os_string_to_bytes(os_string).unwrap(), bytes);
119        }
120    }
121}