Skip to content

Commit fddfd08

Browse files
committed
Auto merge of #26928 - reem:cstr-is-a-cow, r=Gankro
This allows CString and CStr to be used with the Cow type, which is extremely useful when interfacing with C libraries that make extensive use of C-style strings.
2 parents cdcce3b + 69579e4 commit fddfd08

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/libstd/ffi/c_str.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow::{Cow, ToOwned};
11+
use borrow::{Cow, ToOwned, Borrow};
1212
use boxed::Box;
1313
use clone::Clone;
1414
use convert::{Into, From};
@@ -272,6 +272,11 @@ impl fmt::Debug for CString {
272272
}
273273
}
274274

275+
#[stable(feature = "cstr_borrow", since = "1.3.0")]
276+
impl Borrow<CStr> for CString {
277+
fn borrow(&self) -> &CStr { self }
278+
}
279+
275280
impl NulError {
276281
/// Returns the position of the nul byte in the slice that was provided to
277282
/// `CString::new`.
@@ -444,6 +449,15 @@ impl Ord for CStr {
444449
}
445450
}
446451

452+
#[stable(feature = "cstr_borrow", since = "1.3.0")]
453+
impl ToOwned for CStr {
454+
type Owned = CString;
455+
456+
fn to_owned(&self) -> CString {
457+
unsafe { CString::from_vec_unchecked(self.to_bytes().to_vec()) }
458+
}
459+
}
460+
447461
#[cfg(test)]
448462
mod tests {
449463
use prelude::v1::*;
@@ -515,4 +529,28 @@ mod tests {
515529
assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::<str>(format!("123\u{FFFD}")));
516530
}
517531
}
532+
533+
#[test]
534+
fn to_owned() {
535+
let data = b"123\0";
536+
let ptr = data.as_ptr() as *const libc::c_char;
537+
538+
let owned = unsafe { CStr::from_ptr(ptr).to_owned() };
539+
assert_eq!(owned.as_bytes_with_nul(), data);
540+
}
541+
542+
#[test]
543+
fn equal_hash() {
544+
use hash;
545+
546+
let data = b"123\xE2\xFA\xA6\0";
547+
let ptr = data.as_ptr() as *const libc::c_char;
548+
let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) };
549+
550+
let cstr_hash = hash::hash::<_, hash::SipHasher>(&cstr);
551+
let cstring_hash =
552+
hash::hash::<_, hash::SipHasher>(&CString::new(&data[..data.len() - 1]).unwrap());
553+
554+
assert_eq!(cstr_hash, cstring_hash);
555+
}
518556
}

src/libstd/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
#![feature(wrapping)]
151151
#![feature(zero_one)]
152152
#![cfg_attr(windows, feature(str_utf16))]
153-
#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))]
153+
#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))]
154154
#![cfg_attr(test, feature(test, rustc_private, float_consts))]
155155
#![cfg_attr(target_env = "msvc", feature(link_args))]
156156

0 commit comments

Comments
 (0)