Skip to main content

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