Skip to content

Commit 8f9cbe0

Browse files
committed
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.
1 parent e10fd31 commit 8f9cbe0

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

src/libstd/c_str.rs

+54
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ use slice::{ImmutableVector, MutableVector};
8282
use slice;
8383
use str::StrSlice;
8484
use str;
85+
use strbuf::StrBuf;
8586

8687
/// The representation of a C String.
8788
///
@@ -292,6 +293,14 @@ pub trait ToCStr {
292293
}
293294
}
294295

296+
// FIXME (#12938): Until DST lands, we cannot decompose &str into &
297+
// and str, so we cannot usefully take ToCStr arguments by reference
298+
// (without forcing an additional & around &str). So we are instead
299+
// temporarily adding an instance for ~str and StrBuf, so that we can
300+
// take ToCStr as owned. When DST lands, the string instances should
301+
// be revisted, and arguments bound by ToCStr should be passed by
302+
// reference.
303+
295304
impl<'a> ToCStr for &'a str {
296305
#[inline]
297306
fn to_c_str(&self) -> CString {
@@ -314,6 +323,51 @@ impl<'a> ToCStr for &'a str {
314323
}
315324
}
316325

326+
impl ToCStr for ~str {
327+
#[inline]
328+
fn to_c_str(&self) -> CString {
329+
self.as_bytes().to_c_str()
330+
}
331+
332+
#[inline]
333+
unsafe fn to_c_str_unchecked(&self) -> CString {
334+
self.as_bytes().to_c_str_unchecked()
335+
}
336+
337+
#[inline]
338+
fn with_c_str<T>(&self, f: |*libc::c_char| -> T) -> T {
339+
self.as_bytes().with_c_str(f)
340+
}
341+
342+
#[inline]
343+
unsafe fn with_c_str_unchecked<T>(&self, f: |*libc::c_char| -> T) -> T {
344+
self.as_bytes().with_c_str_unchecked(f)
345+
}
346+
}
347+
348+
349+
impl ToCStr for StrBuf {
350+
#[inline]
351+
fn to_c_str(&self) -> CString {
352+
self.as_bytes().to_c_str()
353+
}
354+
355+
#[inline]
356+
unsafe fn to_c_str_unchecked(&self) -> CString {
357+
self.as_bytes().to_c_str_unchecked()
358+
}
359+
360+
#[inline]
361+
fn with_c_str<T>(&self, f: |*libc::c_char| -> T) -> T {
362+
self.as_bytes().with_c_str(f)
363+
}
364+
365+
#[inline]
366+
unsafe fn with_c_str_unchecked<T>(&self, f: |*libc::c_char| -> T) -> T {
367+
self.as_bytes().with_c_str_unchecked(f)
368+
}
369+
}
370+
317371
// The length of the stack allocated buffer for `vec.with_c_str()`
318372
static BUF_LEN: uint = 128;
319373

src/libstd/path/posix.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,18 @@ impl FromStr for Path {
7979
}
8080
}
8181

82+
// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
83+
// we cannot usefully take ToCStr arguments by reference (without forcing an
84+
// additional & around &str). So we are instead temporarily adding an instance
85+
// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
86+
// instance should be removed, and arguments bound by ToCStr should be passed by
87+
// reference.
88+
8289
impl ToCStr for Path {
8390
#[inline]
8491
fn to_c_str(&self) -> CString {
8592
// The Path impl guarantees no internal NUL
86-
unsafe { self.as_vec().to_c_str_unchecked() }
93+
unsafe { self.to_c_str_unchecked() }
8794
}
8895

8996
#[inline]
@@ -92,6 +99,18 @@ impl ToCStr for Path {
9299
}
93100
}
94101

102+
impl<'a> ToCStr for &'a Path {
103+
#[inline]
104+
fn to_c_str(&self) -> CString {
105+
(*self).to_c_str()
106+
}
107+
108+
#[inline]
109+
unsafe fn to_c_str_unchecked(&self) -> CString {
110+
(*self).to_c_str_unchecked()
111+
}
112+
}
113+
95114
impl<S: Writer> ::hash::Hash<S> for Path {
96115
#[inline]
97116
fn hash(&self, state: &mut S) {

src/libstd/path/windows.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,18 @@ impl FromStr for Path {
103103
}
104104
}
105105

106+
// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
107+
// we cannot usefully take ToCStr arguments by reference (without forcing an
108+
// additional & around &str). So we are instead temporarily adding an instance
109+
// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
110+
// instance should be removed, and arguments bound by ToCStr should be passed by
111+
// reference.
112+
106113
impl ToCStr for Path {
107114
#[inline]
108115
fn to_c_str(&self) -> CString {
109-
// The Path impl guarantees no embedded NULs
110-
unsafe { self.as_vec().to_c_str_unchecked() }
116+
// The Path impl guarantees no internal NUL
117+
unsafe { self.to_c_str_unchecked() }
111118
}
112119

113120
#[inline]
@@ -116,6 +123,18 @@ impl ToCStr for Path {
116123
}
117124
}
118125

126+
impl<'a> ToCStr for &'a Path {
127+
#[inline]
128+
fn to_c_str(&self) -> CString {
129+
(*self).to_c_str()
130+
}
131+
132+
#[inline]
133+
unsafe fn to_c_str_unchecked(&self) -> CString {
134+
(*self).to_c_str_unchecked()
135+
}
136+
}
137+
119138
impl<S: Writer> ::hash::Hash<S> for Path {
120139
#[inline]
121140
fn hash(&self, state: &mut S) {

0 commit comments

Comments
 (0)