Skip to content

Instantly share code, notes, and snippets.

@luser
Forked from anonymous/playground.rs
Last active May 22, 2017 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luser/c992337384fae88cd5d65f28176bfb07 to your computer and use it in GitHub Desktop.
Save luser/c992337384fae88cd5d65f28176bfb07 to your computer and use it in GitHub Desktop.
Zero-copy struct referencing with alignment checks
use std::borrow::Cow;
use std::mem;
use std::ptr;
use std::slice;
#[derive(Clone)]
struct S {
pub x: u32,
}
fn get_s(bytes: &[u8]) -> Cow<S> {
if bytes.len() < mem::size_of::<S>() {
println!("too small");
Cow::Owned(S { x: 0 })
} else {
let ptr = bytes.as_ptr();
println!("ptr: {:?}", ptr);
if (ptr as usize) % mem::align_of::<S>() == 0 {
println!("aligned: transmuting");
Cow::Borrowed(unsafe { mem::transmute(ptr) })
} else {
println!("unaligned: copying");
unsafe {
Cow::Owned(ptr::read_unaligned(mem::transmute(ptr)))
}
}
}
}
fn main() {
let s = get_s(&[]);
println!("{}", s.x);
let b = &[1, 0, 0, 0];
let s = get_s(b);
println!("{}", s.x);
let sb = S { x: 2 };
let b: &[u8] = unsafe { slice::from_raw_parts(mem::transmute(&sb), mem::size_of::<S>()) };
let s = get_s(b);
println!("{}", s.x);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment