]> git.lizzy.rs Git - rust.git/commitdiff
Add String::into_boxed_slice and Box<str>::into_string
authorJonathan Reem <jonathan.reem@gmail.com>
Fri, 10 Jul 2015 07:04:06 +0000 (00:04 -0700)
committerJonathan Reem <jonathan.reem@gmail.com>
Sun, 12 Jul 2015 04:31:56 +0000 (21:31 -0700)
Implements merged RFC 1152.

Closes #26697.

src/libcollections/str.rs
src/libcollections/string.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/str.rs
src/libcollectionstest/string.rs

index 7e72ad1569a1f56035e69f3f702a41c91b6d4003..7f86209bd2ac9c514f5def488724cb726fb163c7 100644 (file)
@@ -61,6 +61,7 @@
 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 rustc_unicode;
 use vec::Vec;
 use slice::SliceConcatExt;
+use boxed::Box;
 
 pub use core::str::{FromStr, Utf8Error};
 pub use core::str::{Lines, LinesAny, CharRange};
 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 @@ fn connect(&self, sep: &str) -> String {
     }
 }
 
-/*
-Section: Iterators
-*/
-
 // Helper functions used for Unicode normalization
 fn canonical_sort(comb: &mut [(char, u8)]) {
     let len = comb.len();
@@ -382,10 +376,6 @@ fn next(&mut self) -> Option<u16> { self.encoder.next() }
     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 @@ fn to_owned(&self) -> String {
     }
 }
 
-/*
-Section: CowString
-*/
-
-/*
-Section: Trait implementations
-*/
-
-
 /// Any string that can be represented as a slice.
 #[lang = "str"]
 #[cfg(not(test))]
@@ -1924,4 +1905,14 @@ pub fn escape_default(&self) -> String {
     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())
+        }
+    }
 }
index 6b20d6e2a3f9b99587acdae98ef3ae69a8165439..ef1d9b08b4a9a6d4b5b5328c5529f9c71bd4db62 100644 (file)
@@ -29,6 +29,7 @@
 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 @@ pub fn drain<R>(&mut self, range: R) -> Drain where R: RangeArgument<usize> {
             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 {
index ba1b4964b49a3cc08ba20deba84202e209fd494d..87c7449540c7953a8ec8afc0364c486d77d7c5a3 100644 (file)
@@ -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)]
index 87a018ced195accee2164df7b341a5c85d1913a3..4eee99f2bc91284137d97f77499af643718bbdba 100644 (file)
@@ -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};
index 257caca4016df28e8cef0f826544a4d16649bceb..7b69601f010ba4af2435ed40410b4614a637eb2d 100644 (file)
@@ -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(|| {