From 7c16f4e379fcc79bcce2b6be73cbf03417ca1b59 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 24 Sep 2025 13:36:52 -0700 Subject: [PATCH 1/2] refactor(path): delegate implementations where possible --- src/path/arg.rs | 119 +++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 87 deletions(-) diff --git a/src/path/arg.rs b/src/path/arg.rs index 9edeb57ff..22034bd0e 100644 --- a/src/path/arg.rs +++ b/src/path/arg.rs @@ -243,9 +243,7 @@ impl Arg for &OsStr { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.into_c_str() } #[inline] @@ -253,9 +251,7 @@ impl Arg for &OsStr { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + return self.as_bytes().into_c_str(); } #[inline] @@ -264,7 +260,7 @@ impl Arg for &OsStr { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_bytes(), f) + return self.as_bytes().into_with_c_str(f); } } @@ -283,10 +279,7 @@ impl Arg for &OsString { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(OsString::as_os_str(self).as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -303,12 +296,11 @@ impl Arg for &OsString { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_bytes(), f) + self.as_os_str().into_with_c_str(f) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for OsString { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -322,9 +314,7 @@ impl Arg for OsString { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -332,9 +322,7 @@ impl Arg for OsString { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.into_vec().into_c_str() } #[inline] @@ -343,12 +331,11 @@ impl Arg for OsString { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - f(&CString::new(self.into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?) + f(&self.into_c_str()?) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for &Path { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -362,9 +349,7 @@ impl Arg for &Path { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -372,9 +357,7 @@ impl Arg for &Path { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -383,19 +366,15 @@ impl Arg for &Path { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_os_str().as_bytes(), f) + self.as_os_str().into_with_c_str(f) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for &PathBuf { #[inline] fn as_str(&self) -> io::Result<&str> { - PathBuf::as_path(self) - .as_os_str() - .to_str() - .ok_or(io::Errno::INVAL) + self.as_os_str().to_str().ok_or(io::Errno::INVAL) } #[inline] @@ -405,10 +384,7 @@ impl Arg for &PathBuf { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(PathBuf::as_path(self).as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -425,12 +401,11 @@ impl Arg for &PathBuf { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_os_str().as_bytes(), f) + self.as_os_str().into_with_c_str(f) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for PathBuf { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -444,9 +419,7 @@ impl Arg for PathBuf { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -454,9 +427,7 @@ impl Arg for PathBuf { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.into_os_string().into_vec()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.into_os_string().into_c_str() } #[inline] @@ -465,10 +436,7 @@ impl Arg for PathBuf { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - f( - &CString::new(self.into_os_string().into_vec()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - ) + self.into_os_string().into_with_c_str(f) } } @@ -637,9 +605,7 @@ impl<'a> Arg for Cow<'a, OsStr> { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + (&**self).into_c_str() } #[inline] @@ -647,13 +613,10 @@ impl<'a> Arg for Cow<'a, OsStr> { where Self: 'b, { - Ok(Cow::Owned( - match self { - Cow::Owned(os) => CString::new(os.into_vec()), - Cow::Borrowed(os) => CString::new(os.as_bytes()), - } - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + match self { + Cow::Owned(os) => os.into_c_str(), + Cow::Borrowed(os) => os.into_c_str(), + } } #[inline] @@ -662,7 +625,7 @@ impl<'a> Arg for Cow<'a, OsStr> { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_bytes(), f) + (&*self).into_with_c_str(f) } } @@ -717,9 +680,7 @@ impl<'a> Arg for Component<'a> { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -727,9 +688,7 @@ impl<'a> Arg for Component<'a> { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.as_os_str().as_bytes()).map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_os_str().into_c_str() } #[inline] @@ -738,12 +697,11 @@ impl<'a> Arg for Component<'a> { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_os_str().as_bytes(), f) + self.as_os_str().into_with_c_str(f) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl<'a> Arg for Components<'a> { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -757,10 +715,7 @@ impl<'a> Arg for Components<'a> { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_path().into_c_str() } #[inline] @@ -768,10 +723,7 @@ impl<'a> Arg for Components<'a> { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_path().into_c_str() } #[inline] @@ -780,12 +732,11 @@ impl<'a> Arg for Components<'a> { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_path().as_os_str().as_bytes(), f) + self.as_path().into_with_c_str(f) } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl<'a> Arg for Iter<'a> { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -799,10 +750,7 @@ impl<'a> Arg for Iter<'a> { #[inline] fn as_cow_c_str(&self) -> io::Result> { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_path().into_c_str() } #[inline] @@ -810,10 +758,7 @@ impl<'a> Arg for Iter<'a> { where Self: 'b, { - Ok(Cow::Owned( - CString::new(self.as_path().as_os_str().as_bytes()) - .map_err(|_cstr_err| io::Errno::INVAL)?, - )) + self.as_path().into_c_str() } #[inline] @@ -822,7 +767,7 @@ impl<'a> Arg for Iter<'a> { Self: Sized, F: FnOnce(&CStr) -> io::Result, { - with_c_str(self.as_path().as_os_str().as_bytes(), f) + self.as_path().into_with_c_str(f) } } From f88b1813f0e978b8053e7ea4ada1e49916525284 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 24 Sep 2025 13:37:49 -0700 Subject: [PATCH 2/2] feat(path): enable Path and friends on wasip2 without the feature Unfortunately, `OsStrExt` and `OsStringExt` require the wasip2 feature on wasip2 so we can't use `as_bytes()` on `OsStr` and friends. However, the recommendation on the upstream issue [1] is to just use `to_str` as WASI paths are unicode. [1]: https://github.com/rust-lang/rust/issues/130323#issuecomment-2350430693 --- src/path/arg.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/path/arg.rs b/src/path/arg.rs index 22034bd0e..d7e0a2edf 100644 --- a/src/path/arg.rs +++ b/src/path/arg.rs @@ -229,7 +229,6 @@ impl Arg for String { } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for &OsStr { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -251,6 +250,9 @@ impl Arg for &OsStr { where Self: 'b, { + #[cfg(all(target_os = "wasi", target_env = "p2", not(wasip2)))] + return self.to_str().ok_or(io::Errno::INVAL)?.into_c_str(); + #[cfg(any(wasip2, not(all(target_os = "wasi", target_env = "p2"))))] return self.as_bytes().into_c_str(); } @@ -260,12 +262,15 @@ impl Arg for &OsStr { Self: Sized, F: FnOnce(&CStr) -> io::Result, { + #[cfg(all(target_os = "wasi", target_env = "p2", not(wasip2)))] + return self.as_str()?.into_with_c_str(f); + + #[cfg(any(wasip2, not(all(target_os = "wasi", target_env = "p2"))))] return self.as_bytes().into_with_c_str(f); } } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for &OsString { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -322,6 +327,12 @@ impl Arg for OsString { where Self: 'b, { + #[cfg(all(target_os = "wasi", target_env = "p2", not(wasip2)))] + return self + .into_string() + .map_err(|_strng_err| io::Errno::INVAL)? + .into_c_str(); + #[cfg(any(wasip2, not(all(target_os = "wasi", target_env = "p2"))))] self.into_vec().into_c_str() } @@ -591,7 +602,6 @@ impl<'a> Arg for Cow<'a, str> { } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl<'a> Arg for Cow<'a, OsStr> { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -666,7 +676,6 @@ impl<'a> Arg for Cow<'a, CStr> { } #[cfg(feature = "std")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl<'a> Arg for Component<'a> { #[inline] fn as_str(&self) -> io::Result<&str> { @@ -855,7 +864,6 @@ impl Arg for &Vec { } #[cfg(feature = "alloc")] -#[cfg(any(not(target_os = "wasi"), not(target_env = "p2"), wasip2))] impl Arg for Vec { #[inline] fn as_str(&self) -> io::Result<&str> {