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