Reduce str transmutes, add mut versions of methods.

This commit is contained in:
Clar Charr 2017-03-10 12:10:26 -05:00
parent fa332c9015
commit a2b28be3f8
9 changed files with 57 additions and 14 deletions

View File

@ -187,6 +187,7 @@
- [str_checked_slicing](str-checked-slicing.md)
- [str_escape](str-escape.md)
- [str_internals](str-internals.md)
- [str_mut_extras](str-mut-extras.md)
- [struct_field_attributes](struct-field-attributes.md)
- [structural_match](structural-match.md)
- [target_feature](target-feature.md)

View File

@ -0,0 +1,8 @@
# `str_mut_extras`
The tracking issue for this feature is: [#str_mut_extras]
[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119
------------------------

View File

@ -57,6 +57,7 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(str_mut_extras)]
#![feature(trusted_len)]
#![feature(unicode)]
#![feature(unique)]

View File

@ -72,7 +72,7 @@ pub use core::str::{MatchIndices, RMatchIndices};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{from_utf8_unchecked, ParseBoolError};
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::str::SplitWhitespace;
#[stable(feature = "rust1", since = "1.0.0")]
@ -294,6 +294,13 @@ impl str {
core_str::StrExt::as_bytes(self)
}
/// Converts a mutable string slice to a mutable byte slice.
#[unstable(feature = "str_mut_extras", issue = "41119")]
#[inline(always)]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
core_str::StrExt::as_bytes_mut(self)
}
/// Converts a string slice to a raw pointer.
///
/// As string slices are a slice of bytes, the raw pointer points to a

View File

@ -1790,7 +1790,7 @@ impl ops::IndexMut<ops::RangeFrom<usize>> for String {
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
unsafe { mem::transmute(&mut *self.vec) }
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@ -1822,7 +1822,7 @@ impl ops::Deref for String {
impl ops::DerefMut for String {
#[inline]
fn deref_mut(&mut self) -> &mut str {
unsafe { mem::transmute(&mut *self.vec) }
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}

View File

@ -19,6 +19,7 @@ use char_private::is_printable;
use convert::TryFrom;
use fmt::{self, Write};
use slice;
use str::from_utf8_unchecked_mut;
use iter::FusedIterator;
use mem::transmute;
@ -448,7 +449,7 @@ impl CharExt for char {
code,
dst.len())
};
transmute(slice::from_raw_parts_mut(dst.as_mut_ptr(), len))
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
}
}

View File

@ -21,8 +21,8 @@ use char;
use convert::TryFrom;
use fmt;
use iter::{Map, Cloned, FusedIterator};
use mem;
use slice::{self, SliceIndex};
use mem;
pub mod pattern;
@ -300,6 +300,13 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
Ok(unsafe { from_utf8_unchecked(v) })
}
/// Converts a mutable slice of bytes to a mutable string slice.
#[unstable(feature = "str_mut_extras", issue = "41119")]
pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
run_utf8_validation(v)?;
Ok(unsafe { from_utf8_unchecked_mut(v) })
}
/// Forms a str from a pointer and a length.
///
/// The `len` argument is the number of bytes in the string.
@ -325,7 +332,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
/// str is returned.
///
unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
from_utf8_unchecked_mut(slice::from_raw_parts_mut(p, len))
}
/// Converts a slice of bytes to a string slice without checking
@ -365,6 +372,18 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
mem::transmute(v)
}
/// Converts a slice of bytes to a string slice without checking
/// that the string contains valid UTF-8; mutable version.
///
/// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information.
///
/// [fromutf8]: fn.from_utf8_unchecked.html
#[inline(always)]
#[unstable(feature = "str_mut_extras", issue = "41119")]
pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
mem::transmute(v)
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -1474,7 +1493,6 @@ Section: Trait implementations
mod traits {
use cmp::Ordering;
use ops;
use mem;
use slice::{self, SliceIndex};
use str::eq_slice;
@ -1811,7 +1829,7 @@ mod traits {
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = self.end - self.start;
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
@ -1859,7 +1877,7 @@ mod traits {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
@ -1905,7 +1923,7 @@ mod traits {
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr().offset(self.start as isize);
let len = slice.len() - self.start;
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
@ -1998,7 +2016,7 @@ mod traits {
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
let ptr = slice.as_ptr();
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
@ -2096,6 +2114,8 @@ pub trait StrExt {
fn is_char_boundary(&self, index: usize) -> bool;
#[stable(feature = "core", since = "1.6.0")]
fn as_bytes(&self) -> &[u8];
#[unstable(feature = "str_mut_extras", issue = "0")]
unsafe fn as_bytes_mut(&mut self) -> &mut [u8];
#[stable(feature = "core", since = "1.6.0")]
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
#[stable(feature = "core", since = "1.6.0")]
@ -2373,6 +2393,11 @@ impl StrExt for str {
unsafe { mem::transmute(self) }
}
#[inline]
unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
mem::transmute(self)
}
fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
pat.into_searcher(self).next_match().map(|(i, _)| i)
}

View File

@ -27,7 +27,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use fmt;
use mem;
use ops::Range;
use iter::FusedIterator;
@ -599,12 +598,12 @@ impl AsciiExt for str {
}
fn make_ascii_uppercase(&mut self) {
let me: &mut [u8] = unsafe { mem::transmute(self) };
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_uppercase()
}
fn make_ascii_lowercase(&mut self) {
let me: &mut [u8] = unsafe { mem::transmute(self) };
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_lowercase()
}

View File

@ -296,6 +296,7 @@
#![feature(stmt_expr_attributes)]
#![feature(str_char)]
#![feature(str_internals)]
#![feature(str_mut_extras)]
#![feature(str_utf16)]
#![feature(test, rustc_private)]
#![feature(thread_local)]