use std::{ mem, fmt, error, str, ptr };
#[derive(Debug)]
pub enum Error {
Utf8Encoding,
ReadingOutOfBounds,
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Utf8Encoding => "Couldn't decode UTF-8 string",
Error::ReadingOutOfBounds => "Attempted to read out of bounds",
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", error::Error::description(self))
}
}
static SIZE_MASKS: [u8; 9] = [
0b00000000,
0b10000000,
0b11000000,
0b11100000,
0b11110000,
0b11111000,
0b11111100,
0b11111110,
0b11111111
];
pub struct Encoder {
data: Vec<u8>,
bool_index: usize,
bool_shift: u8,
}
macro_rules! write_bytes {
($data:expr, $value:ident) => ({
unsafe {
let size = mem::size_of_val(&$value);
let ptr: *const u8 = mem::transmute(&$value.to_be());
let len = $data.len();
$data.reserve(size);
$data.set_len(len + size);
ptr::copy_nonoverlapping(
ptr,
$data.as_mut_ptr().offset(len as isize),
size
);
}
})
}
impl Encoder {
#[inline]
pub fn new() -> Encoder {
Encoder {
data: Vec::new(),
bool_index: std::usize::MAX,
bool_shift: 0,
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> Encoder {
Encoder {
data: Vec::with_capacity(capacity),
bool_index: std::usize::MAX,
bool_shift: 0,
}
}
#[inline]
pub fn uint8(&mut self, uint8: u8) -> &mut Encoder {
self.data.push(uint8);
self
}
#[inline]
pub fn uint16(&mut self, uint16: u16) -> &mut Encoder {
write_bytes!(self.data, uint16);
self
}
#[inline]
pub fn uint32(&mut self, uint32: u32) -> &mut Encoder {
write_bytes!(self.data, uint32);
self
}
#[inline]
pub fn uint64(&mut self, uint64: u64) -> &mut Encoder {
write_bytes!(self.data, uint64);
self
}
#[inline]
pub fn int8(&mut self, int8: i8) -> &mut Encoder {
self.data.push(int8 as u8);
self
}
#[inline]
pub fn int16(&mut self, int16: i16) -> &mut Encoder {
write_bytes!(self.data, int16);
self
}
#[inline]
pub fn int32(&mut self, int32: i32) -> &mut Encoder {
write_bytes!(self.data, int32);
self
}
#[inline]
pub fn int64(&mut self, int64: i64) -> &mut Encoder {
write_bytes!(self.data, int64);
self
}
#[inline]
pub fn float32(&mut self, float32: f32) -> &mut Encoder {
self.uint32(unsafe { mem::transmute(float32) })
}
#[inline]
pub fn float64(&mut self, float64: f64) -> &mut Encoder {
self.uint64(unsafe { mem::transmute(float64) })
}
#[inline]
pub fn bool(&mut self, bool: bool) -> &mut Encoder {
let bool_bit: u8 = if bool { 1 } else { 0 };
let index = self.data.len();
if self.bool_index == index && self.bool_shift < 7 {
self.bool_shift += 1;
self.data[index - 1] = self.data[index - 1] | bool_bit << self.bool_shift;
return self;
}
self.bool_index = index + 1;
self.bool_shift = 0;
self.uint8(bool_bit)
}
#[inline]
pub fn size(&mut self, size: usize) -> &mut Encoder {
if size < 128 {
return self.uint8(size as u8);
}
let mut size = size as u64;
let lead = size.leading_zeros() as usize;
let bytes = if lead == 0 { 9 } else { 9 - (lead - 1) / 7 };
let mut buf: [u8; 9] = unsafe { mem::uninitialized() };
for i in (1 .. bytes).rev() {
buf[i] = size as u8;
size >>= 8;
}
buf[0] = (size as u8) | SIZE_MASKS[bytes - 1];
self.data.extend_from_slice(&buf[0 .. bytes]);
self
}
#[inline]
pub fn bytes(&mut self, bytes: &[u8]) -> &mut Encoder {
self.size(bytes.len());
self.data.extend_from_slice(bytes);
self
}
#[inline]
pub fn string(&mut self, string: &str) -> &mut Encoder {
self.size(string.len());
self.data.extend_from_slice(string.as_bytes());
self
}
#[inline]
pub fn end(&mut self) -> Vec<u8> {
self.bool_index = std::usize::MAX;
self.bool_shift = 0;
mem::replace(&mut self.data, Vec::new())
}
}
pub struct Decoder<'a> {
index: usize,
data: &'a [u8],
bool_index: usize,
bool_shift: u8,
}
macro_rules! read_bytes {
($decoder:expr, $t:ident) => ({
let size = mem::size_of::<$t>();
let end = $decoder.index + size;
if end > $decoder.data.len() {
return Err(Error::ReadingOutOfBounds);
}
unsafe {
let mut value: $t = mem::uninitialized();
let ptr: *mut u8 = mem::transmute(&mut value);
ptr::copy_nonoverlapping(
$decoder.data.as_ptr().offset($decoder.index as isize),
ptr,
size
);
$decoder.index = end;
Ok($t::from_be(value))
}
})
}
impl<'a> Decoder<'a> {
#[inline]
pub fn new(data: &[u8]) -> Decoder {
Decoder {
index: 0,
data: data,
bool_index: std::usize::MAX,
bool_shift: 0,
}
}
#[inline]
pub fn uint8(&mut self) -> Result<u8, Error> {
if self.index >= self.data.len() {
return Err(Error::ReadingOutOfBounds);
}
let uint8 = self.data[self.index];
self.index += 1;
return Ok(uint8);
}
#[inline]
pub fn uint16(&mut self) -> Result<u16, Error> {
read_bytes!(self, u16)
}
#[inline]
pub fn uint32(&mut self) -> Result<u32, Error> {
read_bytes!(self, u32)
}
#[inline]
pub fn uint64(&mut self) -> Result<u64, Error> {
read_bytes!(self, u64)
}
#[inline]
pub fn int8(&mut self) -> Result<i8, Error> {
let uint8 = try!(self.uint8());
Ok(uint8 as i8)
}
#[inline]
pub fn int16(&mut self) -> Result<i16, Error> {
read_bytes!(self, i16)
}
#[inline]
pub fn int32(&mut self) -> Result<i32, Error> {
read_bytes!(self, i32)
}
#[inline]
pub fn int64(&mut self) -> Result<i64, Error> {
read_bytes!(self, i64)
}
#[inline]
pub fn float32(&mut self) -> Result<f32, Error> {
let uint32 = try!(self.uint32());
Ok(unsafe { mem::transmute(uint32) })
}
#[inline]
pub fn float64(&mut self) -> Result<f64, Error> {
let uint64 = try!(self.uint64());
Ok(unsafe { mem::transmute(uint64) })
}
pub fn bool(&mut self) -> Result<bool, Error> {
if self.bool_index == self.index && self.bool_shift < 7 {
self.bool_shift += 1;
let bits = self.data[self.index - 1];
let bool_bit = 1 << self.bool_shift;
return Ok(bits & bool_bit == bool_bit);
}
let bits = try!(self.uint8());
self.bool_index = self.index;
self.bool_shift = 0;
Ok(bits & 1 == 1)
}
pub fn size(&mut self) -> Result<usize, Error> {
let high = try!(self.uint8());
if (high & 128) == 0 {
return Ok(high as usize);
}
let mut ext_bytes = (!high).leading_zeros() as usize;
let mut size = (high ^ SIZE_MASKS[ext_bytes]) as usize;
while ext_bytes != 0 {
ext_bytes -= 1;
size = (size << 8) | try!(self.uint8()) as usize;
}
Ok(size)
}
#[inline]
pub fn bytes(&mut self) -> Result<&[u8], Error> {
let end = try!(self.size()) + self.index;
if end > self.data.len() {
return Err(Error::ReadingOutOfBounds);
}
let bytes = &self.data[self.index .. end];
self.index = end;
Ok(bytes)
}
#[inline]
pub fn string(&mut self) -> Result<&str, Error> {
str::from_utf8(try!(self.bytes())).map_err(|_| Error::Utf8Encoding)
}
#[inline]
pub fn end(&self) -> bool {
self.index >= self.data.len()
}
}