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