3 ms·
No, only structs with no invariants. As soon as you have invariants, there are illegal bit patterns. Of course, these illegal bit pattern may not necessarily re
by dbaupp 11y ago
No, only structs with no invariants. As soon as you have invariants, there are illegal bit patterns. Of course, these illegal bit pattern may not necessarily result in memory unsafety, but there's no way for the compiler to know this automatically^.
This functionality could be implemented something like
fn from_bytes<T: JustBits>(bytes: &[u8]) -> Option<&T> {
if bytes.len() >= std::mem::size_of::<T>() {
unsafe {
Some(&*(bytes.as_ptr() as *const T))
}
} else {
None
}
}
/// Values for which any bit pattern is valid.
pub unsafe trait JustBits {}
unsafe impl JustBits for u8 {}
unsafe impl JustBits for i8 {}
unsafe impl JustBits for u16 {}
unsafe impl JustBits for i16 {}
// ...
Some custom struct that can be any bit pattern can then do:
struct CustomStruct { ... }
unsafe impl JustBits for CustomStruct {}
Of course, there's `unsafe` there, but there has to be: it's asserting that "yes, I'm sure that anything works".
^Notably, there's been proposals for `unsafe` fields which will make expressing "invariants exist" more focused, and adjust the trade-offs here.
(I'll note that a TCP header has 3 reserved bits (100, 101, 102) which, I believe, should be set to zero, making some bit patterns theoretically illegal.)