use std::any::Any;
use byteorder::{WriteBytesExt, LittleEndian, BigEndian};
use extprim::i128::i128;
use extprim::u128::u128;
use error;
macro_rules! impl_serialize {
($type:path, $write:path) => {
impl Serialize for $type {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
$write(buffer, *self)?;
Ok(())
}
}
};
}
pub trait Serialize {
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()>;
}
impl Serialize for bool {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
if *self {
buffer.write_i32::<LittleEndian>(-1720552011)?;
} else {
buffer.write_i32::<LittleEndian>(-1132882121)?;
}
Ok(())
}
}
impl Serialize for i8 {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
buffer.push(*self as u8);
Ok(())
}
}
impl Serialize for u8 {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
buffer.push(*self);
Ok(())
}
}
impl_serialize!(i16, WriteBytesExt::write_i16<LittleEndian>);
impl_serialize!(i32, WriteBytesExt::write_i32<LittleEndian>);
impl_serialize!(i64, WriteBytesExt::write_i64<LittleEndian>);
impl_serialize!(u16, WriteBytesExt::write_u16<LittleEndian>);
impl_serialize!(u32, WriteBytesExt::write_u32<LittleEndian>);
impl_serialize!(u64, WriteBytesExt::write_u64<LittleEndian>);
impl_serialize!(f32, WriteBytesExt::write_f32<LittleEndian>);
impl_serialize!(f64, WriteBytesExt::write_f64<LittleEndian>);
impl Serialize for i128 {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
self.as_u128().serialize_to(buffer)
}
}
impl Serialize for u128 {
#[inline]
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
buffer.write_u64::<BigEndian>(self.high64())?;
buffer.write_u64::<BigEndian>(self.low64())?;
Ok(())
}
}
impl Serialize for (i128, i128) {
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
self.1.serialize_to(buffer)?;
self.0.serialize_to(buffer)?;
Ok(())
}
}
impl Serialize for String {
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
let len = self.len();
if len <= 253 {
buffer.push(len as u8);
} else {
buffer.push(254);
buffer.write_uint::<LittleEndian>(len as u64, 3)?;
}
buffer.extend(self.as_bytes());
let rem = len % 4;
if rem > 0 {
for _ in 0..(4 - rem) {
buffer.push(0);
}
}
Ok(())
}
}
impl<T: Serialize> Serialize for Vec<T> {
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
buffer.write_u32::<LittleEndian>(0x1cb5c415u32)?;
let len = buffer.len() as u32;
buffer.write_u32::<LittleEndian>(len)?;
for element in self {
element.serialize_to(buffer)?;
}
Ok(())
}
}
impl Serialize for Box<Any> {
fn serialize_to(&self, buffer: &mut Vec<u8>) -> error::Result<()> {
match self.downcast_ref::<Box<Serialize>>() {
Some(as_ser) => as_ser.serialize_to(buffer),
None => {
panic!("Serialize not implemented")
}
}
}
}