rendy_util/casts.rs
1//! Contains functions for casting
2use std::{any::TypeId, borrow::Cow};
3
4/// Cast vec of some arbitrary type into vec of bytes.
5/// Can lead to UB if allocator changes. Use with caution.
6/// TODO: Replace with something safer.
7pub fn cast_vec<T: Copy>(mut vec: Vec<T>) -> Vec<u8> {
8 let len = std::mem::size_of::<T>() * vec.len();
9 let cap = std::mem::size_of::<T>() * vec.capacity();
10 let ptr = vec.as_mut_ptr();
11 std::mem::forget(vec);
12 unsafe { Vec::from_raw_parts(ptr as _, len, cap) }
13}
14
15/// Cast slice of some arbitrary type into slice of bytes.
16pub fn cast_slice<T>(slice: &[T]) -> &[u8] {
17 let len = std::mem::size_of::<T>() * slice.len();
18 let ptr = slice.as_ptr();
19 unsafe { std::slice::from_raw_parts(ptr as _, len) }
20}
21
22/// Cast `cow` of some arbitrary type into `cow` of bytes.
23/// Can lead to UB if allocator changes. Use with caution.
24/// TODO: Replace with something safer.
25pub fn cast_cow<T: Copy>(cow: Cow<'_, [T]>) -> Cow<'_, [u8]> {
26 match cow {
27 Cow::Borrowed(slice) => Cow::Borrowed(cast_slice(slice)),
28 Cow::Owned(vec) => Cow::Owned(cast_vec(vec)),
29 }
30}
31
32/// Casts identical types.
33/// Useful in generic environment where caller knows that two types are the same
34/// but Rust is not convinced.
35///
36/// # Panics
37///
38/// Panics if types are actually different.
39///
40/// # Example
41///
42/// ```
43/// # extern crate rendy_util;
44/// # use rendy_util::identical_cast;
45/// # use std::any::TypeId;
46/// # fn foo<T: 'static>() {
47/// if TypeId::of::<T>() == TypeId::of::<u32>() {
48/// let value: T = identical_cast(42u32);
49/// }
50/// # }
51///
52/// ```
53pub fn identical_cast<T: 'static, U: 'static>(value: T) -> U {
54 assert_eq!(TypeId::of::<T>(), TypeId::of::<U>());
55 unsafe {
56 // We know types are the same.
57 let mut value = std::mem::ManuallyDrop::new(value);
58 let ptr: *mut T = &mut *value;
59 std::ptr::read(ptr as *mut U)
60 }
61}