raw_parts/
lib.rs

1#![warn(clippy::all)]
2#![warn(clippy::pedantic)]
3#![warn(clippy::cargo)]
4#![allow(clippy::option_if_let_else)]
5#![allow(unknown_lints)]
6#![warn(missing_docs)]
7#![warn(missing_debug_implementations)]
8#![warn(missing_copy_implementations)]
9#![warn(rust_2018_idioms)]
10#![warn(rust_2021_compatibility)]
11#![warn(trivial_casts, trivial_numeric_casts)]
12#![warn(unsafe_op_in_unsafe_fn)]
13#![warn(unused_qualifications)]
14#![warn(variant_size_differences)]
15// Enable feature callouts in generated documentation:
16// https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html
17//
18// This approach is borrowed from tokio.
19#![cfg_attr(docsrs, feature(doc_cfg))]
20#![cfg_attr(docsrs, feature(doc_alias))]
21
22//! A wrapper around the decomposed parts of a `Vec<T>`.
23//!
24//! This crate defines a struct that contains the `Vec`'s internal pointer,
25//! length, and allocated capacity.
26//!
27//! [`RawParts`] makes [`Vec::from_raw_parts`] and [`Vec::into_raw_parts`] easier
28//! to use by giving names to the returned values. This prevents errors from
29//! mixing up the two `usize` values of length and capacity.
30//!
31//! # Examples
32//!
33//! ```
34//! use raw_parts::RawParts;
35//!
36//! let v: Vec<i32> = vec![-1, 0, 1];
37//!
38//! let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
39//!
40//! let rebuilt = unsafe {
41//!     // We can now make changes to the components, such as
42//!     // transmuting the raw pointer to a compatible type.
43//!     let ptr = ptr as *mut u32;
44//!     let raw_parts = RawParts { ptr, length, capacity };
45//!
46//!     raw_parts.into_vec()
47//! };
48//! assert_eq!(rebuilt, [4294967295, 0, 1]);
49//! ```
50//!
51//! # `no_std`
52//!
53//! raw-parts is `no_std` compatible with a required dependency on [`alloc`].
54
55#![no_std]
56#![doc(html_root_url = "https://docs.rs/raw-parts/2.2.0")]
57
58extern crate alloc;
59
60use alloc::vec::Vec;
61use core::fmt;
62use core::hash::{Hash, Hasher};
63use core::mem::ManuallyDrop;
64
65/// A wrapper around the decomposed parts of a `Vec<T>`.
66///
67/// This struct contains the `Vec`'s internal pointer, length, and allocated
68/// capacity.
69///
70/// `RawParts` makes [`Vec::from_raw_parts`] and [`Vec::into_raw_parts`] easier
71/// to use by giving names to the returned values. This prevents errors from
72/// mixing up the two `usize` values of length and capacity.
73///
74/// # Examples
75///
76/// ```
77/// use raw_parts::RawParts;
78///
79/// let v: Vec<i32> = vec![-1, 0, 1];
80///
81/// let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
82///
83/// let rebuilt = unsafe {
84///     // We can now make changes to the components, such as
85///     // transmuting the raw pointer to a compatible type.
86///     let ptr = ptr as *mut u32;
87///     let raw_parts = RawParts { ptr, length, capacity };
88///
89///     raw_parts.into_vec()
90/// };
91/// assert_eq!(rebuilt, [4294967295, 0, 1]);
92/// ```
93pub struct RawParts<T> {
94    /// A non-null pointer to a buffer of `T`.
95    ///
96    /// This pointer is the same as the value returned by [`Vec::as_mut_ptr`] in
97    /// the source vector.
98    pub ptr: *mut T,
99    /// The number of elements in the source vector, also referred to as its
100    /// "length".
101    ///
102    /// This value is the same as the value returned by [`Vec::len`] in the
103    /// source vector.
104    pub length: usize,
105    /// The number of elements the source vector can hold without reallocating.
106    ///
107    /// This value is the same as the value returned by [`Vec::capacity`] in the
108    /// source vector.
109    pub capacity: usize,
110}
111
112impl<T> From<Vec<T>> for RawParts<T> {
113    /// Decompose a `Vec<T>` into its raw components.
114    fn from(vec: Vec<T>) -> Self {
115        Self::from_vec(vec)
116    }
117}
118
119impl<T> fmt::Debug for RawParts<T> {
120    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
121        fmt.debug_struct("RawParts")
122            .field("ptr", &self.ptr)
123            .field("length", &self.length)
124            .field("capacity", &self.capacity)
125            .finish()
126    }
127}
128
129impl<T> PartialEq for RawParts<T> {
130    fn eq(&self, other: &Self) -> bool {
131        self.ptr == other.ptr && self.length == other.length && self.capacity == other.capacity
132    }
133}
134
135impl<T> Eq for RawParts<T> {}
136
137impl<T> Hash for RawParts<T> {
138    fn hash<H: Hasher>(&self, state: &mut H) {
139        self.ptr.hash(state);
140        self.length.hash(state);
141        self.capacity.hash(state);
142    }
143}
144
145// Do not implement the `From` trait in the other direction since `crate::from`
146// is an unsafe function.
147//
148// ```
149// impl<T> From<RawParts<T>> for Vec<T> {
150//     fn from(raw_parts: RawParts<T>) -> Self {
151//         // ERROR: this requires `unsafe`, which we don't want to hide in a
152//         // `From` impl.
153//         from(raw_parts)
154//     }
155// }
156
157impl<T> RawParts<T> {
158    /// Construct the raw components of a `Vec<T>` by decomposing it.
159    ///
160    /// Returns a struct containing the raw pointer to the underlying data, the
161    /// length of the vector (in elements), and the allocated capacity of the
162    /// data (in elements).
163    ///
164    /// After calling this function, the caller is responsible for the memory
165    /// previously managed by the `Vec`. The only way to do this is to convert
166    /// the raw pointer, length, and capacity back into a `Vec` with the
167    /// [`Vec::from_raw_parts`] function or the [`into_vec`] function, allowing
168    /// the destructor to perform the cleanup.
169    ///
170    /// [`into_vec`]: Self::into_vec
171    ///
172    /// # Examples
173    ///
174    /// ```
175    /// use raw_parts::RawParts;
176    ///
177    /// let v: Vec<i32> = vec![-1, 0, 1];
178    ///
179    /// let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
180    ///
181    /// let rebuilt = unsafe {
182    ///     // We can now make changes to the components, such as
183    ///     // transmuting the raw pointer to a compatible type.
184    ///     let ptr = ptr as *mut u32;
185    ///     let raw_parts = RawParts { ptr, length, capacity };
186    ///
187    ///     raw_parts.into_vec()
188    /// };
189    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
190    /// ```
191    #[must_use]
192    pub fn from_vec(vec: Vec<T>) -> Self {
193        // FIXME Update this when vec_into_raw_parts is stabilized
194        // See: https://doc.rust-lang.org/1.69.0/src/alloc/vec/mod.rs.html#823-826
195        // See: https://doc.rust-lang.org/beta/unstable-book/library-features/vec-into-raw-parts.html
196        //
197        // https://github.com/rust-lang/rust/issues/65816
198        let mut me = ManuallyDrop::new(vec);
199        let (ptr, length, capacity) = (me.as_mut_ptr(), me.len(), me.capacity());
200
201        Self {
202            ptr,
203            length,
204            capacity,
205        }
206    }
207
208    /// Creates a `Vec<T>` directly from the raw components of another vector.
209    ///
210    /// # Safety
211    ///
212    /// This function has the same safety invariants as [`Vec::from_raw_parts`],
213    /// which are repeated in the following paragraphs.
214    ///
215    /// This is highly unsafe, due to the number of invariants that aren't
216    /// checked:
217    ///
218    /// * `ptr` must have been allocated using the global allocator, such as via
219    ///   the [`alloc::alloc`] function.
220    /// * `T` needs to have the same alignment as what `ptr` was allocated with.
221    ///   (`T` having a less strict alignment is not sufficient, the alignment really
222    ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
223    ///   allocated and deallocated with the same layout.)
224    /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
225    ///   to be the same size as the pointer was allocated with. (Because similar to
226    ///   alignment, [`dealloc`] must be called with the same layout `size`.)
227    /// * `length` needs to be less than or equal to `capacity`.
228    /// * The first `length` values must be properly initialized values of type `T`.
229    /// * `capacity` needs to be the capacity that the pointer was allocated with.
230    /// * The allocated size in bytes must be no larger than `isize::MAX`.
231    ///   See the safety documentation of [`pointer::offset`].
232    ///
233    /// These requirements are always upheld by any `ptr` that has been allocated
234    /// via `Vec<T>`. Other allocation sources are allowed if the invariants are
235    /// upheld.
236    ///
237    /// Violating these may cause problems like corrupting the allocator's
238    /// internal data structures. For example it is normally **not** safe
239    /// to build a `Vec<u8>` from a pointer to a C `char` array with length
240    /// `size_t`, doing so is only safe if the array was initially allocated by
241    /// a `Vec` or `String`.
242    /// It's also not safe to build one from a `Vec<u16>` and its length, because
243    /// the allocator cares about the alignment, and these two types have different
244    /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
245    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
246    /// these issues, it is often preferable to do casting/transmuting using
247    /// [`slice::from_raw_parts`] instead.
248    ///
249    /// The ownership of `ptr` is effectively transferred to the
250    /// `Vec<T>` which may then deallocate, reallocate or change the
251    /// contents of memory pointed to by the pointer at will. Ensure
252    /// that nothing else uses the pointer after calling this
253    /// function.
254    ///
255    /// [`String`]: alloc::string::String
256    /// [`alloc::alloc`]: alloc::alloc::alloc
257    /// [`dealloc`]: alloc::alloc::GlobalAlloc::dealloc
258    /// [`slice::from_raw_parts`]: core::slice::from_raw_parts
259    /// [`pointer::offset`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// use core::ptr;
265    /// use core::mem;
266    ///
267    /// use raw_parts::RawParts;
268    ///
269    /// let v = vec![1, 2, 3];
270    ///
271    /// // Pull out the various important pieces of information about `v`
272    /// let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
273    ///
274    /// unsafe {
275    ///     // Overwrite memory with 4, 5, 6
276    ///     for i in 0..length as isize {
277    ///         ptr::write(ptr.offset(i), 4 + i);
278    ///     }
279    ///
280    ///     // Put everything back together into a Vec
281    ///     let raw_parts = RawParts { ptr, length, capacity };
282    ///     let rebuilt = raw_parts.into_vec();
283    ///     assert_eq!(rebuilt, [4, 5, 6]);
284    /// }
285    /// ```
286    #[must_use]
287    pub unsafe fn into_vec(self) -> Vec<T> {
288        let Self {
289            ptr,
290            length,
291            capacity,
292        } = self;
293
294        // Safety:
295        //
296        // The safety invariants that callers must uphold when calling `from` match
297        // the safety invariants of `Vec::from_raw_parts`.
298        unsafe { Vec::from_raw_parts(ptr, length, capacity) }
299    }
300}
301
302#[cfg(test)]
303mod tests {
304    use alloc::format;
305    use alloc::vec::Vec;
306    use core::hash::{Hash, Hasher};
307
308    use fnv::FnvHasher;
309
310    use crate::RawParts;
311
312    #[test]
313    fn roundtrip() {
314        let mut vec = Vec::with_capacity(100); // capacity is 100
315        vec.extend_from_slice(b"123456789"); // length is 9
316
317        let raw_parts = RawParts::from_vec(vec);
318        let raw_ptr = raw_parts.ptr;
319
320        let mut roundtripped_vec = unsafe { raw_parts.into_vec() };
321
322        assert_eq!(roundtripped_vec.capacity(), 100);
323        assert_eq!(roundtripped_vec.len(), 9);
324        assert_eq!(roundtripped_vec.as_mut_ptr(), raw_ptr);
325    }
326
327    #[test]
328    fn from_vec_sets_ptr() {
329        let mut vec = Vec::with_capacity(100); // capacity is 100
330        vec.extend_from_slice(b"123456789"); // length is 9
331        let ptr = vec.as_mut_ptr();
332
333        let raw_parts = RawParts::from_vec(vec);
334        assert_eq!(raw_parts.ptr, ptr);
335    }
336
337    #[test]
338    fn from_vec_sets_length() {
339        let mut vec = Vec::with_capacity(100); // capacity is 100
340        vec.extend_from_slice(b"123456789"); // length is 9
341
342        let raw_parts = RawParts::from_vec(vec);
343        assert_eq!(raw_parts.length, 9);
344    }
345
346    #[test]
347    fn from_vec_sets_capacity() {
348        let mut vec = Vec::with_capacity(100); // capacity is 100
349        vec.extend_from_slice(b"123456789"); // length is 9
350
351        let raw_parts = RawParts::from_vec(vec);
352        assert_eq!(raw_parts.capacity, 100);
353    }
354
355    #[test]
356    fn from_sets_ptr() {
357        let mut vec = Vec::with_capacity(100); // capacity is 100
358        vec.extend_from_slice(b"123456789"); // length is 9
359        let ptr = vec.as_mut_ptr();
360
361        let raw_parts = RawParts::from(vec);
362        assert_eq!(raw_parts.ptr, ptr);
363    }
364
365    #[test]
366    fn from_sets_length() {
367        let mut vec = Vec::with_capacity(100); // capacity is 100
368        vec.extend_from_slice(b"123456789"); // length is 9
369
370        let raw_parts = RawParts::from(vec);
371        assert_eq!(raw_parts.length, 9);
372    }
373
374    #[test]
375    fn from_sets_capacity() {
376        let mut vec = Vec::with_capacity(100); // capacity is 100
377        vec.extend_from_slice(b"123456789"); // length is 9
378
379        let raw_parts = RawParts::from(vec);
380        assert_eq!(raw_parts.capacity, 100);
381    }
382
383    #[test]
384    fn debug_test() {
385        let mut vec = Vec::with_capacity(100); // capacity is 100
386        vec.extend_from_slice(b"123456789"); // length is 9
387        let raw_parts = RawParts::from_vec(vec);
388
389        assert_eq!(
390            format!(
391                "RawParts {{ ptr: {:?}, length: 9, capacity: 100 }}",
392                raw_parts.ptr
393            ),
394            format!("{:?}", raw_parts)
395        );
396    }
397
398    #[test]
399    fn partial_eq_fail_pointer() {
400        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
401        vec_1.extend_from_slice(b"123456789"); // length is 9
402        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
403        vec_2.extend_from_slice(b"123456789"); // length is 9
404
405        let raw_parts_1 = RawParts::from_vec(vec_1);
406        let raw_parts_2 = RawParts::from_vec(vec_2);
407        assert_ne!(raw_parts_1, raw_parts_2);
408    }
409
410    #[test]
411    fn partial_eq_fail_capacity() {
412        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
413        vec_1.extend_from_slice(b"123456789"); // length is 9
414        let mut vec_2 = Vec::with_capacity(101); // capacity is 101
415        vec_2.extend_from_slice(b"123456789"); // length is 9
416
417        let raw_parts_1 = RawParts::from_vec(vec_1);
418        let raw_parts_2 = RawParts::from_vec(vec_2);
419        assert_ne!(raw_parts_1, raw_parts_2);
420    }
421
422    #[test]
423    fn partial_eq_fail_length() {
424        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
425        vec_1.extend_from_slice(b"123456789"); // length is 9
426        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
427        vec_2.extend_from_slice(b"12345678"); // length is 8
428
429        let raw_parts_1 = RawParts::from_vec(vec_1);
430        let raw_parts_2 = RawParts::from_vec(vec_2);
431        assert_ne!(raw_parts_1, raw_parts_2);
432    }
433
434    #[test]
435    fn partial_eq_pass() {
436        let mut vec = Vec::with_capacity(100); // capacity is 100
437        vec.extend_from_slice(b"123456789"); // length is 9
438
439        let RawParts {
440            ptr,
441            length,
442            capacity,
443        } = RawParts::from_vec(vec);
444        let a = RawParts {
445            ptr,
446            length,
447            capacity,
448        };
449        let b = RawParts {
450            ptr,
451            length,
452            capacity,
453        };
454        assert_eq!(a, b);
455    }
456
457    #[test]
458    fn hash_fail_pointer() {
459        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
460        vec_1.extend_from_slice(b"123456789"); // length is 9
461        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
462        vec_2.extend_from_slice(b"123456789"); // length is 9
463
464        let raw_parts_1 = RawParts::from_vec(vec_1);
465        let mut hasher = FnvHasher::default();
466        raw_parts_1.hash(&mut hasher);
467        let hash_a = hasher.finish();
468
469        let raw_parts_2 = RawParts::from_vec(vec_2);
470        let mut hasher = FnvHasher::default();
471        raw_parts_2.hash(&mut hasher);
472        let hash_b = hasher.finish();
473
474        assert_ne!(hash_a, hash_b);
475    }
476
477    #[test]
478    fn hash_fail_capacity() {
479        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
480        vec_1.extend_from_slice(b"123456789"); // length is 9
481        let mut vec_2 = Vec::with_capacity(101); // capacity is 101
482        vec_2.extend_from_slice(b"123456789"); // length is 9
483
484        let raw_parts_1 = RawParts::from_vec(vec_1);
485        let mut hasher = FnvHasher::default();
486        raw_parts_1.hash(&mut hasher);
487        let hash_a = hasher.finish();
488
489        let raw_parts_2 = RawParts::from_vec(vec_2);
490        let mut hasher = FnvHasher::default();
491        raw_parts_2.hash(&mut hasher);
492        let hash_b = hasher.finish();
493
494        assert_ne!(hash_a, hash_b);
495    }
496
497    #[test]
498    fn hash_fail_length() {
499        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
500        vec_1.extend_from_slice(b"123456789"); // length is 9
501        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
502        vec_2.extend_from_slice(b"12345678"); // length is 8
503
504        let raw_parts_1 = RawParts::from_vec(vec_1);
505        let mut hasher = FnvHasher::default();
506        raw_parts_1.hash(&mut hasher);
507        let hash_a = hasher.finish();
508
509        let raw_parts_2 = RawParts::from_vec(vec_2);
510        let mut hasher = FnvHasher::default();
511        raw_parts_2.hash(&mut hasher);
512        let hash_b = hasher.finish();
513
514        assert_ne!(hash_a, hash_b);
515    }
516
517    #[test]
518    fn hash_eq_pass() {
519        let mut vec = Vec::with_capacity(100); // capacity is 100
520        vec.extend_from_slice(b"123456789"); // length is 9
521        let raw_parts = RawParts::from_vec(vec);
522
523        let mut hasher = FnvHasher::default();
524        raw_parts.hash(&mut hasher);
525        let hash_a = hasher.finish();
526
527        let mut hasher = FnvHasher::default();
528        raw_parts.hash(&mut hasher);
529        let hash_b = hasher.finish();
530
531        assert_eq!(hash_a, hash_b);
532    }
533}
534
535// Ensure code blocks in `README.md` compile.
536//
537// This module declaration should be kept at the end of the file, in order to
538// not interfere with code coverage.
539#[cfg(doctest)]
540#[doc = include_str!("../README.md")]
541mod readme {}