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.
This commit is contained in:
Aaron Turon 2014-05-05 14:15:11 -07:00
parent e10fd31721
commit 8f9cbe08c6
3 changed files with 95 additions and 3 deletions

View File

@ -82,6 +82,7 @@ use slice::{ImmutableVector, MutableVector};
use slice; use slice;
use str::StrSlice; use str::StrSlice;
use str; use str;
use strbuf::StrBuf;
/// The representation of a C String. /// 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 { impl<'a> ToCStr for &'a str {
#[inline] #[inline]
fn to_c_str(&self) -> CString { 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<T>(&self, f: |*libc::c_char| -> T) -> T {
self.as_bytes().with_c_str(f)
}
#[inline]
unsafe fn with_c_str_unchecked<T>(&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<T>(&self, f: |*libc::c_char| -> T) -> T {
self.as_bytes().with_c_str(f)
}
#[inline]
unsafe fn with_c_str_unchecked<T>(&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()` // The length of the stack allocated buffer for `vec.with_c_str()`
static BUF_LEN: uint = 128; static BUF_LEN: uint = 128;

View File

@ -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 { impl ToCStr for Path {
#[inline] #[inline]
fn to_c_str(&self) -> CString { fn to_c_str(&self) -> CString {
// The Path impl guarantees no internal NUL // The Path impl guarantees no internal NUL
unsafe { self.as_vec().to_c_str_unchecked() } unsafe { self.to_c_str_unchecked() }
} }
#[inline] #[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<S: Writer> ::hash::Hash<S> for Path { impl<S: Writer> ::hash::Hash<S> for Path {
#[inline] #[inline]
fn hash(&self, state: &mut S) { fn hash(&self, state: &mut S) {

View File

@ -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 { impl ToCStr for Path {
#[inline] #[inline]
fn to_c_str(&self) -> CString { fn to_c_str(&self) -> CString {
// The Path impl guarantees no embedded NULs // The Path impl guarantees no internal NUL
unsafe { self.as_vec().to_c_str_unchecked() } unsafe { self.to_c_str_unchecked() }
} }
#[inline] #[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<S: Writer> ::hash::Hash<S> for Path { impl<S: Writer> ::hash::Hash<S> for Path {
#[inline] #[inline]
fn hash(&self, state: &mut S) { fn hash(&self, state: &mut S) {