Skip to content

Commit 8ca27a6

Browse files
committed
std: Align raw modules with unsafe conventions
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::with_raw_buf * slice::raw::mut_buf_as_slice => slice::with_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
1 parent 399ff25 commit 8ca27a6

File tree

15 files changed

+304
-208
lines changed

15 files changed

+304
-208
lines changed

src/libcollections/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub use core::slice::{OrdSlicePrelude, SlicePrelude, Items, MutItems};
106106
pub use core::slice::{ImmutableIntSlice, MutableIntSlice};
107107
pub use core::slice::{MutSplits, MutChunks, Splits};
108108
pub use core::slice::{bytes, mut_ref_slice, ref_slice, CloneSlicePrelude};
109-
pub use core::slice::{Found, NotFound};
109+
pub use core::slice::{Found, NotFound, from_raw_buf, from_raw_mut_buf};
110110

111111
// Functional utilities
112112

src/libcollections/str.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items};
7979
pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange};
8080
pub use core::str::{FromStr, from_str};
8181
pub use core::str::{Str, StrPrelude};
82+
pub use core::str::{from_utf8_unchecked, from_c_str};
8283
pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices};
8384

8485
// FIXME(conventions): ensure bit/char conventions are followed by str's API
@@ -392,11 +393,11 @@ pub fn replace(s: &str, from: &str, to: &str) -> String {
392393
let mut result = String::new();
393394
let mut last_end = 0;
394395
for (start, end) in s.match_indices(from) {
395-
result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
396+
result.push_str(unsafe { s.slice_unchecked(last_end, start) });
396397
result.push_str(to);
397398
last_end = end;
398399
}
399-
result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
400+
result.push_str(unsafe { s.slice_unchecked(last_end, s.len()) });
400401
result
401402
}
402403

@@ -669,16 +670,7 @@ pub trait StrAllocating: Str {
669670
/// assert_eq!(s.replace("cookie monster", "little lamb"), s);
670671
/// ```
671672
fn replace(&self, from: &str, to: &str) -> String {
672-
let me = self.as_slice();
673-
let mut result = String::new();
674-
let mut last_end = 0;
675-
for (start, end) in me.match_indices(from) {
676-
result.push_str(unsafe{raw::slice_bytes(me, last_end, start)});
677-
result.push_str(to);
678-
last_end = end;
679-
}
680-
result.push_str(unsafe{raw::slice_bytes(me, last_end, me.len())});
681-
result
673+
replace(self.as_slice(), from, to)
682674
}
683675

684676
/// Given a string, makes a new string with repeated copies of it.

src/libcollections/string.rs

+56-20
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,52 @@ impl String {
297297
chs.iter().map(|c| *c).collect()
298298
}
299299

300+
/// Creates a new `String` from a length, capacity, and pointer.
301+
///
302+
/// This is unsafe because:
303+
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
304+
/// * We assume that the `Vec` contains valid UTF-8.
305+
#[inline]
306+
#[unstable = "function just moved from string::raw"]
307+
pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
308+
String {
309+
vec: Vec::from_raw_parts(buf, length, capacity),
310+
}
311+
}
312+
313+
/// Creates a `String` from a null-terminated `*const u8` buffer.
314+
///
315+
/// This function is unsafe because we dereference memory until we find the
316+
/// NUL character, which is not guaranteed to be present. Additionally, the
317+
/// slice is not checked to see whether it contains valid UTF-8
318+
#[unstable = "just renamed from `mod raw`"]
319+
pub unsafe fn from_raw_buf(buf: *const u8) -> String {
320+
String::from_str(str::from_c_str(buf as *const i8))
321+
}
322+
323+
/// Creates a `String` from a `*const u8` buffer of the given length.
324+
///
325+
/// This function is unsafe because it blindly assumes the validity of the
326+
/// pointer `buf` for `len` bytes of memory. This function will copy the
327+
/// memory from `buf` into a new allocation (owned by the returned
328+
/// `String`).
329+
///
330+
/// This function is also unsafe because it does not validate that the
331+
/// buffer is valid UTF-8 encoded data.
332+
#[unstable = "just renamed from `mod raw`"]
333+
pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
334+
String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
335+
}
336+
337+
/// Converts a vector of bytes to a new `String` without checking if
338+
/// it contains valid UTF-8. This is unsafe because it assumes that
339+
/// the UTF-8-ness of the vector has already been validated.
340+
#[inline]
341+
#[unstable = "awaiting stabilization"]
342+
pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
343+
String { vec: bytes }
344+
}
345+
300346
/// Return the underlying byte buffer, encoded as UTF-8.
301347
///
302348
/// # Example
@@ -823,12 +869,8 @@ impl<T: fmt::Show> ToString for T {
823869
}
824870

825871
/// Unsafe operations
826-
#[unstable = "waiting on raw module conventions"]
872+
#[deprecated]
827873
pub mod raw {
828-
use core::mem;
829-
use core::ptr::RawPtr;
830-
use core::raw::Slice;
831-
832874
use super::String;
833875
use vec::Vec;
834876

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

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

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

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

src/libcollections/vec.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,27 @@ impl<T> Vec<T> {
234234
/// }
235235
/// }
236236
/// ```
237-
#[experimental]
237+
#[unstable = "needs finalization"]
238238
pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
239239
capacity: uint) -> Vec<T> {
240240
Vec { ptr: ptr, len: length, cap: capacity }
241241
}
242242

243+
/// Creates a vector by copying the elements from a raw pointer.
244+
///
245+
/// This function will copy `elts` contiguous elements starting at `ptr`
246+
/// into a new allocation owned by the returned `Vec`. The elements of the
247+
/// buffer are copied into the vector without cloning, as if `ptr::read()`
248+
/// were called on them.
249+
#[inline]
250+
#[unstable = "just renamed from raw::from_buf"]
251+
pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec<T> {
252+
let mut dst = Vec::with_capacity(elts);
253+
dst.set_len(elts);
254+
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
255+
dst
256+
}
257+
243258
/// Consumes the `Vec`, partitioning it based on a predicate.
244259
///
245260
/// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
@@ -1366,23 +1381,18 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
13661381
}
13671382

13681383
/// Unsafe vector operations.
1369-
#[unstable]
1384+
#[deprecated]
13701385
pub mod raw {
13711386
use super::Vec;
1372-
use core::ptr;
1373-
use core::slice::SlicePrelude;
13741387

13751388
/// Constructs a vector from an unsafe pointer to a buffer.
13761389
///
13771390
/// The elements of the buffer are copied into the vector without cloning,
13781391
/// as if `ptr::read()` were called on them.
13791392
#[inline]
1380-
#[unstable]
1393+
#[deprecated = "renamed to Vec::from_raw_buf"]
13811394
pub unsafe fn from_buf<T>(ptr: *const T, elts: uint) -> Vec<T> {
1382-
let mut dst = Vec::with_capacity(elts);
1383-
dst.set_len(elts);
1384-
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
1385-
dst
1395+
Vec::from_raw_buf(ptr, elts)
13861396
}
13871397
}
13881398

src/libcore/slice.rs

+47-3
Original file line numberDiff line numberDiff line change
@@ -1547,15 +1547,55 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
15471547
}
15481548
}
15491549

1550+
/// Forms a slice from a pointer and a length.
1551+
///
1552+
/// The pointer given is actually a reference to the base of the slice. This
1553+
/// reference is used to give a concrete lifetime to tie the returned slice to.
1554+
/// Typically this should indicate that the slice is valid for as long as the
1555+
/// pointer itself is valid.
1556+
///
1557+
/// The `len` argument is the number of **elements**, not the number of bytes.
1558+
///
1559+
/// This function is unsafe as there is no guarantee that the given pointer is
1560+
/// valid for `len` elements, nor whether the lifetime provided is a suitable
1561+
/// lifetime for the returned slice.
1562+
///
1563+
/// # Example
1564+
///
1565+
/// ```rust
1566+
/// use std::slice;
1567+
///
1568+
/// // manifest a slice out of thin air!
1569+
/// let ptr = 0x1234 as *const uint;
1570+
/// let amt = 10;
1571+
/// unsafe {
1572+
/// let slice = slice::from_raw_buf(&ptr, amt);
1573+
/// }
1574+
/// ```
1575+
#[inline]
1576+
#[unstable = "just renamed from `mod raw`"]
1577+
pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
1578+
transmute(RawSlice { data: *p, len: len })
1579+
}
15501580

1551-
1581+
/// Performs the same functionality as `from_raw_buf`, except that a mutable
1582+
/// slice is returned.
1583+
///
1584+
/// This function is unsafe for the same reasons as `from_raw_buf`, as well as
1585+
/// not being able to provide a non-aliasing guarantee of the returned mutable
1586+
/// slice.
1587+
#[inline]
1588+
#[unstable = "just renamed from `mod raw`"]
1589+
pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
1590+
transmute(RawSlice { data: *p as *const T, len: len })
1591+
}
15521592

15531593
//
15541594
// Submodules
15551595
//
15561596

15571597
/// Unsafe operations
1558-
#[experimental = "needs review"]
1598+
#[deprecated]
15591599
pub mod raw {
15601600
use mem::transmute;
15611601
use ptr::RawPtr;
@@ -1567,6 +1607,7 @@ pub mod raw {
15671607
* not bytes).
15681608
*/
15691609
#[inline]
1610+
#[deprecated = "renamed to slice::from_raw_buf"]
15701611
pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U)
15711612
-> U {
15721613
f(transmute(Slice {
@@ -1580,6 +1621,7 @@ pub mod raw {
15801621
* not bytes).
15811622
*/
15821623
#[inline]
1624+
#[deprecated = "renamed to slice::from_raw_mut_buf"]
15831625
pub unsafe fn mut_buf_as_slice<T,
15841626
U>(
15851627
p: *mut T,
@@ -1598,6 +1640,7 @@ pub mod raw {
15981640
* if the slice is empty. O(1).
15991641
*/
16001642
#[inline]
1643+
#[deprecated = "inspect `Slice::{data, len}` manually (increment data by 1)"]
16011644
pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
16021645
if slice.len == 0 { return None; }
16031646
let head: *const T = slice.data;
@@ -1611,7 +1654,8 @@ pub mod raw {
16111654
* slice so it no longer contains that element. Returns None
16121655
* if the slice is empty. O(1).
16131656
*/
1614-
#[inline]
1657+
#[inline]
1658+
#[deprecated = "inspect `Slice::{data, len}` manually (decrement len by 1)"]
16151659
pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> {
16161660
if slice.len == 0 { return None; }
16171661
let tail: *const T = slice.data.offset((slice.len - 1) as int);

0 commit comments

Comments
 (0)