scolapasta_path/platform_string.rs
1//! Conversions between [platform strings] and bytes.
2//!
3//! [platform strings]: OsString
4
5use core::fmt;
6use std::error;
7use std::ffi::{OsStr, OsString};
8
9#[cfg(not(any(unix, windows, target_os = "wasi")))]
10mod default;
11#[cfg(any(unix, target_os = "wasi"))]
12mod unix_wasi;
13#[cfg(windows)]
14mod windows;
15
16#[cfg(not(any(unix, windows, target_os = "wasi")))]
17use default as imp;
18#[cfg(any(unix, target_os = "wasi"))]
19use unix_wasi as imp;
20#[cfg(windows)]
21use windows as imp;
22
23/// Convert a byte slice to a platform-specific [`OsStr`].
24///
25/// Unsupported platforms fallback to converting through [`str`].
26///
27/// # Examples
28///
29/// ```
30/// # use std::ffi::OsStr;
31/// # use scolapasta_path::bytes_to_os_str;
32/// let bytes: &[u8] = b"/etc/passwd";
33/// assert_eq!(bytes_to_os_str(bytes), Ok(OsStr::new("/etc/passwd")));
34/// ```
35///
36/// # Errors
37///
38/// On unix-like platforms, this function is infallible.
39///
40/// On Windows, if the given byte slice does not contain valid UTF-8, an error
41/// is returned.
42#[inline]
43pub fn bytes_to_os_str(bytes: &[u8]) -> Result<&OsStr, ConvertBytesError> {
44 imp::bytes_to_os_str(bytes)
45}
46
47/// Convert a byte vec to a platform-specific [`OsString`].
48///
49/// Unsupported platforms fallback to converting through [`String`].
50///
51/// # Examples
52///
53/// ```
54/// # use std::ffi::OsString;
55/// # use scolapasta_path::bytes_to_os_string;
56/// let bytes = b"/etc/passwd".to_vec();
57/// assert_eq!(bytes_to_os_string(bytes), Ok(OsString::from("/etc/passwd")));
58/// ```
59///
60/// # Errors
61///
62/// On unix-like platforms, this function is infallible.
63///
64/// On Windows, if the given byte slice does not contain valid UTF-8, an error
65/// is returned.
66#[inline]
67pub fn bytes_to_os_string(bytes: Vec<u8>) -> Result<OsString, ConvertBytesError> {
68 imp::bytes_to_os_string(bytes)
69}
70
71/// Convert a platform-specific [`OsStr`] to a byte slice.
72///
73/// Unsupported platforms fallback to converting through [`str`].
74///
75/// # Examples
76///
77/// ```
78/// # use std::ffi::OsStr;
79/// # use scolapasta_path::os_str_to_bytes;
80/// let platform_string: &OsStr = OsStr::new("/etc/passwd");
81/// assert_eq!(os_str_to_bytes(platform_string), Ok(&b"/etc/passwd"[..]));
82/// ```
83///
84/// # Errors
85///
86/// On unix-like platforms, this function is infallible.
87///
88/// On Windows, if the given byte slice does not contain valid UTF-8, an error
89/// is returned.
90#[inline]
91pub fn os_str_to_bytes(os_str: &OsStr) -> Result<&[u8], ConvertBytesError> {
92 imp::os_str_to_bytes(os_str)
93}
94
95/// Convert a platform-specific [`OsString`] to a byte vec.
96///
97/// Unsupported platforms fallback to converting through [`String`].
98///
99/// # Examples
100///
101/// ```
102/// # use std::ffi::OsString;
103/// # use scolapasta_path::os_string_to_bytes;
104/// let platform_string: OsString = OsString::from("/etc/passwd");
105/// assert_eq!(
106/// os_string_to_bytes(platform_string),
107/// Ok(b"/etc/passwd".to_vec())
108/// );
109/// ```
110///
111/// # Errors
112///
113/// On unix-like platforms, this function is infallible.
114///
115/// On Windows, if the given byte slice does not contain valid UTF-8, an error
116/// is returned.
117#[inline]
118pub fn os_string_to_bytes(os_string: OsString) -> Result<Vec<u8>, ConvertBytesError> {
119 imp::os_string_to_bytes(os_string)
120}
121
122/// Error returned when a [platform string] cannot be converted to bytes or
123/// bytes cannot be converted to a [platform string].
124///
125/// On unix-like platforms, this error is never returned. On Windows platforms,
126/// platform strings can only be converted to byte vectors (and conversely byte
127/// vectors to platform strings) when they contain valid UTF-8 contents.
128///
129/// This error is returned by [`bytes_to_os_str`], [`os_string_to_bytes`] and
130/// [`os_str_to_bytes`]. See their documentation for more details.
131///
132/// [platform string]: OsString
133#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
134pub struct ConvertBytesError {
135 _private: (),
136}
137
138impl ConvertBytesError {
139 /// Constructs a new, default `ConvertBytesError`.
140 ///
141 /// # Examples
142 ///
143 /// ```
144 /// # use scolapasta_path::ConvertBytesError;
145 /// const ERR: ConvertBytesError = ConvertBytesError::new();
146 /// assert_eq!(
147 /// ERR.message(),
148 /// "Could not convert between bytes and platform string"
149 /// );
150 /// ```
151 #[inline]
152 #[must_use]
153 pub const fn new() -> Self {
154 Self { _private: () }
155 }
156
157 /// Retrieve the exception message associated with this convert bytes error.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// # use scolapasta_path::ConvertBytesError;
163 /// let err = ConvertBytesError::new();
164 /// assert_eq!(
165 /// err.message(),
166 /// "Could not convert between bytes and platform string"
167 /// );
168 /// ```
169 #[inline]
170 #[must_use]
171 pub const fn message(self) -> &'static str {
172 "Could not convert between bytes and platform string"
173 }
174}
175
176impl fmt::Display for ConvertBytesError {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.write_str(self.message())
179 }
180}
181
182impl error::Error for ConvertBytesError {}