Skip to content

Commit

Permalink
Make the writer even more unsafe.
Browse files Browse the repository at this point in the history
Instead of changing the length every write we just adjust the pointer.
This avoids rust-lang/rust#45068.
However we now need to ensure that we set the length when we are done.
  • Loading branch information
jrmuizel committed Oct 6, 2017
1 parent 582b0ac commit eaa5d63
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions webrender_api/src/display_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,15 +492,13 @@ impl<'a, 'b> Serialize for DisplayItemRef<'a, 'b> {
// }
//

struct UnsafeVecWriter<'a>(&'a mut Vec<u8>);
struct UnsafeVecWriter(*mut u8);

impl<'a> Write for UnsafeVecWriter<'a> {
impl Write for UnsafeVecWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unsafe {
let old_len = self.0.len();
self.0.set_len(old_len + buf.len());
debug_assert!(self.0.len() <= self.0.capacity());
ptr::copy_nonoverlapping(buf.as_ptr(), self.0.as_mut_ptr().offset(old_len as isize), buf.len());
ptr::copy_nonoverlapping(buf.as_ptr(), self.0, buf.len());
self.0 = self.0.offset(buf.len() as isize);
}
Ok(buf.len())
}
Expand All @@ -523,7 +521,16 @@ fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: &T) {
bincode::serialize_into(&mut size,e , bincode::Infinite).unwrap();
vec.reserve(size.0);

bincode::serialize_into(&mut UnsafeVecWriter(vec), e, bincode::Infinite).unwrap();
let old_len = vec.len();
let ptr = unsafe { vec.as_mut_ptr().offset(old_len as isize) };
let mut w = UnsafeVecWriter(ptr);
bincode::serialize_into(&mut w, e, bincode::Infinite).unwrap();

// fix up the length
unsafe { vec.set_len(old_len + size.0); }

// make sure we wrote the right amount
debug_assert!(((w.0 as usize) - (vec.as_ptr() as usize)) == vec.len());
}

#[derive(Clone)]
Expand Down

0 comments on commit eaa5d63

Please sign in to comment.