Skip to content

Commit

Permalink
Reduce str transmutes, add mut versions of methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
clarfonthey committed Apr 9, 2017
1 parent fa332c9 commit a2b28be
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions src/doc/unstable-book/src/str-mut-extras.md
@@ -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

------------------------

1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Expand Up @@ -57,6 +57,7 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(str_mut_extras)]
#![feature(trusted_len)]
#![feature(unicode)]
#![feature(unique)]
Expand Down
9 changes: 8 additions & 1 deletion src/libcollections/str.rs
Expand Up @@ -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")]
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/string.rs
Expand Up @@ -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")]
Expand Down Expand Up @@ -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) }
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/libcore/char.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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))
}
}

Expand Down
39 changes: 32 additions & 7 deletions src/libcore/str/mod.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -1474,7 +1493,6 @@ Section: Trait implementations
mod traits {
use cmp::Ordering;
use ops;
use mem;
use slice::{self, SliceIndex};
use str::eq_slice;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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)
}
Expand Down
5 changes: 2 additions & 3 deletions src/libstd/ascii.rs
Expand Up @@ -27,7 +27,6 @@
#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use mem;
use ops::Range;
use iter::FusedIterator;

Expand Down Expand Up @@ -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()
}

Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Expand Up @@ -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)]
Expand Down

0 comments on commit a2b28be

Please sign in to comment.