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