I checked that tests seem to work and miri doesn't seem to complain but I wonder if this code valid in semantic sense and would be broken in future Rust release.
References and pointers to different unsized types are not guaranteed to have the same layout, even though this holds on current compiler versions. The preferred method is to use a pointer cast (Rust Playground):
use core::ops::Deref;
#[derive(Eq, PartialEq, Debug)]
struct UniqueArray<const N: usize>([i32; N]);
#[derive(Eq, PartialEq, Debug)]
struct UniqueVec(Vec<i32>);
#[derive(Eq, PartialEq, Debug)]
#[repr(transparent)]
struct UniqueSlice([i32]);
impl<const N: usize> Deref for UniqueArray<N> {
type Target = UniqueSlice;
#[inline]
fn deref(&self) -> &UniqueSlice {
unsafe { &*(self.0.as_slice() as *const [i32] as *const UniqueSlice) }
}
}
impl Deref for UniqueVec {
type Target = UniqueSlice;
#[inline]
fn deref(&self) -> &UniqueSlice {
unsafe { &*(self.0.as_slice() as *const [i32] as *const UniqueSlice) }
}
}
and transmutes from &[u8] to &BStr (here, for example). That's not an argument that this is a rigorously justified thing to do—my sense from reading the Unsafe Code Guidelines is that it's not yet officially guaranteed to work—but perhaps indicates that it's unlikely to break in practice.
Using unstable features, I think you could also do
fn cast_to_unique(slice: &[i32]) -> &UniqueSlice {
let ptr: *const () = slice.as_ptr().cast();
let len = slice.len();
unsafe { &*std::ptr::from_raw_parts(ptr, len) }
}
I believe repr(transparent) is still necessary for that to be correct. See here and the documentation for the Pointee trait.
You don't need to disassemble and re-assamble the pointer. Pointer casts work directly from unsized type to unsized type as long as the metadata matches.