use ::std::mem; use ::std::io::Write; use ::std::io::Result as IOResult;
use ::std::marker::PhantomData;
#[inline]
pub unsafe fn encode<'a, T: AbomonationRef<'a>, W: Write>(typed: &T, write: &mut W) -> IOResult<()> {
let slice = ::std::slice::from_raw_parts(mem::transmute(typed), mem::size_of::<T>());
write.write_all(slice)?;
typed.entomb(write)?;
Ok(())
}
#[inline]
pub unsafe fn decode<'a, T: AbomonationRef<'a>>(bytes: &'a mut [u8]) -> Option<(&'a T, &'a mut [u8])> {
if bytes.len() < mem::size_of::<T>() { None }
else {
let (split1, split2) = bytes.split_at_mut(mem::size_of::<T>());
let result: &mut T = mem::transmute(split1.get_unchecked_mut(0));
if let Some(remaining) = result.exhume(split2) {
Some((result, remaining))
}
else {
None
}
}
}
#[inline]
pub fn measure<'a, T: AbomonationRef<'a>>(typed: &T) -> usize {
mem::size_of::<T>() + typed.extent()
}
pub trait AbomonationRef<'a> {
#[inline(always)] unsafe fn entomb<W: Write>(&self, _write: &mut W) -> IOResult<()> { Ok(()) }
#[inline(always)] unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> { Some(bytes) }
#[inline(always)] fn extent(&self) -> usize { 0 }
}
#[macro_export]
#[deprecated(since="0.5", note="please use the AbomonationRef<'a>_derive crate")]
macro_rules! unsafe_abomonate_ref {
($t:ty) => {
impl<'a> AbomonationRef<'a> for $t { }
};
($t:ty : $($field:ident),*) => {
impl<'a> AbomonationRef<'a> for $t {
#[inline] unsafe fn entomb<W: ::std::io::Write>(&self, write: &mut W) -> ::std::io::Result<()> {
$( self.$field.entomb(write)?; )*
Ok(())
}
#[inline] unsafe fn exhume<'b>(&'b mut self, mut bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
$( let temp = bytes; bytes = self.$field.exhume(temp)?; )*
Some(bytes)
}
#[inline] fn extent(&self) -> usize {
let mut size = 0;
$( size += self.$field.extent(); )*
size
}
}
};
}
macro_rules! tuple_abomonate {
( $($name:ident)+) => (
impl<'a, $($name: AbomonationRef<'a>),*> AbomonationRef<'a> for ($($name,)*) {
#[allow(non_snake_case)]
#[inline(always)] unsafe fn entomb<WRITE: Write>(&self, write: &mut WRITE) -> IOResult<()> {
let ($(ref $name,)*) = *self;
$($name.entomb(write)?;)*
Ok(())
}
#[allow(non_snake_case)]
#[inline(always)] unsafe fn exhume<'b>(&'b mut self, mut bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
let ($(ref mut $name,)*) = *self;
$( let temp = bytes; bytes = $name.exhume(temp)?; )*
Some(bytes)
}
#[allow(non_snake_case)]
#[inline(always)] fn extent(&self) -> usize {
let mut size = 0;
let ($(ref $name,)*) = *self;
$( size += $name.extent(); )*
size
}
}
);
}
impl<'a> AbomonationRef<'a> for u8 { }
impl<'a> AbomonationRef<'a> for u16 { }
impl<'a> AbomonationRef<'a> for u32 { }
impl<'a> AbomonationRef<'a> for u64 { }
impl<'a> AbomonationRef<'a> for usize { }
impl<'a> AbomonationRef<'a> for i8 { }
impl<'a> AbomonationRef<'a> for i16 { }
impl<'a> AbomonationRef<'a> for i32 { }
impl<'a> AbomonationRef<'a> for i64 { }
impl<'a> AbomonationRef<'a> for isize { }
impl<'a> AbomonationRef<'a> for f32 { }
impl<'a> AbomonationRef<'a> for f64 { }
impl<'a> AbomonationRef<'a> for bool { }
impl<'a> AbomonationRef<'a> for () { }
impl<'a> AbomonationRef<'a> for char { }
impl<'a> AbomonationRef<'a> for ::std::time::Duration { }
impl<'a, T> AbomonationRef<'a> for PhantomData<T> {}
impl<'a, T: AbomonationRef<'a>> AbomonationRef<'a> for Option<T> {
#[inline(always)] unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
if let &Some(ref inner) = self {
inner.entomb(write)?;
}
Ok(())
}
#[inline(always)] unsafe fn exhume<'b>(&'b mut self, mut bytes: &'a mut[u8]) -> Option<&'a mut [u8]> {
if let &mut Some(ref mut inner) = self {
let tmp = bytes; bytes = inner.exhume(tmp)?;
}
Some(bytes)
}
#[inline] fn extent(&self) -> usize {
self.as_ref().map(|inner| inner.extent()).unwrap_or(0)
}
}
impl<'a, T: AbomonationRef<'a>, E: AbomonationRef<'a>> AbomonationRef<'a> for Result<T, E> {
#[inline(always)] unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
match self {
&Ok(ref inner) => inner.entomb(write)?,
&Err(ref inner) => inner.entomb(write)?,
};
Ok(())
}
#[inline(always)] unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut[u8]) -> Option<&'a mut [u8]> {
match self {
&mut Ok(ref mut inner) => inner.exhume(bytes),
&mut Err(ref mut inner) => inner.exhume(bytes),
}
}
#[inline] fn extent(&self) -> usize {
match self {
&Ok(ref inner) => inner.extent(),
&Err(ref inner) => inner.extent(),
}
}
}
tuple_abomonate!(A);
tuple_abomonate!(A B);
tuple_abomonate!(A B C);
tuple_abomonate!(A B C D);
tuple_abomonate!(A B C D E);
tuple_abomonate!(A B C D E F);
tuple_abomonate!(A B C D E F G);
tuple_abomonate!(A B C D E F G H);
tuple_abomonate!(A B C D E F G H I);
tuple_abomonate!(A B C D E F G H I J);
tuple_abomonate!(A B C D E F G H I J K);
tuple_abomonate!(A B C D E F G H I J K L);
tuple_abomonate!(A B C D E F G H I J K L M);
tuple_abomonate!(A B C D E F G H I J K L M N);
tuple_abomonate!(A B C D E F G H I J K L M N O);
tuple_abomonate!(A B C D E F G H I J K L M N O P);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD AE);
tuple_abomonate!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD AE AF);
macro_rules! array_abomonate {
($size:expr) => (
impl<'a, T: AbomonationRef<'a>> AbomonationRef<'a> for [T; $size] {
#[inline(always)]
unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
for element in self { element.entomb(write)?; }
Ok(())
}
#[inline(always)]
unsafe fn exhume<'b>(&'b mut self, mut bytes: &'a mut[u8]) -> Option<&'a mut [u8]> {
for element in self {
let tmp = bytes; bytes = element.exhume(tmp)?;
}
Some(bytes)
}
#[inline(always)] fn extent(&self) -> usize {
let mut size = 0;
for element in self {
size += element.extent();
}
size
}
}
)
}
array_abomonate!(0);
array_abomonate!(1);
array_abomonate!(2);
array_abomonate!(3);
array_abomonate!(4);
array_abomonate!(5);
array_abomonate!(6);
array_abomonate!(7);
array_abomonate!(8);
array_abomonate!(9);
array_abomonate!(10);
array_abomonate!(11);
array_abomonate!(12);
array_abomonate!(13);
array_abomonate!(14);
array_abomonate!(15);
array_abomonate!(16);
array_abomonate!(17);
array_abomonate!(18);
array_abomonate!(19);
array_abomonate!(20);
array_abomonate!(21);
array_abomonate!(22);
array_abomonate!(23);
array_abomonate!(24);
array_abomonate!(25);
array_abomonate!(26);
array_abomonate!(27);
array_abomonate!(28);
array_abomonate!(29);
array_abomonate!(30);
array_abomonate!(31);
array_abomonate!(32);
impl<'a> AbomonationRef<'a> for String {
#[inline]
unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
write.write_all(self.as_bytes())?;
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
if self.len() > bytes.len() { None }
else {
let (mine, rest) = bytes.split_at_mut(self.len());
::std::ptr::write(self, String::from_raw_parts(mem::transmute(mine.as_ptr()), self.len(), self.len()));
Some(rest)
}
}
#[inline] fn extent(&self) -> usize {
self.len()
}
}
impl<'a, T: AbomonationRef<'a>> AbomonationRef<'a> for Vec<T> {
#[inline]
unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
write.write_all(typed_to_bytes(&self[..]))?;
for element in self.iter() { element.entomb(write)?; }
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
let binary_len = self.len() * mem::size_of::<T>();
if binary_len > bytes.len() { None }
else {
let (mine, mut rest) = bytes.split_at_mut(binary_len);
let slice = ::std::slice::from_raw_parts_mut(mine.as_mut_ptr() as *mut T, self.len());
::std::ptr::write(self, Vec::from_raw_parts(slice.as_mut_ptr(), self.len(), self.len()));
for element in self.iter_mut() {
let temp = rest; rest = element.exhume(temp)?;
}
Some(rest)
}
}
#[inline]
fn extent(&self) -> usize {
let mut sum = mem::size_of::<T>() * self.len();
for element in self.iter() {
sum += element.extent();
}
sum
}
}
impl<'a, T: AbomonationRef<'a>> AbomonationRef<'a> for Box<T> {
#[inline]
unsafe fn entomb<W: Write>(&self, bytes: &mut W) -> IOResult<()> {
bytes.write_all(::std::slice::from_raw_parts(mem::transmute(&**self), mem::size_of::<T>()))?;
(**self).entomb(bytes)?;
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
let binary_len = mem::size_of::<T>();
if binary_len > bytes.len() { None }
else {
let (mine, mut rest) = bytes.split_at_mut(binary_len);
::std::ptr::write(self, mem::transmute(mine.as_mut_ptr() as *mut T));
let temp = rest; rest = (**self).exhume(temp)?;
Some(rest)
}
}
#[inline] fn extent(&self) -> usize {
mem::size_of::<T>() + (&**self).extent()
}
}
impl<'a, 'c, T: AbomonationRef<'a>> AbomonationRef<'a> for &'c T where 'a : 'c {
#[inline]
unsafe fn entomb<W: Write>(&self, bytes: &mut W) -> IOResult<()> {
bytes.write_all(::std::slice::from_raw_parts(mem::transmute(&**self), mem::size_of::<T>()))?;
(**self).entomb(bytes)?;
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
let binary_len = mem::size_of::<T>();
if binary_len > bytes.len() { None }
else {
let (mine, mut rest) = bytes.split_at_mut(binary_len);
let mut_ref: &mut T = mem::transmute(mine.as_mut_ptr() as *mut T);
let temp = rest; rest = (*mut_ref).exhume(temp)?;
*self = mut_ref;
Some(rest)
}
}
#[inline] fn extent(&self) -> usize {
mem::size_of::<T>() + (&**self).extent()
}
}
impl<'a, 'c> AbomonationRef<'a> for &'c str where 'a : 'c {
#[inline]
unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
write.write_all(self.as_bytes())?;
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
if self.len() > bytes.len() { None }
else {
let (mine, rest) = bytes.split_at_mut(self.len());
let slice = ::std::slice::from_raw_parts(mine.as_ptr(), self.len());
*self = ::std::str::from_utf8_unchecked(slice);
Some(rest)
}
}
#[inline] fn extent(&self) -> usize {
self.len()
}
}
impl<'a, 'c, T: AbomonationRef<'a>> AbomonationRef<'a> for &'c [T] where 'a : 'c {
#[inline]
unsafe fn entomb<W: Write>(&self, write: &mut W) -> IOResult<()> {
write.write_all(typed_to_bytes(&self[..]))?;
for element in self.iter() { element.entomb(write)?; }
Ok(())
}
#[inline]
unsafe fn exhume<'b>(&'b mut self, bytes: &'a mut [u8]) -> Option<&'a mut [u8]> {
let binary_len = self.len() * mem::size_of::<T>();
if binary_len > bytes.len() { None }
else {
let (mine, mut rest) = bytes.split_at_mut(binary_len);
let slice = ::std::slice::from_raw_parts_mut(mine.as_mut_ptr() as *mut T, self.len());
for element in slice.iter_mut() {
let temp = rest; rest = element.exhume(temp)?;
}
*self = slice;
Some(rest)
}
}
#[inline]
fn extent(&self) -> usize {
let mut sum = mem::size_of::<T>() * self.len();
for element in self.iter() {
sum += element.extent();
}
sum
}
}
#[inline] unsafe fn typed_to_bytes<T>(slice: &[T]) -> &[u8] {
::std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>())
}