Skip to content

Commit

Permalink
Add String::into_boxed_slice and Box<str>::into_string
Browse files Browse the repository at this point in the history
Implements merged RFC 1152.

Closes #26697.
  • Loading branch information
reem committed Jul 12, 2015
1 parent b8bb908 commit 69521af
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 21 deletions.
33 changes: 12 additions & 21 deletions src/libcollections/str.rs
Expand Up @@ -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;
Expand All @@ -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};
Expand All @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))]
Expand Down Expand Up @@ -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())
}
}
}
11 changes: 11 additions & 0 deletions src/libcollections/string.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/libcollectionstest/lib.rs
Expand Up @@ -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)]
Expand Down
8 changes: 8 additions & 0 deletions src/libcollectionstest/str.rs
Expand Up @@ -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};
Expand Down
7 changes: 7 additions & 0 deletions src/libcollectionstest/string.rs
Expand Up @@ -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(|| {
Expand Down

0 comments on commit 69521af

Please sign in to comment.