#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::cargo)]
#![allow(clippy::option_if_let_else)]
#![allow(unknown_lints)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![warn(missing_copy_implementations)]
#![warn(rust_2018_idioms)]
#![warn(rust_2021_compatibility)]
#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unsafe_op_in_unsafe_fn)]
#![warn(unused_qualifications)]
#![warn(variant_size_differences)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, feature(doc_alias))]
#![no_std]
#![doc(html_root_url = "https://docs.rs/raw-parts/1.1.2")]
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
mod readme {}
extern crate alloc;
use alloc::vec::Vec;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::mem::ManuallyDrop;
pub struct RawParts<T> {
pub ptr: *mut T,
pub length: usize,
pub capacity: usize,
}
impl<T> From<Vec<T>> for RawParts<T> {
fn from(vec: Vec<T>) -> Self {
Self::from_vec(vec)
}
}
impl<T> fmt::Debug for RawParts<T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("RawParts")
.field("ptr", &self.ptr)
.field("length", &self.length)
.field("capacity", &self.capacity)
.finish()
}
}
impl<T> PartialEq for RawParts<T> {
fn eq(&self, other: &Self) -> bool {
self.ptr == other.ptr && self.length == other.length && self.capacity == other.capacity
}
}
impl<T> Eq for RawParts<T> {}
impl<T> Hash for RawParts<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.ptr.hash(state);
self.length.hash(state);
self.capacity.hash(state);
}
}
impl<T> RawParts<T> {
#[must_use]
pub fn from_vec(vec: Vec<T>) -> RawParts<T> {
let mut me = ManuallyDrop::new(vec);
let (ptr, length, capacity) = (me.as_mut_ptr(), me.len(), me.capacity());
Self {
ptr,
length,
capacity,
}
}
#[must_use]
#[allow(clippy::needless_pass_by_value)]
pub unsafe fn into_vec(this: Self) -> Vec<T> {
let Self {
ptr,
length,
capacity,
} = this;
unsafe { Vec::from_raw_parts(ptr, length, capacity) }
}
}
#[cfg(test)]
mod tests {
use alloc::format;
use alloc::vec::Vec;
use crate::RawParts;
#[test]
fn roundtrip() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789");
let raw_parts = RawParts::from_vec(vec);
let raw_ptr = raw_parts.ptr;
let mut roundtripped_vec = unsafe { RawParts::into_vec(raw_parts) };
assert_eq!(roundtripped_vec.capacity(), 100);
assert_eq!(roundtripped_vec.len(), 9);
assert_eq!(roundtripped_vec.as_mut_ptr(), raw_ptr);
}
#[test]
fn from_vec_sets_ptr() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789"); let ptr = vec.as_mut_ptr();
let raw_parts = RawParts::from_vec(vec);
assert_eq!(raw_parts.ptr, ptr);
}
#[test]
fn from_vec_sets_length() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789");
let raw_parts = RawParts::from_vec(vec);
assert_eq!(raw_parts.length, 9);
}
#[test]
fn from_vec_sets_capacity() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789");
let raw_parts = RawParts::from_vec(vec);
assert_eq!(raw_parts.capacity, 100);
}
#[test]
fn debug_test() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789"); let raw_parts = RawParts::from_vec(vec);
assert_eq!(
format!(
"RawParts {{ ptr: {:?}, length: 9, capacity: 100 }}",
raw_parts.ptr
),
format!("{:?}", raw_parts)
);
}
#[test]
fn partial_eq_fail_pointer() {
let mut vec_1 = Vec::with_capacity(100); vec_1.extend_from_slice(b"123456789"); let mut vec_2 = Vec::with_capacity(100); vec_2.extend_from_slice(b"123456789");
let raw_parts_1 = RawParts::from_vec(vec_1);
let raw_parts_2 = RawParts::from_vec(vec_2);
assert_ne!(raw_parts_1, raw_parts_2);
}
#[test]
fn partial_eq_fail_capacity() {
let mut vec_1 = Vec::with_capacity(100); vec_1.extend_from_slice(b"123456789"); let mut vec_2 = Vec::with_capacity(101); vec_2.extend_from_slice(b"123456789");
let raw_parts_1 = RawParts::from_vec(vec_1);
let raw_parts_2 = RawParts::from_vec(vec_2);
assert_ne!(raw_parts_1, raw_parts_2);
}
#[test]
fn partial_eq_fail_length() {
let mut vec_1 = Vec::with_capacity(100); vec_1.extend_from_slice(b"123456789"); let mut vec_2 = Vec::with_capacity(100); vec_2.extend_from_slice(b"12345678");
let raw_parts_1 = RawParts::from_vec(vec_1);
let raw_parts_2 = RawParts::from_vec(vec_2);
assert_ne!(raw_parts_1, raw_parts_2);
}
#[test]
fn partial_eq_pass() {
let mut vec = Vec::with_capacity(100); vec.extend_from_slice(b"123456789");
let RawParts {
ptr,
length,
capacity,
} = RawParts::from_vec(vec);
let a = RawParts {
ptr,
length,
capacity,
};
let b = RawParts {
ptr,
length,
capacity,
};
assert_eq!(a, b);
}
}