about summary refs log tree commit diff
path: root/library/std/src/sys/path/windows.rs
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2025-04-11 16:15:34 +0000
committerChris Denton <chris@chrisdenton.dev>2025-04-11 18:02:03 +0000
commitb613e9781a773232f81af9f61a8c8ac34b04873a (patch)
tree928795829efa5ecb8426dce0c784f11b9af98540 /library/std/src/sys/path/windows.rs
parent2205455d444f5f9da3a52e50f43c0306480218fb (diff)
downloadrust-b613e9781a773232f81af9f61a8c8ac34b04873a.tar.gz
rust-b613e9781a773232f81af9f61a8c8ac34b04873a.zip
Use with_native_path for Windows
Also add a WCStr type
Diffstat (limited to 'library/std/src/sys/path/windows.rs')
-rw-r--r--library/std/src/sys/path/windows.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs
index 6547ed9aa5f..e0e003f6a81 100644
--- a/library/std/src/sys/path/windows.rs
+++ b/library/std/src/sys/path/windows.rs
@@ -10,6 +10,40 @@ mod tests;
 pub const MAIN_SEP_STR: &str = "\\";
 pub const MAIN_SEP: char = '\\';
 
+/// A null terminated wide string.
+#[repr(transparent)]
+pub struct WCStr([u16]);
+
+impl WCStr {
+    /// Convert a slice to a WCStr without checks.
+    ///
+    /// Though it is memory safe, the slice should also not contain interior nulls
+    /// as this may lead to unwanted truncation.
+    ///
+    /// # Safety
+    ///
+    /// The slice must end in a null.
+    pub unsafe fn from_wchars_with_null_unchecked(s: &[u16]) -> &Self {
+        unsafe { &*(s as *const [u16] as *const Self) }
+    }
+
+    pub fn as_ptr(&self) -> *const u16 {
+        self.0.as_ptr()
+    }
+
+    pub fn count_bytes(&self) -> usize {
+        self.0.len()
+    }
+}
+
+#[inline]
+pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) -> io::Result<T> {
+    let path = maybe_verbatim(path)?;
+    // SAFETY: maybe_verbatim returns null-terminated strings
+    let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) };
+    f(path)
+}
+
 #[inline]
 pub fn is_sep_byte(b: u8) -> bool {
     b == b'/' || b == b'\\'