From 8f9cbe08c61b05527e6d48589d4a963126448467 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 StrBuf 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 StrBuf, 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 | 54 ++++++++++++++++++++++++++++++++++++++ src/libstd/path/posix.rs | 21 ++++++++++++++- src/libstd/path/windows.rs | 23 ++++++++++++++-- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 0885a7af00b4d..0c529ee4d963e 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -82,6 +82,7 @@ use slice::{ImmutableVector, MutableVector}; use slice; use str::StrSlice; use str; +use strbuf::StrBuf; /// The representation of a C String. /// @@ -292,6 +293,14 @@ 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 and StrBuf, 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 { @@ -314,6 +323,51 @@ 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) + } +} + + +impl ToCStr for StrBuf { + #[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 dfe7241d7af03..176788edcc466 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) {