mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-21 22:32:23 +00:00
feat: add TransparentWrapperAlloc trait (#111)
* feat: add TransparentWrapperAlloc trait * implements wrap_vec and peel_vec * fix: review comments * remote asserts as they don't do anything * avoid issue with stacked borrows
This commit is contained in:
parent
e8cd71df54
commit
abe55e525e
@ -297,3 +297,57 @@ pub fn pod_collect_to_vec<
|
|||||||
dst_bytes[..src_size].copy_from_slice(src_bytes);
|
dst_bytes[..src_size].copy_from_slice(src_bytes);
|
||||||
dst
|
dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An extension trait for `TransparentWrapper` and alloc types.
|
||||||
|
pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
|
||||||
|
/// Convert a vec of the inner type into a vec of the wrapper type.
|
||||||
|
fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
Inner: Sized
|
||||||
|
{
|
||||||
|
let mut s = core::mem::ManuallyDrop::new(s);
|
||||||
|
|
||||||
|
let length = s.len();
|
||||||
|
let capacity = s.capacity();
|
||||||
|
let ptr = s.as_mut_ptr();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// SAFETY:
|
||||||
|
// * ptr comes from Vec (and will not be double-dropped)
|
||||||
|
// * the two types have the identical representation
|
||||||
|
// * the len and capacity fields are valid
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
ptr as *mut Self,
|
||||||
|
length,
|
||||||
|
capacity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a vec of the wrapper type into a vec of the inner type.
|
||||||
|
fn peel_vec(s: Vec<Self>) -> Vec<Inner>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
Inner: Sized
|
||||||
|
{
|
||||||
|
let mut s = core::mem::ManuallyDrop::new(s);
|
||||||
|
|
||||||
|
let length = s.len();
|
||||||
|
let capacity = s.capacity();
|
||||||
|
let ptr = s.as_mut_ptr();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// SAFETY:
|
||||||
|
// * ptr comes from Vec (and will not be double-dropped)
|
||||||
|
// * the two types have the identical representation
|
||||||
|
// * the len and capacity fields are valid
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
ptr as *mut Inner,
|
||||||
|
length,
|
||||||
|
capacity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<I: ?Sized, T: TransparentWrapper<I>> TransparentWrapperAlloc<I> for T {}
|
||||||
|
@ -61,4 +61,21 @@ fn test_transparent_wrapper() {
|
|||||||
Foreign::default(),
|
Foreign::default(),
|
||||||
]));
|
]));
|
||||||
// counterpart?
|
// counterpart?
|
||||||
|
|
||||||
|
#[cfg(feature = "extern_crate_alloc")]
|
||||||
|
{
|
||||||
|
use bytemuck::allocation::TransparentWrapperAlloc;
|
||||||
|
|
||||||
|
let a: Vec<Foreign> = vec![Foreign::default(); 2];
|
||||||
|
|
||||||
|
let b: Vec<Wrapper> = Wrapper::wrap_vec(a);
|
||||||
|
assert_eq!(
|
||||||
|
bytemuck::cast_slice::<Wrapper, u8>(b.as_slice()), &[0u8, 0]
|
||||||
|
);
|
||||||
|
|
||||||
|
let c: Vec<Foreign> = Wrapper::peel_vec(b);
|
||||||
|
assert_eq!(
|
||||||
|
bytemuck::cast_slice::<Wrapper, u8>(Wrapper::wrap_slice(c.as_slice())), &[0, 0]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user