Auto merge of #41258 - clarcharr:str_box_extras, r=Kimundi

More methods for str boxes. (reduce Box<[u8]> ↔ Box<str> transmutes)

This is a follow-up to #41096 that adds safer methods for converting between `Box<str>` and `Box<[u8]>`. They're gated under a different feature from the `&mut str` methods because they may be too niche to include in public APIs, although having them internally helps reduce the number of transmutes the standard library uses.

What's added:

* `From<Box<str>> for Box<[u8]>`
* `<Box<str>>::into_boxed_bytes` (just calls `Into::into`)
* `alloc::str` (new module)
* `from_boxed_utf8` and `from_boxed_utf8_unchecked`, defined in `alloc:str`, exported in `collections::str`
* exports `from_utf8_mut` in `collections::str` (missed from previous PR)
This commit is contained in:
bors
2017-04-26 06:18:17 +00:00
8 changed files with 60 additions and 8 deletions

View File

@@ -68,6 +68,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
use core::ptr::{self, Unique};
use core::convert::From;
use str::from_boxed_utf8_unchecked;
/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
@@ -320,8 +321,7 @@ impl<T> Default for Box<[T]> {
#[stable(feature = "default_box_extra", since = "1.17.0")]
impl Default for Box<str> {
fn default() -> Box<str> {
let default: Box<[u8]> = Default::default();
unsafe { mem::transmute(default) }
unsafe { from_boxed_utf8_unchecked(Default::default()) }
}
}
@@ -366,7 +366,7 @@ impl Clone for Box<str> {
let buf = RawVec::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
mem::transmute(buf.into_box()) // bytes to str ~magic
from_boxed_utf8_unchecked(buf.into_box())
}
}
}
@@ -441,8 +441,16 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
#[stable(feature = "box_from_slice", since = "1.17.0")]
impl<'a> From<&'a str> for Box<str> {
fn from(s: &'a str) -> Box<str> {
let boxed: Box<[u8]> = Box::from(s.as_bytes());
unsafe { mem::transmute(boxed) }
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
}
}
#[stable(feature = "boxed_str_conv", since = "1.18.0")]
impl From<Box<str>> for Box<[u8]> {
fn from(s: Box<str>) -> Self {
unsafe {
mem::transmute(s)
}
}
}

View File

@@ -129,6 +129,8 @@ mod boxed_test;
pub mod arc;
pub mod rc;
pub mod raw_vec;
#[unstable(feature = "str_box_extras", issue = "41119")]
pub mod str;
pub mod oom;
pub use oom::oom;

21
src/liballoc/str.rs Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Methods for dealing with boxed strings.
use core::mem;
use boxed::Box;
/// Converts a boxed slice of bytes to a boxed string slice without checking
/// that the string contains valid UTF-8.
#[unstable(feature = "str_box_extras", issue = "41119")]
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
mem::transmute(v)
}