Skip to content

Commit

Permalink
Use aligned reads and writes in the abomonation implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
HadrienG2 committed Nov 11, 2019
1 parent b618538 commit 952a208
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 215 deletions.
26 changes: 22 additions & 4 deletions src/align/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use std::{
io::Write,
mem,
mem::{self, MaybeUninit},
ptr::NonNull,
};

Expand Down Expand Up @@ -77,9 +77,27 @@ impl<W: Write> AlignedWriter<W> {
self.written_so_far += 1;
}

// Write down the binary data and exit
// FIXME: Move write_bytes functionality here
crate::write_bytes(&mut self.inner, data)?;
// This is the correct way to reinterpret typed data as bytes, it
// accounts for the fact that T may contain padding bytes.
let bytes = std::slice::from_raw_parts(
data.as_ptr() as *const MaybeUninit<u8>,
data.len() * mem::size_of::<T>()
);

// FIXME: Unfortunately, `Write::write_all()` expects initialized
// bytes. This transmute is undefined behavior if T contains
// uninitialized padding bytes.
//
// To resolve this UB, we'd need either a "freeze" operation
// that turns uninitialized bytes into arbitrary initialized
// bytes, or a `Write` interface that accepts uninit bytes.
//
// See this Rust internals forum topic for more discussion:
// https://internals.rust-lang.org/t/writing-down-binary-data-with-padding-bytes/11197/
//
self.inner.write_all(mem::transmute::<&[MaybeUninit<u8>], &[u8]>(bytes))?;

// Keep track of the amount of emitted data and exit
self.written_so_far += mem::size_of_val::<[T]>(data);
Ok(())
}
Expand Down
Loading

0 comments on commit 952a208

Please sign in to comment.