Skip to content

Instantly share code, notes, and snippets.

@rklaehn
Created September 3, 2020 09:28
Show Gist options
  • Save rklaehn/84eaad6af3171a653ccc5f1abc03845c to your computer and use it in GitHub Desktop.
Save rklaehn/84eaad6af3171a653ccc5f1abc03845c to your computer and use it in GitHub Desktop.
/// This abomination only works if the underlying bytes are known in number (Sized),
/// can be moved around in memory (Unpin) and do no hold on to other things than the
/// underlying bytes ('static).
#[cfg(feature = "dataflow")]
impl<T: Abomonation + 'static + Sized + Unpin> Abomonation for ArcVal<T> {
unsafe fn entomb<W: std::io::Write>(&self, write: &mut W) -> std::io::Result<()> {
/* Since the value T has not yet been seen by abomonate (it is behind a pointer)
* we need to fully encode it.
*/
abomonation::encode(self.deref(), write)
}
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
use std::{mem, ptr};
/* The idea here is to construct a new Arc<T> from the entombed bytes.
* The state of this ArcVal upon entry of this function contains only an invalid
* pointer to an ArcInner that we need to dispose of without trying to run
* its destructor (which would panic).
*/
let (value, bytes) = abomonation::decode::<T>(bytes)?;
// value is just a reference to the first part of old bytes, so move it into a new Arc
let arc = Arc::new(ptr::read(value));
// now swap the fresh arc into its place ...
let garbage = mem::replace(&mut self.0, arc);
// ... and forget about the old one
mem::forget(garbage);
Some(bytes)
}
fn extent(&self) -> usize {
std::mem::size_of::<T>() + self.deref().extent()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment