]> git.lizzy.rs Git - rust.git/commitdiff
Add {String,Vec}::into_raw_parts
authorJake Goulding <jake.goulding@gmail.com>
Tue, 22 Oct 2019 16:48:52 +0000 (12:48 -0400)
committerJake Goulding <jake.goulding@gmail.com>
Fri, 25 Oct 2019 15:25:52 +0000 (11:25 -0400)
src/liballoc/string.rs
src/liballoc/vec.rs
src/libcore/intrinsics.rs

index 1d0faeccecf1d9150c74aaf183f4e37b52d626f0..d9927c642b2d8528cc012de950ace36fdbcdafa6 100644 (file)
 ///
 /// let story = String::from("Once upon a time...");
 ///
+// FIXME Update this when vec_into_raw_parts is stabilized
 /// // Prevent automatically dropping the String's data
 /// let mut story = mem::ManuallyDrop::new(story);
 ///
@@ -647,6 +648,37 @@ pub fn from_utf16_lossy(v: &[u16]) -> String {
         decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect()
     }
 
+    /// Decomposes a `String` into its raw components.
+    ///
+    /// Returns the raw pointer to the underlying data, the length of
+    /// the string (in bytes), and the allocated capacity of the data
+    /// (in bytes). These are the same arguments in the same order as
+    /// the arguments to [`from_raw_parts`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `String`. The only way to do
+    /// this is to convert the raw pointer, length, and capacity back
+    /// into a `String` with the [`from_raw_parts`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_raw_parts`]: #method.from_raw_parts
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_into_raw_parts)]
+    /// let s = String::from("hello");
+    ///
+    /// let (ptr, len, cap) = s.into_raw_parts();
+    ///
+    /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };
+    /// assert_eq!(rebuilt, "hello");
+    /// ```
+    #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_raw_parts(self) -> (*mut u8, usize, usize) {
+        self.vec.into_raw_parts()
+    }
+
     /// Creates a new `String` from a length, capacity, and pointer.
     ///
     /// # Safety
@@ -678,6 +710,7 @@ pub fn from_utf16_lossy(v: &[u16]) -> String {
     /// unsafe {
     ///     let s = String::from("hello");
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     ///     // Prevent automatically dropping the String's data
     ///     let mut s = mem::ManuallyDrop::new(s);
     ///
index c8fb897123475c82ee4467a0176f825630121856..641f9eafa8d23fa55a047204cac29b989d544880 100644 (file)
@@ -358,6 +358,44 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
         }
     }
 
+    /// Decomposes a `Vec<T>` into its raw components.
+    ///
+    /// Returns the raw pointer to the underlying data, the length of
+    /// the vector (in elements), and the allocated capacity of the
+    /// data (in elements). These are the same arguments in the same
+    /// order as the arguments to [`from_raw_parts`].
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `Vec`. The only way to do
+    /// this is to convert the raw pointer, length, and capacity back
+    /// into a `Vec` with the [`from_raw_parts`] function, allowing
+    /// the destructor to perform the cleanup.
+    ///
+    /// [`from_raw_parts`]: #method.from_raw_parts
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_into_raw_parts)]
+    /// let v: Vec<i32> = vec![-1, 0, 1];
+    ///
+    /// let (ptr, len, cap) = v.into_raw_parts();
+    ///
+    /// let rebuilt = unsafe {
+    ///     // We can now make changes to the components, such as
+    ///     // transmuting the raw pointer to a compatible type.
+    ///     let ptr = ptr as *mut u32;
+    ///
+    ///     Vec::from_raw_parts(ptr, len, cap)
+    /// };
+    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
+    /// ```
+    #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
+    pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
+        let mut me = mem::ManuallyDrop::new(self);
+        (me.as_mut_ptr(), me.len(), me.capacity())
+    }
+
     /// Creates a `Vec<T>` directly from the raw components of another vector.
     ///
     /// # Safety
@@ -391,6 +429,7 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
     ///
     /// let v = vec![1, 2, 3];
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
     /// // of the allocation.
     /// let mut v = mem::ManuallyDrop::new(v);
index b240d059114eb7e67bdf65efde9f8f498bd960d4..4655d39fb8f1fd187bf1222e7a21163014eeb53f 100644 (file)
     /// // the original inner type (`&i32`) to the converted inner type
     /// // (`Option<&i32>`), so read the nomicon pages linked above.
     /// let v_from_raw = unsafe {
+    // FIXME Update this when vec_into_raw_parts is stabilized
     ///     // Ensure the original vector is not dropped.
     ///     let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
     ///     Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,