Skip to content

std: Align raw modules with unsafe conventions #19152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 23, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub use core::slice::{OrdSlicePrelude, SlicePrelude, Items, MutItems};
pub use core::slice::{ImmutableIntSlice, MutableIntSlice};
pub use core::slice::{MutSplits, MutChunks, Splits};
pub use core::slice::{bytes, mut_ref_slice, ref_slice, CloneSlicePrelude};
pub use core::slice::{Found, NotFound};
pub use core::slice::{Found, NotFound, from_raw_buf, from_raw_mut_buf};

// Functional utilities

Expand Down
16 changes: 4 additions & 12 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items};
pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange};
pub use core::str::{FromStr, from_str};
pub use core::str::{Str, StrPrelude};
pub use core::str::{from_utf8_unchecked, from_c_str};
pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices};

// FIXME(conventions): ensure bit/char conventions are followed by str's API
Expand Down Expand Up @@ -392,11 +393,11 @@ pub fn replace(s: &str, from: &str, to: &str) -> String {
let mut result = String::new();
let mut last_end = 0;
for (start, end) in s.match_indices(from) {
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
result.push_str(unsafe { s.slice_unchecked(last_end, start) });
result.push_str(to);
last_end = end;
}
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
result.push_str(unsafe { s.slice_unchecked(last_end, s.len()) });
result
}

Expand Down Expand Up @@ -669,16 +670,7 @@ pub trait StrAllocating: Str {
/// assert_eq!(s.replace("cookie monster", "little lamb"), s);
/// ```
fn replace(&self, from: &str, to: &str) -> String {
let me = self.as_slice();
let mut result = String::new();
let mut last_end = 0;
for (start, end) in me.match_indices(from) {
result.push_str(unsafe{raw::slice_bytes(me, last_end, start)});
result.push_str(to);
last_end = end;
}
result.push_str(unsafe{raw::slice_bytes(me, last_end, me.len())});
result
replace(self.as_slice(), from, to)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I would've thought we'd deprecate the free replace fn in favor of this method.

}

/// Given a string, makes a new string with repeated copies of it.
Expand Down
76 changes: 56 additions & 20 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,52 @@ impl String {
chs.iter().map(|c| *c).collect()
}

/// Creates a new `String` from a length, capacity, and pointer.
///
/// This is unsafe because:
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
/// * We assume that the `Vec` contains valid UTF-8.
#[inline]
#[unstable = "function just moved from string::raw"]
pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
vec: Vec::from_raw_parts(buf, length, capacity),
}
}

/// Creates a `String` from a null-terminated `*const u8` buffer.
///
/// This function is unsafe because we dereference memory until we find the
/// NUL character, which is not guaranteed to be present. Additionally, the
/// slice is not checked to see whether it contains valid UTF-8
#[unstable = "just renamed from `mod raw`"]
pub unsafe fn from_raw_buf(buf: *const u8) -> String {
String::from_str(str::from_c_str(buf as *const i8))
}

/// Creates a `String` from a `*const u8` buffer of the given length.
///
/// This function is unsafe because it blindly assumes the validity of the
/// pointer `buf` for `len` bytes of memory. This function will copy the
/// memory from `buf` into a new allocation (owned by the returned
/// `String`).
///
/// This function is also unsafe because it does not validate that the
/// buffer is valid UTF-8 encoded data.
#[unstable = "just renamed from `mod raw`"]
pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
}

/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
#[inline]
#[unstable = "awaiting stabilization"]
pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
String { vec: bytes }
}

/// Return the underlying byte buffer, encoded as UTF-8.
///
/// # Example
Expand Down Expand Up @@ -823,12 +869,8 @@ impl<T: fmt::Show> ToString for T {
}

/// Unsafe operations
#[unstable = "waiting on raw module conventions"]
#[deprecated]
pub mod raw {
use core::mem;
use core::ptr::RawPtr;
use core::raw::Slice;

use super::String;
use vec::Vec;

Expand All @@ -838,45 +880,39 @@ pub mod raw {
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
/// * We assume that the `Vec` contains valid UTF-8.
#[inline]
#[deprecated = "renamed to String::from_raw_parts"]
pub unsafe fn from_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
vec: Vec::from_raw_parts(buf, length, capacity),
}
String::from_raw_parts(buf, length, capacity)
}

/// Creates a `String` from a `*const u8` buffer of the given length.
///
/// This function is unsafe because of two reasons:
///
/// * A raw pointer is dereferenced and transmuted to `&[u8]`;
/// * The slice is not checked to see whether it contains valid UTF-8.
#[deprecated = "renamed to String::from_raw_buf_len"]
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String {
use slice::CloneSliceAllocPrelude;
let slice: &[u8] = mem::transmute(Slice {
data: buf,
len: len,
});
self::from_utf8(slice.to_vec())
String::from_raw_buf_len(buf, len)
}

/// Creates a `String` from a null-terminated `*const u8` buffer.
///
/// This function is unsafe because we dereference memory until we find the NUL character,
/// which is not guaranteed to be present. Additionally, the slice is not checked to see
/// whether it contains valid UTF-8
#[deprecated = "renamed to String::from_raw_buf"]
pub unsafe fn from_buf(buf: *const u8) -> String {
let mut len = 0;
while *buf.offset(len) != 0 {
len += 1;
}
self::from_buf_len(buf, len as uint)
String::from_raw_buf(buf)
}

/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
#[inline]
#[deprecated = "renamed to String::from_utf8_unchecked"]
pub unsafe fn from_utf8(bytes: Vec<u8>) -> String {
String { vec: bytes }
String::from_utf8_unchecked(bytes)
}
}

Expand Down
28 changes: 19 additions & 9 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,27 @@ impl<T> Vec<T> {
/// }
/// }
/// ```
#[experimental]
#[unstable = "needs finalization"]
pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
capacity: uint) -> Vec<T> {
Vec { ptr: ptr, len: length, cap: capacity }
}

/// Creates a vector by copying the elements from a raw pointer.
///
/// This function will copy `elts` contiguous elements starting at `ptr`
/// into a new allocation owned by the returned `Vec`. The elements of the
/// buffer are copied into the vector without cloning, as if `ptr::read()`
/// were called on them.
#[inline]
#[unstable = "just renamed from raw::from_buf"]
pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec<T> {
let mut dst = Vec::with_capacity(elts);
dst.set_len(elts);
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
dst
}

/// Consumes the `Vec`, partitioning it based on a predicate.
///
/// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
Expand Down Expand Up @@ -1366,23 +1381,18 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
}

/// Unsafe vector operations.
#[unstable]
#[deprecated]
pub mod raw {
use super::Vec;
use core::ptr;
use core::slice::SlicePrelude;

/// Constructs a vector from an unsafe pointer to a buffer.
///
/// The elements of the buffer are copied into the vector without cloning,
/// as if `ptr::read()` were called on them.
#[inline]
#[unstable]
#[deprecated = "renamed to Vec::from_raw_buf"]
pub unsafe fn from_buf<T>(ptr: *const T, elts: uint) -> Vec<T> {
let mut dst = Vec::with_capacity(elts);
dst.set_len(elts);
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
dst
Vec::from_raw_buf(ptr, elts)
}
}

Expand Down
50 changes: 47 additions & 3 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1547,15 +1547,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] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm reasonably happy with this design; it's pragmatic.

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;
Expand All @@ -1567,6 +1607,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 {
Expand All @@ -1580,6 +1621,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,
Expand All @@ -1598,6 +1640,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;
Expand All @@ -1611,7 +1654,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);
Expand Down
Loading