From 69521affbb6c177192522606d4f7f09f5c07537c Mon Sep 17 00:00:00 2001 From: Jonathan Reem Date: Fri, 10 Jul 2015 00:04:06 -0700 Subject: [PATCH] Add String::into_boxed_slice and Box::into_string Implements merged RFC 1152. Closes #26697. --- src/libcollections/str.rs | 33 ++++++++++++-------------------- src/libcollections/string.rs | 11 +++++++++++ src/libcollectionstest/lib.rs | 1 + src/libcollectionstest/str.rs | 8 ++++++++ src/libcollectionstest/string.rs | 7 +++++++ 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 7e72ad1569a1f..7f86209bd2ac9 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> SliceConcatExt for [S] { type Output = String; @@ -134,10 +132,6 @@ impl> SliceConcatExt 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) { 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` into a `String` without copying or allocating. + #[unstable(feature = "box_str", + reason = "recently added, matches RFC")] + pub fn into_string(self: Box) -> String { + unsafe { + let slice = mem::transmute::, Box<[u8]>>(self); + String::from_utf8_unchecked(slice.into_vec()) + } + } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 6b20d6e2a3f9b..ef1d9b08b4a9a 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`. + /// + /// Note that this will drop any excess capacity. + #[unstable(feature = "box_str", + reason = "recently added, matches RFC")] + pub fn into_boxed_slice(self) -> Box { + let slice = self.vec.into_boxed_slice(); + unsafe { mem::transmute::, Box>(slice) } + } } impl FromUtf8Error { diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index ba1b4964b49a3..87c7449540c79 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 87a018ced195a..4eee99f2bc912 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 in the first place is through a String, so just + // test that we can round-trip between Box 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 257caca4016df..7b69601f010ba 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(|| {