Code shared from the Rust Playground
| fn check_safe_transmute<T: Copy>(buf: &[u8]) { | |
| if buf.len() < ::std::mem::size_of::<T>() { | |
| panic!("Slice has insufficient capacity!"); | |
| } | |
| let p = buf.as_ptr() as usize; | |
| let align_of = ::std::mem::align_of::<T>(); | |
| if align_of > 0 && (p & (align_of - 1)) != 0 { | |
| panic!("Slice has bad alignment!"); | |
| } | |
| } | |
| trait ViewExt { | |
| fn view_as<T>(&self) -> &T where T: Copy; | |
| fn view_mut<T>(&mut self) -> &mut T where T: Copy; | |
| } | |
| impl ViewExt for [u8] { | |
| fn view_as<T>(&self) -> &T where T: Copy { | |
| check_safe_transmute::<T>(self); | |
| unsafe { | |
| &*::std::mem::transmute::<*const u8, *const T>(self.as_ptr()) | |
| } | |
| } | |
| fn view_mut<T>(&mut self) -> &mut T where T: Copy { | |
| check_safe_transmute::<T>(self); | |
| unsafe { | |
| &mut *::std::mem::transmute::<*mut u8, *mut T>(self.as_mut_ptr()) | |
| } | |
| } | |
| } | |
| #[repr(packed)] | |
| #[derive(Clone, Copy, Debug)] | |
| struct Ipv4Addr { | |
| addr: [u8; 4], | |
| } | |
| fn main() { | |
| let mut buf = [0; 8]; | |
| buf[0] = 1; | |
| { | |
| let addr = buf.view_mut::<Ipv4Addr>(); | |
| assert!(addr.addr[0] == 1); | |
| addr.addr[1] = 2; | |
| println!("{:?}", addr); | |
| } | |
| assert!(buf[1] == 2); | |
| println!("{:?}", buf); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment