about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonathan Reem <jonathan.reem@gmail.com>2015-07-10 00:04:06 -0700
committerJonathan Reem <jonathan.reem@gmail.com>2015-07-11 21:31:56 -0700
commit69521affbb6c177192522606d4f7f09f5c07537c (patch)
tree3cf1dc26416e4cb0d9ccb35fd5d92cec56db1ee3
parentb8bb908d8829e7834748261a61605be2523fc878 (diff)
downloadrust-69521affbb6c177192522606d4f7f09f5c07537c.tar.gz
rust-69521affbb6c177192522606d4f7f09f5c07537c.zip
Add String::into_boxed_slice and Box<str>::into_string
Implements merged RFC 1152.

Closes #26697.
-rw-r--r--src/libcollections/str.rs33
-rw-r--r--src/libcollections/string.rs11
-rw-r--r--src/libcollectionstest/lib.rs1
-rw-r--r--src/libcollectionstest/str.rs8
-rw-r--r--src/libcollectionstest/string.rs7
5 files changed, 39 insertions, 21 deletions
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 7e72ad1569a..7f86209bd2a 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -61,6 +61,7 @@ use core::result::Result;
 use core::str as core_str;
 use core::str::pattern::Pattern;
 use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
+use core::mem;
 use rustc_unicode::str::{UnicodeStr, Utf16Encoder};
 
 use vec_deque::VecDeque;
@@ -69,6 +70,7 @@ use string::String;
 use rustc_unicode;
 use vec::Vec;
 use slice::SliceConcatExt;
+use boxed::Box;
 
 pub use core::str::{FromStr, Utf8Error};
 pub use core::str::{Lines, LinesAny, CharRange};
@@ -82,10 +84,6 @@ pub use core::str::{from_utf8_unchecked, ParseBoolError};
 pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices};
 pub use core::str::pattern;
 
-/*
-Section: Creating a string
-*/
-
 impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
     type Output = String;
 
@@ -134,10 +132,6 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
     }
 }
 
-/*
-Section: Iterators
-*/
-
 // Helper functions used for Unicode normalization
 fn canonical_sort(comb: &mut [(char, u8)]) {
     let len = comb.len();
@@ -382,10 +376,6 @@ impl<'a> Iterator for Utf16Units<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) { self.encoder.size_hint() }
 }
 
-/*
-Section: Misc
-*/
-
 // Return the initial codepoint accumulator for the first byte.
 // The first byte is special, only want bottom 5 bits for width 2, 4 bits
 // for width 3, and 3 bits for width 4
@@ -414,15 +404,6 @@ impl ToOwned for str {
     }
 }
 
-/*
-Section: CowString
-*/
-
-/*
-Section: Trait implementations
-*/
-
-
 /// Any string that can be represented as a slice.
 #[lang = "str"]
 #[cfg(not(test))]
@@ -1924,4 +1905,14 @@ impl str {
     pub fn escape_unicode(&self) -> String {
         self.chars().flat_map(|c| c.escape_unicode()).collect()
     }
+
+    /// Converts the `Box<str>` into a `String` without copying or allocating.
+    #[unstable(feature = "box_str",
+               reason = "recently added, matches RFC")]
+    pub fn into_string(self: Box<str>) -> String {
+        unsafe {
+            let slice = mem::transmute::<Box<str>, Box<[u8]>>(self);
+            String::from_utf8_unchecked(slice.into_vec())
+        }
+    }
 }
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 6b20d6e2a3f..ef1d9b08b4a 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -29,6 +29,7 @@ use borrow::{Cow, IntoCow};
 use range::RangeArgument;
 use str::{self, FromStr, Utf8Error, Chars};
 use vec::{DerefVec, Vec, as_vec};
+use boxed::Box;
 
 /// A growable string stored as a UTF-8 encoded buffer.
 #[derive(Clone, PartialOrd, Eq, Ord)]
@@ -741,6 +742,16 @@ impl String {
             string: self_ptr,
         }
     }
+
+    /// Converts the string into `Box<str>`.
+    ///
+    /// Note that this will drop any excess capacity.
+    #[unstable(feature = "box_str",
+               reason = "recently added, matches RFC")]
+    pub fn into_boxed_slice(self) -> Box<str> {
+        let slice = self.vec.into_boxed_slice();
+        unsafe { mem::transmute::<Box<[u8]>, Box<str>>(slice) }
+    }
 }
 
 impl FromUtf8Error {
diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs
index ba1b4964b49..87c7449540c 100644
--- a/src/libcollectionstest/lib.rs
+++ b/src/libcollectionstest/lib.rs
@@ -44,6 +44,7 @@
 #![feature(str_escape)]
 #![feature(str_match_indices)]
 #![feature(str_utf16)]
+#![feature(box_str)]
 #![feature(subslice_offset)]
 #![feature(test)]
 #![feature(unboxed_closures)]
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 87a018ced19..4eee99f2bc9 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -1746,6 +1746,14 @@ fn to_uppercase() {
     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
 }
 
+#[test]
+fn test_into_string() {
+    // The only way to acquire a Box<str> in the first place is through a String, so just
+    // test that we can round-trip between Box<str> and String.
+    let string = String::from("Some text goes here");
+    assert_eq!(string.clone().into_boxed_slice().into_string(), string);
+}
+
 mod pattern {
     use std::str::pattern::Pattern;
     use std::str::pattern::{Searcher, ReverseSearcher};
diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs
index 257caca4016..7b69601f010 100644
--- a/src/libcollectionstest/string.rs
+++ b/src/libcollectionstest/string.rs
@@ -374,6 +374,13 @@ fn test_extend_ref() {
     assert_eq!(&a, "foobar");
 }
 
+#[test]
+fn test_into_boxed_slice() {
+    let xs = String::from("hello my name is bob");
+    let ys = xs.into_boxed_slice();
+    assert_eq!(&*ys, "hello my name is bob");
+}
+
 #[bench]
 fn bench_with_capacity(b: &mut Bencher) {
     b.iter(|| {