From 4e32b521eab06406c77554e42d0ef42b238e2861 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 5 May 2014 14:15:11 -0700 Subject: [PATCH] Add ToCStr impl for &Path and ~str This is a stopgap until DST (#12938) lands. Until DST lands, we cannot decompose &str into & and str, so we cannot usefully take ToCStr arguments by reference (without forcing an additional & around &str). So we are instead temporarily adding an instance for &Path and ~str, so that we can take ToCStr as owned. When DST lands, the &Path instance should be removed, the string instances should be revisted, and arguments bound by ToCStr should be passed by reference. FIXMEs have been added accordingly. --- src/libstd/c_str.rs | 29 +++++++++++++++++++++++++++++ src/libstd/path/posix.rs | 21 ++++++++++++++++++++- src/libstd/path/windows.rs | 23 +++++++++++++++++++++-- 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 310bc861cd3f2..d6b0253d213da 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -293,6 +293,13 @@ pub trait ToCStr { } } +// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so +// we cannot usefully take ToCStr arguments by reference (without forcing an +// additional & around &str). So we are instead temporarily adding an instance +// for ~str, so that we can take ToCStr as owned. When DST lands, the string +// instances should be revisted, and arguments bound by ToCStr should be passed +// by reference. + impl<'a> ToCStr for &'a str { #[inline] fn to_c_str(&self) -> CString { @@ -315,6 +322,28 @@ impl<'a> ToCStr for &'a str { } } +impl ToCStr for ~str { + #[inline] + fn to_c_str(&self) -> CString { + self.as_bytes().to_c_str() + } + + #[inline] + unsafe fn to_c_str_unchecked(&self) -> CString { + self.as_bytes().to_c_str_unchecked() + } + + #[inline] + fn with_c_str(&self, f: |*libc::c_char| -> T) -> T { + self.as_bytes().with_c_str(f) + } + + #[inline] + unsafe fn with_c_str_unchecked(&self, f: |*libc::c_char| -> T) -> T { + self.as_bytes().with_c_str_unchecked(f) + } +} + // The length of the stack allocated buffer for `vec.with_c_str()` static BUF_LEN: uint = 128; diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 99a281755e4e0..4f7132dc6e442 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -79,11 +79,18 @@ impl FromStr for Path { } } +// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so +// we cannot usefully take ToCStr arguments by reference (without forcing an +// additional & around &str). So we are instead temporarily adding an instance +// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path +// instance should be removed, and arguments bound by ToCStr should be passed by +// reference. + impl ToCStr for Path { #[inline] fn to_c_str(&self) -> CString { // The Path impl guarantees no internal NUL - unsafe { self.as_vec().to_c_str_unchecked() } + unsafe { self.to_c_str_unchecked() } } #[inline] @@ -92,6 +99,18 @@ impl ToCStr for Path { } } +impl<'a> ToCStr for &'a Path { + #[inline] + fn to_c_str(&self) -> CString { + (*self).to_c_str() + } + + #[inline] + unsafe fn to_c_str_unchecked(&self) -> CString { + (*self).to_c_str_unchecked() + } +} + impl ::hash::Hash for Path { #[inline] fn hash(&self, state: &mut S) { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 758a76167cdef..c58ccbd225d56 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -103,11 +103,18 @@ impl FromStr for Path { } } +// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so +// we cannot usefully take ToCStr arguments by reference (without forcing an +// additional & around &str). So we are instead temporarily adding an instance +// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path +// instance should be removed, and arguments bound by ToCStr should be passed by +// reference. + impl ToCStr for Path { #[inline] fn to_c_str(&self) -> CString { - // The Path impl guarantees no embedded NULs - unsafe { self.as_vec().to_c_str_unchecked() } + // The Path impl guarantees no internal NUL + unsafe { self.to_c_str_unchecked() } } #[inline] @@ -116,6 +123,18 @@ impl ToCStr for Path { } } +impl<'a> ToCStr for &'a Path { + #[inline] + fn to_c_str(&self) -> CString { + (*self).to_c_str() + } + + #[inline] + unsafe fn to_c_str_unchecked(&self) -> CString { + (*self).to_c_str_unchecked() + } +} + impl ::hash::Hash for Path { #[inline] fn hash(&self, state: &mut S) {