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. Converting a
146// `RawParts` back into a `Vec` requires an `unsafe` block via the [`into_vec`]
147// method, which we don't want to hide in a `From` impl.
148//
149// ```
150// impl<T> From<RawParts<T>> for Vec<T> {
151//     fn from(raw_parts: RawParts<T>) -> Self {
152//         // ERROR: this requires `unsafe`, which we don't want to hide in a
153//         // `From` impl.
154//         unsafe { raw_parts.into_vec() }
155//     }
156// }
157// ```
158//
159// [`into_vec`]: Self::into_vec
160
161impl<T> RawParts<T> {
162    /// Construct the raw components of a `Vec<T>` by decomposing it.
163    ///
164    /// Returns a struct containing the raw pointer to the underlying data, the
165    /// length of the vector (in elements), and the allocated capacity of the
166    /// data (in elements).
167    ///
168    /// After calling this function, the caller is responsible for the memory
169    /// previously managed by the `Vec`. The only way to do this is to convert
170    /// the raw pointer, length, and capacity back into a `Vec` with the
171    /// [`Vec::from_raw_parts`] function or the [`into_vec`] function, allowing
172    /// the destructor to perform the cleanup.
173    ///
174    /// [`into_vec`]: Self::into_vec
175    ///
176    /// # Examples
177    ///
178    /// ```
179    /// use raw_parts::RawParts;
180    ///
181    /// let v: Vec<i32> = vec![-1, 0, 1];
182    ///
183    /// let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
184    ///
185    /// let rebuilt = unsafe {
186    ///     // We can now make changes to the components, such as
187    ///     // transmuting the raw pointer to a compatible type.
188    ///     let ptr = ptr as *mut u32;
189    ///     let raw_parts = RawParts { ptr, length, capacity };
190    ///
191    ///     raw_parts.into_vec()
192    /// };
193    /// assert_eq!(rebuilt, [4294967295, 0, 1]);
194    /// ```
195    #[must_use]
196    pub fn from_vec(vec: Vec<T>) -> Self {
197        // FIXME Update this when vec_into_raw_parts is stabilized
198        // See: https://doc.rust-lang.org/1.69.0/src/alloc/vec/mod.rs.html#823-826
199        // See: https://doc.rust-lang.org/beta/unstable-book/library-features/vec-into-raw-parts.html
200        //
201        // https://github.com/rust-lang/rust/issues/65816
202        let mut me = ManuallyDrop::new(vec);
203        let (ptr, length, capacity) = (me.as_mut_ptr(), me.len(), me.capacity());
204
205        Self {
206            ptr,
207            length,
208            capacity,
209        }
210    }
211
212    /// Creates a `Vec<T>` directly from the raw components of another vector.
213    ///
214    /// # Safety
215    ///
216    /// This function has the same safety invariants as [`Vec::from_raw_parts`],
217    /// which are repeated in the following paragraphs.
218    ///
219    /// This is highly unsafe, due to the number of invariants that aren't
220    /// checked:
221    ///
222    /// * `ptr` must have been allocated using the global allocator, such as via
223    ///   the [`alloc::alloc`] function.
224    /// * `T` needs to have the same alignment as what `ptr` was allocated with.
225    ///   (`T` having a less strict alignment is not sufficient, the alignment really
226    ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
227    ///   allocated and deallocated with the same layout.)
228    /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
229    ///   to be the same size as the pointer was allocated with. (Because similar to
230    ///   alignment, [`dealloc`] must be called with the same layout `size`.)
231    /// * `length` needs to be less than or equal to `capacity`.
232    /// * The first `length` values must be properly initialized values of type `T`.
233    /// * `capacity` needs to be the capacity that the pointer was allocated with.
234    /// * The allocated size in bytes must be no larger than `isize::MAX`.
235    ///   See the safety documentation of [`pointer::offset`].
236    ///
237    /// These requirements are always upheld by any `ptr` that has been allocated
238    /// via `Vec<T>`. Other allocation sources are allowed if the invariants are
239    /// upheld.
240    ///
241    /// Violating these may cause problems like corrupting the allocator's
242    /// internal data structures. For example it is normally **not** safe
243    /// to build a `Vec<u8>` from a pointer to a C `char` array with length
244    /// `size_t`, doing so is only safe if the array was initially allocated by
245    /// a `Vec` or `String`.
246    /// It's also not safe to build one from a `Vec<u16>` and its length, because
247    /// the allocator cares about the alignment, and these two types have different
248    /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
249    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
250    /// these issues, it is often preferable to do casting/transmuting using
251    /// [`slice::from_raw_parts`] instead.
252    ///
253    /// The ownership of `ptr` is effectively transferred to the
254    /// `Vec<T>` which may then deallocate, reallocate or change the
255    /// contents of memory pointed to by the pointer at will. Ensure
256    /// that nothing else uses the pointer after calling this
257    /// function.
258    ///
259    /// [`String`]: alloc::string::String
260    /// [`alloc::alloc`]: alloc::alloc::alloc
261    /// [`dealloc`]: alloc::alloc::GlobalAlloc::dealloc
262    /// [`slice::from_raw_parts`]: core::slice::from_raw_parts
263    /// [`pointer::offset`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset
264    ///
265    /// # Examples
266    ///
267    /// ```
268    /// use core::ptr;
269    ///
270    /// use raw_parts::RawParts;
271    ///
272    /// let v = vec![1, 2, 3];
273    ///
274    /// // Pull out the various important pieces of information about `v`
275    /// let RawParts { ptr, length, capacity } = RawParts::from_vec(v);
276    ///
277    /// unsafe {
278    ///     // Overwrite memory with 4, 5, 6
279    ///     for i in 0..length as isize {
280    ///         ptr::write(ptr.offset(i), 4 + i);
281    ///     }
282    ///
283    ///     // Put everything back together into a Vec
284    ///     let raw_parts = RawParts { ptr, length, capacity };
285    ///     let rebuilt = raw_parts.into_vec();
286    ///     assert_eq!(rebuilt, [4, 5, 6]);
287    /// }
288    /// ```
289    #[must_use]
290    pub unsafe fn into_vec(self) -> Vec<T> {
291        let Self {
292            ptr,
293            length,
294            capacity,
295        } = self;
296
297        // Safety:
298        //
299        // The safety invariants that callers must uphold when calling `from` match
300        // the safety invariants of `Vec::from_raw_parts`.
301        unsafe { Vec::from_raw_parts(ptr, length, capacity) }
302    }
303}
304
305#[cfg(test)]
306mod tests {
307    use alloc::format;
308    use alloc::vec::Vec;
309    use core::hash::{Hash, Hasher};
310
311    use fnv::FnvHasher;
312
313    use crate::RawParts;
314
315    #[test]
316    fn roundtrip() {
317        let mut vec = Vec::with_capacity(100); // capacity is 100
318        vec.extend_from_slice(b"123456789"); // length is 9
319
320        let raw_parts = RawParts::from_vec(vec);
321        let raw_ptr = raw_parts.ptr;
322
323        let mut roundtripped_vec = unsafe { raw_parts.into_vec() };
324
325        assert_eq!(roundtripped_vec.capacity(), 100);
326        assert_eq!(roundtripped_vec.len(), 9);
327        assert_eq!(roundtripped_vec.as_mut_ptr(), raw_ptr);
328    }
329
330    #[test]
331    fn from_vec_sets_ptr() {
332        let mut vec = Vec::with_capacity(100); // capacity is 100
333        vec.extend_from_slice(b"123456789"); // length is 9
334        let ptr = vec.as_mut_ptr();
335
336        let raw_parts = RawParts::from_vec(vec);
337        assert_eq!(raw_parts.ptr, ptr);
338        drop(unsafe { raw_parts.into_vec() });
339    }
340
341    #[test]
342    fn from_vec_sets_length() {
343        let mut vec = Vec::with_capacity(100); // capacity is 100
344        vec.extend_from_slice(b"123456789"); // length is 9
345
346        let raw_parts = RawParts::from_vec(vec);
347        assert_eq!(raw_parts.length, 9);
348        drop(unsafe { raw_parts.into_vec() });
349    }
350
351    #[test]
352    fn from_vec_sets_capacity() {
353        let mut vec = Vec::with_capacity(100); // capacity is 100
354        vec.extend_from_slice(b"123456789"); // length is 9
355
356        let raw_parts = RawParts::from_vec(vec);
357        assert_eq!(raw_parts.capacity, 100);
358        drop(unsafe { raw_parts.into_vec() });
359    }
360
361    #[test]
362    fn from_vec_empty() {
363        let vec: Vec<u8> = Vec::new();
364
365        let raw_parts = RawParts::from_vec(vec);
366        assert_eq!(raw_parts.length, 0);
367        assert_eq!(raw_parts.capacity, 0);
368        assert!(!raw_parts.ptr.is_null());
369
370        // Rebuild the Vec to avoid leaking memory.
371        let _ = unsafe { raw_parts.into_vec() };
372    }
373
374    #[test]
375    fn from_sets_ptr() {
376        let mut vec = Vec::with_capacity(100); // capacity is 100
377        vec.extend_from_slice(b"123456789"); // length is 9
378        let ptr = vec.as_mut_ptr();
379
380        let raw_parts = RawParts::from(vec);
381        assert_eq!(raw_parts.ptr, ptr);
382        drop(unsafe { raw_parts.into_vec() });
383    }
384
385    #[test]
386    fn from_sets_length() {
387        let mut vec = Vec::with_capacity(100); // capacity is 100
388        vec.extend_from_slice(b"123456789"); // length is 9
389
390        let raw_parts = RawParts::from(vec);
391        assert_eq!(raw_parts.length, 9);
392        drop(unsafe { raw_parts.into_vec() });
393    }
394
395    #[test]
396    fn from_sets_capacity() {
397        let mut vec = Vec::with_capacity(100); // capacity is 100
398        vec.extend_from_slice(b"123456789"); // length is 9
399
400        let raw_parts = RawParts::from(vec);
401        assert_eq!(raw_parts.capacity, 100);
402        drop(unsafe { raw_parts.into_vec() });
403    }
404
405    #[test]
406    fn debug_test() {
407        let mut vec = Vec::with_capacity(100); // capacity is 100
408        vec.extend_from_slice(b"123456789"); // length is 9
409        let raw_parts = RawParts::from_vec(vec);
410
411        assert_eq!(
412            format!(
413                "RawParts {{ ptr: {:?}, length: 9, capacity: 100 }}",
414                raw_parts.ptr
415            ),
416            format!("{:?}", raw_parts)
417        );
418        drop(unsafe { raw_parts.into_vec() });
419    }
420
421    #[test]
422    fn partial_eq_fail_pointer() {
423        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
424        vec_1.extend_from_slice(b"123456789"); // length is 9
425        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
426        vec_2.extend_from_slice(b"123456789"); // length is 9
427
428        let raw_parts_1 = RawParts::from_vec(vec_1);
429        let raw_parts_2 = RawParts::from_vec(vec_2);
430        assert_ne!(raw_parts_1, raw_parts_2);
431        drop(unsafe { raw_parts_1.into_vec() });
432        drop(unsafe { raw_parts_2.into_vec() });
433    }
434
435    #[test]
436    fn partial_eq_fail_capacity() {
437        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
438        vec_1.extend_from_slice(b"123456789"); // length is 9
439        let mut vec_2 = Vec::with_capacity(101); // capacity is 101
440        vec_2.extend_from_slice(b"123456789"); // length is 9
441
442        let raw_parts_1 = RawParts::from_vec(vec_1);
443        let raw_parts_2 = RawParts::from_vec(vec_2);
444        assert_ne!(raw_parts_1, raw_parts_2);
445        drop(unsafe { raw_parts_1.into_vec() });
446        drop(unsafe { raw_parts_2.into_vec() });
447    }
448
449    #[test]
450    fn partial_eq_fail_length() {
451        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
452        vec_1.extend_from_slice(b"123456789"); // length is 9
453        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
454        vec_2.extend_from_slice(b"12345678"); // length is 8
455
456        let raw_parts_1 = RawParts::from_vec(vec_1);
457        let raw_parts_2 = RawParts::from_vec(vec_2);
458        assert_ne!(raw_parts_1, raw_parts_2);
459        drop(unsafe { raw_parts_1.into_vec() });
460        drop(unsafe { raw_parts_2.into_vec() });
461    }
462
463    #[test]
464    fn partial_eq_pass() {
465        let mut vec = Vec::with_capacity(100); // capacity is 100
466        vec.extend_from_slice(b"123456789"); // length is 9
467
468        let RawParts {
469            ptr,
470            length,
471            capacity,
472        } = RawParts::from_vec(vec);
473        let a = RawParts {
474            ptr,
475            length,
476            capacity,
477        };
478        let b = RawParts {
479            ptr,
480            length,
481            capacity,
482        };
483        assert_eq!(a, b);
484        drop(unsafe {
485            RawParts {
486                ptr,
487                length,
488                capacity,
489            }
490            .into_vec()
491        });
492    }
493
494    #[test]
495    fn hash_fail_pointer() {
496        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
497        vec_1.extend_from_slice(b"123456789"); // length is 9
498        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
499        vec_2.extend_from_slice(b"123456789"); // length is 9
500
501        let raw_parts_1 = RawParts::from_vec(vec_1);
502        let mut hasher = FnvHasher::default();
503        raw_parts_1.hash(&mut hasher);
504        let hash_a = hasher.finish();
505
506        let raw_parts_2 = RawParts::from_vec(vec_2);
507        let mut hasher = FnvHasher::default();
508        raw_parts_2.hash(&mut hasher);
509        let hash_b = hasher.finish();
510
511        assert_ne!(hash_a, hash_b);
512        drop(unsafe { raw_parts_1.into_vec() });
513        drop(unsafe { raw_parts_2.into_vec() });
514    }
515
516    #[test]
517    fn hash_fail_capacity() {
518        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
519        vec_1.extend_from_slice(b"123456789"); // length is 9
520        let mut vec_2 = Vec::with_capacity(101); // capacity is 101
521        vec_2.extend_from_slice(b"123456789"); // length is 9
522
523        let raw_parts_1 = RawParts::from_vec(vec_1);
524        let mut hasher = FnvHasher::default();
525        raw_parts_1.hash(&mut hasher);
526        let hash_a = hasher.finish();
527
528        let raw_parts_2 = RawParts::from_vec(vec_2);
529        let mut hasher = FnvHasher::default();
530        raw_parts_2.hash(&mut hasher);
531        let hash_b = hasher.finish();
532
533        assert_ne!(hash_a, hash_b);
534        drop(unsafe { raw_parts_1.into_vec() });
535        drop(unsafe { raw_parts_2.into_vec() });
536    }
537
538    #[test]
539    fn hash_fail_length() {
540        let mut vec_1 = Vec::with_capacity(100); // capacity is 100
541        vec_1.extend_from_slice(b"123456789"); // length is 9
542        let mut vec_2 = Vec::with_capacity(100); // capacity is 100
543        vec_2.extend_from_slice(b"12345678"); // length is 8
544
545        let raw_parts_1 = RawParts::from_vec(vec_1);
546        let mut hasher = FnvHasher::default();
547        raw_parts_1.hash(&mut hasher);
548        let hash_a = hasher.finish();
549
550        let raw_parts_2 = RawParts::from_vec(vec_2);
551        let mut hasher = FnvHasher::default();
552        raw_parts_2.hash(&mut hasher);
553        let hash_b = hasher.finish();
554
555        assert_ne!(hash_a, hash_b);
556        drop(unsafe { raw_parts_1.into_vec() });
557        drop(unsafe { raw_parts_2.into_vec() });
558    }
559
560    #[test]
561    fn hash_eq_pass() {
562        let mut vec = Vec::with_capacity(100); // capacity is 100
563        vec.extend_from_slice(b"123456789"); // length is 9
564        let raw_parts = RawParts::from_vec(vec);
565
566        let mut hasher = FnvHasher::default();
567        raw_parts.hash(&mut hasher);
568        let hash_a = hasher.finish();
569
570        let mut hasher = FnvHasher::default();
571        raw_parts.hash(&mut hasher);
572        let hash_b = hasher.finish();
573
574        assert_eq!(hash_a, hash_b);
575        drop(unsafe { raw_parts.into_vec() });
576    }
577}
578
579// Ensure code blocks in `README.md` compile.
580//
581// This module declaration should be kept at the end of the file, in order to
582// not interfere with code coverage.
583#[cfg(doctest)]
584#[doc = include_str!("../README.md")]
585mod readme {}