Skip to content

Commit a808ba3

Browse files
authored
Rollup merge of rust-lang#65705 - shepmaster:vec-into-raw, r=SimonSapin
Add {String,Vec}::into_raw_parts Aspects to address: - [x] Create a tracking issue - rust-lang#65816
2 parents 23f890f + 6600cf6 commit a808ba3

File tree

3 files changed

+89
-14
lines changed

3 files changed

+89
-14
lines changed

src/liballoc/string.rs

+44-9
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,21 @@ use crate::vec::Vec;
196196
///
197197
/// let story = String::from("Once upon a time...");
198198
///
199-
/// let ptr = story.as_ptr();
199+
// FIXME Update this when vec_into_raw_parts is stabilized
200+
/// // Prevent automatically dropping the String's data
201+
/// let mut story = mem::ManuallyDrop::new(story);
202+
///
203+
/// let ptr = story.as_mut_ptr();
200204
/// let len = story.len();
201205
/// let capacity = story.capacity();
202206
///
203207
/// // story has nineteen bytes
204208
/// assert_eq!(19, len);
205209
///
206-
/// // Now that we have our parts, we throw the story away.
207-
/// mem::forget(story);
208-
///
209210
/// // We can re-build a String out of ptr, len, and capacity. This is all
210211
/// // unsafe because we are responsible for making sure the components are
211212
/// // valid:
212-
/// let s = unsafe { String::from_raw_parts(ptr as *mut _, len, capacity) } ;
213+
/// let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ;
213214
///
214215
/// assert_eq!(String::from("Once upon a time..."), s);
215216
/// ```
@@ -647,6 +648,37 @@ impl String {
647648
decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect()
648649
}
649650

651+
/// Decomposes a `String` into its raw components.
652+
///
653+
/// Returns the raw pointer to the underlying data, the length of
654+
/// the string (in bytes), and the allocated capacity of the data
655+
/// (in bytes). These are the same arguments in the same order as
656+
/// the arguments to [`from_raw_parts`].
657+
///
658+
/// After calling this function, the caller is responsible for the
659+
/// memory previously managed by the `String`. The only way to do
660+
/// this is to convert the raw pointer, length, and capacity back
661+
/// into a `String` with the [`from_raw_parts`] function, allowing
662+
/// the destructor to perform the cleanup.
663+
///
664+
/// [`from_raw_parts`]: #method.from_raw_parts
665+
///
666+
/// # Examples
667+
///
668+
/// ```
669+
/// #![feature(vec_into_raw_parts)]
670+
/// let s = String::from("hello");
671+
///
672+
/// let (ptr, len, cap) = s.into_raw_parts();
673+
///
674+
/// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };
675+
/// assert_eq!(rebuilt, "hello");
676+
/// ```
677+
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
678+
pub fn into_raw_parts(self) -> (*mut u8, usize, usize) {
679+
self.vec.into_raw_parts()
680+
}
681+
650682
/// Creates a new `String` from a length, capacity, and pointer.
651683
///
652684
/// # Safety
@@ -677,13 +709,16 @@ impl String {
677709
///
678710
/// unsafe {
679711
/// let s = String::from("hello");
680-
/// let ptr = s.as_ptr();
712+
///
713+
// FIXME Update this when vec_into_raw_parts is stabilized
714+
/// // Prevent automatically dropping the String's data
715+
/// let mut s = mem::ManuallyDrop::new(s);
716+
///
717+
/// let ptr = s.as_mut_ptr();
681718
/// let len = s.len();
682719
/// let capacity = s.capacity();
683720
///
684-
/// mem::forget(s);
685-
///
686-
/// let s = String::from_raw_parts(ptr as *mut _, len, capacity);
721+
/// let s = String::from_raw_parts(ptr, len, capacity);
687722
///
688723
/// assert_eq!(String::from("hello"), s);
689724
/// }

src/liballoc/vec.rs

+44-5
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,44 @@ impl<T> Vec<T> {
358358
}
359359
}
360360

361+
/// Decomposes a `Vec<T>` into its raw components.
362+
///
363+
/// Returns the raw pointer to the underlying data, the length of
364+
/// the vector (in elements), and the allocated capacity of the
365+
/// data (in elements). These are the same arguments in the same
366+
/// order as the arguments to [`from_raw_parts`].
367+
///
368+
/// After calling this function, the caller is responsible for the
369+
/// memory previously managed by the `Vec`. The only way to do
370+
/// this is to convert the raw pointer, length, and capacity back
371+
/// into a `Vec` with the [`from_raw_parts`] function, allowing
372+
/// the destructor to perform the cleanup.
373+
///
374+
/// [`from_raw_parts`]: #method.from_raw_parts
375+
///
376+
/// # Examples
377+
///
378+
/// ```
379+
/// #![feature(vec_into_raw_parts)]
380+
/// let v: Vec<i32> = vec![-1, 0, 1];
381+
///
382+
/// let (ptr, len, cap) = v.into_raw_parts();
383+
///
384+
/// let rebuilt = unsafe {
385+
/// // We can now make changes to the components, such as
386+
/// // transmuting the raw pointer to a compatible type.
387+
/// let ptr = ptr as *mut u32;
388+
///
389+
/// Vec::from_raw_parts(ptr, len, cap)
390+
/// };
391+
/// assert_eq!(rebuilt, [4294967295, 0, 1]);
392+
/// ```
393+
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
394+
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
395+
let mut me = mem::ManuallyDrop::new(self);
396+
(me.as_mut_ptr(), me.len(), me.capacity())
397+
}
398+
361399
/// Creates a `Vec<T>` directly from the raw components of another vector.
362400
///
363401
/// # Safety
@@ -389,18 +427,19 @@ impl<T> Vec<T> {
389427
/// use std::ptr;
390428
/// use std::mem;
391429
///
392-
/// let mut v = vec![1, 2, 3];
430+
/// let v = vec![1, 2, 3];
431+
///
432+
// FIXME Update this when vec_into_raw_parts is stabilized
433+
/// // Prevent running `v`'s destructor so we are in complete control
434+
/// // of the allocation.
435+
/// let mut v = mem::ManuallyDrop::new(v);
393436
///
394437
/// // Pull out the various important pieces of information about `v`
395438
/// let p = v.as_mut_ptr();
396439
/// let len = v.len();
397440
/// let cap = v.capacity();
398441
///
399442
/// unsafe {
400-
/// // Cast `v` into the void: no destructor run, so we are in
401-
/// // complete control of the allocation to which `p` points.
402-
/// mem::forget(v);
403-
///
404443
/// // Overwrite memory with 4, 5, 6
405444
/// for i in 0..len as isize {
406445
/// ptr::write(p.offset(i), 4 + i);

src/libcore/intrinsics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,7 @@ extern "rust-intrinsic" {
874874
/// // the original inner type (`&i32`) to the converted inner type
875875
/// // (`Option<&i32>`), so read the nomicon pages linked above.
876876
/// let v_from_raw = unsafe {
877+
// FIXME Update this when vec_into_raw_parts is stabilized
877878
/// // Ensure the original vector is not dropped.
878879
/// let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
879880
/// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,

0 commit comments

Comments
 (0)