Skip to content

Commit

Permalink
Add ToCStr impl for &Path and StrBuf
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aturon committed May 15, 2014
1 parent e10fd31 commit 8f9cbe0
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 3 deletions.
54 changes: 54 additions & 0 deletions src/libstd/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ use slice::{ImmutableVector, MutableVector};
use slice;
use str::StrSlice;
use str;
use strbuf::StrBuf;

/// The representation of a C String.
///
Expand Down Expand Up @@ -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 {
Expand All @@ -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()`
static BUF_LEN: uint = 128;

Expand Down
21 changes: 20 additions & 1 deletion src/libstd/path/posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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 {
#[inline]
fn hash(&self, state: &mut S) {
Expand Down
23 changes: 21 additions & 2 deletions src/libstd/path/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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 {
#[inline]
fn hash(&self, state: &mut S) {
Expand Down

0 comments on commit 8f9cbe0

Please sign in to comment.