use std::mem::size_of;
use std::slice;
pub unsafe fn reinterpret_mut_slice<T, S>(slice: &mut [T]) -> &mut [S] {
let size_t = size_of::<T>();
let size_s = size_of::<S>();
let nu_len = if size_t > 0 {
assert_ne!(
size_s, 0,
"Cannot reinterpret a slice of non-zero sized types as a slice of zero sized types."
);
assert_eq!(
(slice.len() * size_t) % size_s,
0,
"Slice cannot be safely reinterpreted due to a misaligned size"
);
(slice.len() * size_t) / size_s
} else {
assert_eq!(
size_s, 0,
"Cannot reinterpret a slice of zero sized types as a slice of non-zero sized types."
);
slice.len()
};
slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut S, nu_len)
}
pub unsafe fn reinterpret_slice<T, S>(slice: &[T]) -> &[S] {
let size_t = size_of::<T>();
let size_s = size_of::<S>();
let nu_len = if size_t > 0 {
assert_ne!(
size_s, 0,
"Cannot reinterpret a slice of non-zero sized types as a slice of zero sized types."
);
assert_eq!(
(slice.len() * size_t) % size_s,
0,
"Slice cannot be safely reinterpreted due to a misaligned size"
);
(slice.len() * size_t) / size_s
} else {
assert_eq!(
size_s, 0,
"Cannot reinterpret a slice of zero sized types as a slice of non-zero sized types."
);
slice.len()
};
slice::from_raw_parts(slice.as_ptr() as *const S, nu_len)
}
pub unsafe fn reinterpret_vec<T, S>(mut vec: Vec<T>) -> Vec<S> {
let size_t = size_of::<T>();
let size_s = size_of::<S>();
let nu_vec = if size_t > 0 {
assert_ne!(
size_s, 0,
"Cannot reinterpret a Vec of non-zero sized types as a Vec of zero sized types."
);
assert_eq!(
(vec.len() * size_t) % size_s,
0,
"Vec cannot be safely reinterpreted due to a misaligned size"
);
let nu_len = (vec.len() * size_t) / size_s;
assert_eq!(
(vec.capacity() * size_t) % size_s,
0,
"Vec cannot be safely reinterpreted due to a misaligned capacity"
);
let nu_capacity = (vec.capacity() * size_t) / size_s;
let vec_ptr = vec.as_mut_ptr();
Vec::from_raw_parts(vec_ptr as *mut S, nu_len, nu_capacity)
} else {
assert_eq!(
size_s, 0,
"Cannot reinterpret a Vec of zero sized types as a Vec of non-zero sized types."
);
let nu_len = vec.len();
let nu_capacity = vec.capacity();
debug_assert_eq!(
nu_capacity,
(-1isize) as usize,
"Capacity should be -1 for 0 sized types. (bug)"
);
let vec_ptr = vec.as_mut_ptr();
Vec::from_raw_parts(vec_ptr as *mut S, nu_len, nu_capacity)
};
::std::mem::forget(vec);
nu_vec
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reinterpret_slice_test() {
let vec: Vec<[f64; 3]> = vec![[0.1, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
let flat: Vec<f64> = vec![0.1, 1.0, 2.0, 1.2, 1.4, 2.1, 0.5, 3.2, 4.0];
let nu_flat: &[f64] = unsafe { reinterpret_slice(vec.as_slice()) };
assert_eq!(*nu_flat, *flat.as_slice());
assert_eq!(nu_flat, flat.as_slice());
let nu_slice: &[[f64; 3]] = unsafe { reinterpret_slice(flat.as_slice()) };
assert_eq!(*nu_slice, *vec.as_slice());
assert_eq!(nu_slice, vec.as_slice());
}
#[test]
fn reinterpret_mut_slice_test() {
let vec: Vec<[f64; 3]> = vec![[0.5, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
let flat_mut = &mut [-0.5, -1.0, -1.0, 0.2, -0.6, -0.9, -0.5, 1.2, 1.0];
let nu_mut_slice: &mut [[f64; 3]] = unsafe { reinterpret_mut_slice(flat_mut) };
for v in nu_mut_slice.iter_mut() {
v[0] += 1.0;
v[1] += 2.0;
v[2] += 3.0;
}
assert_eq!(nu_mut_slice, vec.as_slice());
}
#[test]
fn reinterpret_vec_test() {
let exp_vec: Vec<[f64; 3]> = vec![[0.5, 1.0, 2.0], [1.2, 1.4, 2.1], [0.5, 3.2, 4.0]];
let vec = vec![-0.5, -1.0, -1.0, 0.2, -0.6, -0.9, -0.5, 1.2, 1.0];
let mut nu_vec: Vec<[f64; 3]> = unsafe { reinterpret_vec(vec.clone()) };
for v in nu_vec.iter_mut() {
v[0] += 1.0;
v[1] += 2.0;
v[2] += 3.0;
}
assert_eq!(nu_vec, exp_vec);
}
#[test]
fn zero_size_test() {
#[derive(Debug, Clone, PartialEq)]
struct Foo {
a: (),
b: (),
}
let exp_vec: Vec<Foo> = vec![Foo { a: (), b: () }, Foo { a: (), b: () }];
let mut mut_vec = vec![(), ()];
let vec = mut_vec.clone();
let mut_slice = mut_vec.as_mut_slice();
let slice = vec.as_slice();
let exp_slice = exp_vec.as_slice();
let nu_vec: Vec<Foo> = unsafe { reinterpret_vec(vec.clone()) };
assert_eq!(nu_vec, exp_vec);
let nu_slice: &[Foo] = unsafe { reinterpret_slice(slice) };
assert_eq!(nu_slice, exp_slice);
let nu_mut_slice: &mut [Foo] = unsafe { reinterpret_mut_slice(mut_slice) };
assert_eq!(nu_mut_slice, exp_slice);
let old_vec: Vec<()> = unsafe { reinterpret_vec(nu_vec.clone()) };
assert_eq!(vec, old_vec);
let old_slice: &[()] = unsafe { reinterpret_mut_slice(nu_mut_slice) };
assert_eq!(slice, old_slice);
}
}