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 {}