diff options
| author | bors <bors@rust-lang.org> | 2014-11-23 05:46:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-11-23 05:46:52 +0000 |
| commit | 641e2a110de4bb1b2c2b596ef1168ae7865aa529 (patch) | |
| tree | e3bcf593519b1aa31df2d79373079f1ada8e0d39 /src/libcore | |
| parent | 529f8bcd8b03f1bcff46c31c682ce9274abff86d (diff) | |
| parent | 8ca27a633ed393438a12bbf074b4f2e6063baa6f (diff) | |
| download | rust-641e2a110de4bb1b2c2b596ef1168ae7865aa529.tar.gz rust-641e2a110de4bb1b2c2b596ef1168ae7865aa529.zip | |
auto merge of #19152 : alexcrichton/rust/issue-17863, r=aturon
This commit is an implementation of [RFC 240][rfc] when applied to the standard library. It primarily deprecates the entirety of `string::raw`, `vec::raw`, `slice::raw`, and `str::raw` in favor of associated functions, methods, and other free functions. The detailed renaming is: * slice::raw::buf_as_slice => slice::from_raw_buf * slice::raw::mut_buf_as_slice => slice::from_raw_mut_buf * slice::shift_ptr => deprecated with no replacement * slice::pop_ptr => deprecated with no replacement * str::raw::from_utf8 => str::from_utf8_unchecked * str::raw::c_str_to_static_slice => str::from_c_str * str::raw::slice_bytes => deprecated for slice_unchecked (slight semantic diff) * str::raw::slice_unchecked => str.slice_unchecked * string::raw::from_parts => String::from_raw_parts * string::raw::from_buf_len => String::from_raw_buf_len * string::raw::from_buf => String::from_raw_buf * string::raw::from_utf8 => String::from_utf8_unchecked * vec::raw::from_buf => Vec::from_raw_buf All previous functions exist in their `#[deprecated]` form, and the deprecation messages indicate how to migrate to the newer variants. [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0240-unsafe-api-location.md [breaking-change] Closes #17863
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/slice.rs | 50 | ||||
| -rw-r--r-- | src/libcore/str.rs | 103 |
2 files changed, 123 insertions, 30 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 7a3e06e7eb4..754da272c24 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1559,15 +1559,55 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { } } +/// Forms a slice from a pointer and a length. +/// +/// The pointer given is actually a reference to the base of the slice. This +/// reference is used to give a concrete lifetime to tie the returned slice to. +/// Typically this should indicate that the slice is valid for as long as the +/// pointer itself is valid. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// This function is unsafe as there is no guarantee that the given pointer is +/// valid for `len` elements, nor whether the lifetime provided is a suitable +/// lifetime for the returned slice. +/// +/// # Example +/// +/// ```rust +/// use std::slice; +/// +/// // manifest a slice out of thin air! +/// let ptr = 0x1234 as *const uint; +/// let amt = 10; +/// unsafe { +/// let slice = slice::from_raw_buf(&ptr, amt); +/// } +/// ``` +#[inline] +#[unstable = "just renamed from `mod raw`"] +pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { + transmute(RawSlice { data: *p, len: len }) +} - +/// Performs the same functionality as `from_raw_buf`, except that a mutable +/// slice is returned. +/// +/// This function is unsafe for the same reasons as `from_raw_buf`, as well as +/// not being able to provide a non-aliasing guarantee of the returned mutable +/// slice. +#[inline] +#[unstable = "just renamed from `mod raw`"] +pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] { + transmute(RawSlice { data: *p as *const T, len: len }) +} // // Submodules // /// Unsafe operations -#[experimental = "needs review"] +#[deprecated] pub mod raw { use mem::transmute; use ptr::RawPtr; @@ -1579,6 +1619,7 @@ pub mod raw { * not bytes). */ #[inline] + #[deprecated = "renamed to slice::from_raw_buf"] pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U) -> U { f(transmute(Slice { @@ -1592,6 +1633,7 @@ pub mod raw { * not bytes). */ #[inline] + #[deprecated = "renamed to slice::from_raw_mut_buf"] pub unsafe fn mut_buf_as_slice<T, U>( p: *mut T, @@ -1610,6 +1652,7 @@ pub mod raw { * if the slice is empty. O(1). */ #[inline] + #[deprecated = "inspect `Slice::{data, len}` manually (increment data by 1)"] pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { if slice.len == 0 { return None; } let head: *const T = slice.data; @@ -1623,7 +1666,8 @@ pub mod raw { * slice so it no longer contains that element. Returns None * if the slice is empty. O(1). */ - #[inline] + #[inline] + #[deprecated = "inspect `Slice::{data, len}` manually (decrement len by 1)"] pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { if slice.len == 0 { return None; } let tail: *const T = slice.data.offset((slice.len - 1) as int); diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 28d0dff25d2..3b2a7c62312 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -19,18 +19,19 @@ pub use self::Utf16Item::*; pub use self::Searcher::{Naive, TwoWay, TwoWayLong}; -use mem; -use char; use char::Char; +use char; use cmp::{Eq, mod}; use default::Default; -use iter::{Map, Iterator}; -use iter::{DoubleEndedIterator, ExactSize}; use iter::range; +use iter::{DoubleEndedIterator, ExactSize}; +use iter::{Map, Iterator}; use kinds::Sized; +use mem; use num::Int; use option::{Option, None, Some}; -use raw::Repr; +use ptr::RawPtr; +use raw::{Repr, Slice}; use slice::{mod, SlicePrelude}; use uint; @@ -82,8 +83,39 @@ Section: Creating a string /// Returns None if the slice is not utf-8. pub fn from_utf8<'a>(v: &'a [u8]) -> Option<&'a str> { if is_utf8(v) { - Some(unsafe { raw::from_utf8(v) }) - } else { None } + Some(unsafe { from_utf8_unchecked(v) }) + } else { + None + } +} + +/// Converts a slice of bytes to a string slice without checking +/// that the string contains valid UTF-8. +pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { + mem::transmute(v) +} + +/// Constructs a static string slice from a given raw pointer. +/// +/// This function will read memory starting at `s` until it finds a 0, and then +/// transmute the memory up to that point as a string slice, returning the +/// corresponding `&'static str` value. +/// +/// This function is unsafe because the caller must ensure the C string itself +/// has the static lifetime and that the memory `s` is valid up to and including +/// the first null byte. +/// +/// # Panics +/// +/// This function will panic if the string pointed to by `s` is not valid UTF-8. +pub unsafe fn from_c_str(s: *const i8) -> &'static str { + let s = s as *const u8; + let mut len = 0u; + while *s.offset(len as int) != 0 { + len += 1u; + } + let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len }); + from_utf8(v).expect("from_c_str passed invalid utf-8 data") } /// Something that can be used to compare against a character @@ -352,8 +384,8 @@ impl<'a, Sep: CharEq> Iterator<&'a str> for CharSplits<'a, Sep> { } match next_split { Some((a, b)) => unsafe { - let elt = raw::slice_unchecked(self.string, 0, a); - self.string = raw::slice_unchecked(self.string, b, self.string.len()); + let elt = self.string.slice_unchecked(0, a); + self.string = self.string.slice_unchecked(b, self.string.len()); Some(elt) }, None => self.get_end(), @@ -394,8 +426,8 @@ for CharSplits<'a, Sep> { } match next_split { Some((a, b)) => unsafe { - let elt = raw::slice_unchecked(self.string, b, len); - self.string = raw::slice_unchecked(self.string, 0, a); + let elt = self.string.slice_unchecked(b, len); + self.string = self.string.slice_unchecked(0, a); Some(elt) }, None => { self.finished = true; Some(self.string) } @@ -1112,8 +1144,8 @@ const CONT_MASK: u8 = 0b0011_1111u8; const TAG_CONT_U8: u8 = 0b1000_0000u8; /// Unsafe operations +#[deprecated] pub mod raw { - use mem; use ptr::RawPtr; use raw::Slice; use slice::SlicePrelude; @@ -1121,13 +1153,15 @@ pub mod raw { /// Converts a slice of bytes to a string slice without checking /// that the string contains valid UTF-8. + #[deprecated = "renamed to str::from_utf8_unchecked"] pub unsafe fn from_utf8<'a>(v: &'a [u8]) -> &'a str { - mem::transmute(v) + super::from_utf8_unchecked(v) } /// Form a slice from a C string. Unsafe because the caller must ensure the /// C string has the static lifetime, or else the return value may be /// invalidated later. + #[deprecated = "renamed to str::from_c_str"] pub unsafe fn c_str_to_static_slice(s: *const i8) -> &'static str { let s = s as *const u8; let mut curr = s; @@ -1150,10 +1184,11 @@ pub mod raw { /// If begin is greater than end. /// If end is greater than the length of the string. #[inline] + #[deprecated = "call the slice_unchecked method instead"] pub unsafe fn slice_bytes<'a>(s: &'a str, begin: uint, end: uint) -> &'a str { assert!(begin <= end); assert!(end <= s.len()); - slice_unchecked(s, begin, end) + s.slice_unchecked(begin, end) } /// Takes a bytewise (not UTF-8) slice from a string. @@ -1162,11 +1197,9 @@ pub mod raw { /// /// Caller must check slice boundaries! #[inline] + #[deprecated = "this has moved to a method on `str` directly"] pub unsafe fn slice_unchecked<'a>(s: &'a str, begin: uint, end: uint) -> &'a str { - mem::transmute(Slice { - data: s.as_ptr().offset(begin as int), - len: end - begin, - }) + s.slice_unchecked(begin, end) } } @@ -1566,6 +1599,14 @@ pub trait StrPrelude for Sized? { /// ``` fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str; + /// Takes a bytewise (not UTF-8) slice from a string. + /// + /// Returns the substring from [`begin`..`end`). + /// + /// Caller must check both UTF-8 character boundaries and the boundaries of + /// the entire slice as well. + unsafe fn slice_unchecked<'a>(&'a self, begin: uint, end: uint) -> &'a str; + /// Returns true if `needle` is a prefix of the string. /// /// # Example @@ -2012,7 +2053,7 @@ impl StrPrelude for str { if begin <= end && self.is_char_boundary(begin) && self.is_char_boundary(end) { - unsafe { raw::slice_unchecked(self, begin, end) } + unsafe { self.slice_unchecked(begin, end) } } else { slice_error_fail(self, begin, end) } @@ -2022,7 +2063,7 @@ impl StrPrelude for str { fn slice_from(&self, begin: uint) -> &str { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(begin) { - unsafe { raw::slice_unchecked(self, begin, self.len()) } + unsafe { self.slice_unchecked(begin, self.len()) } } else { slice_error_fail(self, begin, self.len()) } @@ -2032,7 +2073,7 @@ impl StrPrelude for str { fn slice_to(&self, end: uint) -> &str { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(end) { - unsafe { raw::slice_unchecked(self, 0, end) } + unsafe { self.slice_unchecked(0, end) } } else { slice_error_fail(self, 0, end) } @@ -2057,11 +2098,19 @@ impl StrPrelude for str { match (begin_byte, end_byte) { (None, _) => panic!("slice_chars: `begin` is beyond end of string"), (_, None) => panic!("slice_chars: `end` is beyond end of string"), - (Some(a), Some(b)) => unsafe { raw::slice_bytes(self, a, b) } + (Some(a), Some(b)) => unsafe { self.slice_unchecked(a, b) } } } #[inline] + unsafe fn slice_unchecked(&self, begin: uint, end: uint) -> &str { + mem::transmute(Slice { + data: self.as_ptr().offset(begin as int), + len: end - begin, + }) + } + + #[inline] fn starts_with(&self, needle: &str) -> bool { let n = needle.len(); self.len() >= n && needle.as_bytes() == self.as_bytes()[..n] @@ -2077,13 +2126,13 @@ impl StrPrelude for str { fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &str { let cur = match self.find(|c: char| !to_trim.matches(c)) { None => "", - Some(i) => unsafe { raw::slice_bytes(self, i, self.len()) } + Some(i) => unsafe { self.slice_unchecked(i, self.len()) } }; match cur.rfind(|c: char| !to_trim.matches(c)) { None => "", Some(i) => { let right = cur.char_range_at(i).next; - unsafe { raw::slice_bytes(cur, 0, right) } + unsafe { cur.slice_unchecked(0, right) } } } } @@ -2092,7 +2141,7 @@ impl StrPrelude for str { fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &str { match self.find(|c: char| !to_trim.matches(c)) { None => "", - Some(first) => unsafe { raw::slice_bytes(self, first, self.len()) } + Some(first) => unsafe { self.slice_unchecked(first, self.len()) } } } @@ -2102,7 +2151,7 @@ impl StrPrelude for str { None => "", Some(last) => { let next = self.char_range_at(last).next; - unsafe { raw::slice_bytes(self, 0u, next) } + unsafe { self.slice_unchecked(0u, next) } } } } @@ -2223,7 +2272,7 @@ impl StrPrelude for str { None } else { let CharRange {ch, next} = self.char_range_at(0u); - let next_s = unsafe { raw::slice_bytes(self, next, self.len()) }; + let next_s = unsafe { self.slice_unchecked(next, self.len()) }; Some((ch, next_s)) } } |
