about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-10 14:52:48 +0000
committerbors <bors@rust-lang.org>2015-07-10 14:52:48 +0000
commitfddfd089b75379f1d25f81541572d69a93f95c4f (patch)
tree0c5bb22a9600f6b62e96e7e1ef60f1f1a846237b
parentcdcce3ba4491436e6603833cee19533003993117 (diff)
parent69579e4d37849fe64cbdfc7e40dc614af802704d (diff)
downloadrust-fddfd089b75379f1d25f81541572d69a93f95c4f.tar.gz
rust-fddfd089b75379f1d25f81541572d69a93f95c4f.zip
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.
-rw-r--r--src/libstd/ffi/c_str.rs40
-rw-r--r--src/libstd/lib.rs2
2 files changed, 40 insertions, 2 deletions
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index ffc204ada60..f13c10156f5 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow::{Cow, ToOwned};
+use borrow::{Cow, ToOwned, Borrow};
 use boxed::Box;
 use clone::Clone;
 use convert::{Into, From};
@@ -272,6 +272,11 @@ impl fmt::Debug for CString {
     }
 }
 
+#[stable(feature = "cstr_borrow", since = "1.3.0")]
+impl Borrow<CStr> for CString {
+    fn borrow(&self) -> &CStr { self }
+}
+
 impl NulError {
     /// Returns the position of the nul byte in the slice that was provided to
     /// `CString::new`.
@@ -444,6 +449,15 @@ impl Ord for CStr {
     }
 }
 
+#[stable(feature = "cstr_borrow", since = "1.3.0")]
+impl ToOwned for CStr {
+    type Owned = CString;
+
+    fn to_owned(&self) -> CString {
+        unsafe { CString::from_vec_unchecked(self.to_bytes().to_vec()) }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
@@ -515,4 +529,28 @@ mod tests {
             assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::<str>(format!("123\u{FFFD}")));
         }
     }
+
+    #[test]
+    fn to_owned() {
+        let data = b"123\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+
+        let owned = unsafe { CStr::from_ptr(ptr).to_owned() };
+        assert_eq!(owned.as_bytes_with_nul(), data);
+    }
+
+    #[test]
+    fn equal_hash() {
+        use hash;
+
+        let data = b"123\xE2\xFA\xA6\0";
+        let ptr = data.as_ptr() as *const libc::c_char;
+        let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) };
+
+        let cstr_hash = hash::hash::<_, hash::SipHasher>(&cstr);
+        let cstring_hash =
+            hash::hash::<_, hash::SipHasher>(&CString::new(&data[..data.len() - 1]).unwrap());
+
+        assert_eq!(cstr_hash, cstring_hash);
+    }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index caf3f497e10..1e82a03f286 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -150,7 +150,7 @@
 #![feature(wrapping)]
 #![feature(zero_one)]
 #![cfg_attr(windows, feature(str_utf16))]
-#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))]
+#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))]
 #![cfg_attr(test, feature(test, rustc_private, float_consts))]
 #![cfg_attr(target_env = "msvc", feature(link_args))]