about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-11-23 05:46:52 +0000
committerbors <bors@rust-lang.org>2014-11-23 05:46:52 +0000
commit641e2a110de4bb1b2c2b596ef1168ae7865aa529 (patch)
treee3bcf593519b1aa31df2d79373079f1ada8e0d39 /src/libcore
parent529f8bcd8b03f1bcff46c31c682ce9274abff86d (diff)
parent8ca27a633ed393438a12bbf074b4f2e6063baa6f (diff)
downloadrust-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.rs50
-rw-r--r--src/libcore/str.rs103
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))
         }
     }