2015-12-30 17:06:48 -05:00
|
|
|
use std::mem;
|
|
|
|
use std::ptr::copy_nonoverlapping;
|
|
|
|
|
2016-01-06 23:37:18 -05:00
|
|
|
use ::byte_sized::ByteSized;
|
|
|
|
use ::byte_sized::{U16_BYTES, U32_BYTES, U64_BYTES};
|
2016-01-05 17:46:31 -05:00
|
|
|
use ::converter::Converter;
|
|
|
|
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
|
|
|
|
/// Defines the current platforms endianess.
|
|
|
|
/// This is can only be big endian or little endian.
|
|
|
|
/// This library does not support a mixed endian setting.
|
|
|
|
#[cfg(target_endian="big")]
|
|
|
|
pub type PlatformEndian = BigEndian;
|
|
|
|
|
|
|
|
/// Defines the current platforms endianess.
|
|
|
|
/// This is can only be BigEndian or LittleEndian.
|
|
|
|
/// This library does not support a mixed endian setting.
|
|
|
|
///
|
|
|
|
/// Defaults to LittleEndian.
|
|
|
|
//#[cfg(target_endian="little")]
|
|
|
|
#[cfg(not(target_endian="big"))]
|
|
|
|
pub type PlatformEndian = LittleEndian;
|
|
|
|
|
2016-01-19 12:02:53 -05:00
|
|
|
/// Handles serialization where the most
|
|
|
|
/// significant byte is stored at the lowest address.
|
|
|
|
pub enum BigEndian
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles serialization where the most
|
|
|
|
/// significant byte is stored at the lowest address.
|
|
|
|
pub enum LittleEndian
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-01-05 17:46:31 -05:00
|
|
|
/// Create an enumeration of the different
|
|
|
|
/// available endianesses.
|
2016-01-06 23:37:18 -05:00
|
|
|
#[derive(Clone, Copy)]
|
2016-01-05 17:46:31 -05:00
|
|
|
pub enum Endianess
|
|
|
|
{
|
|
|
|
/// Referes to BigEndian.
|
|
|
|
BIG,
|
|
|
|
|
|
|
|
/// Referes to LittleEndian.
|
|
|
|
LITTLE,
|
|
|
|
|
|
|
|
/// Referes to PlatformEndian. This can be anyone
|
|
|
|
/// of the other available endians depending on
|
|
|
|
/// the platform you are on.
|
|
|
|
PLATFORM
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
/// Handles reading bytes from a given buffer
|
|
|
|
/// and turning them into the requested type.
|
|
|
|
macro_rules! read_bytes
|
|
|
|
{
|
2016-01-02 14:54:03 -05:00
|
|
|
($buffer: expr, $returnType: ident, $convertFunc: ident) =>
|
2015-12-30 17:06:48 -05:00
|
|
|
({
|
2016-01-03 03:22:21 -05:00
|
|
|
// Make sure that there is enough space to read
|
|
|
|
// a value from the buffer.
|
|
|
|
assert!($buffer.len() == $returnType::BYTES);
|
|
|
|
|
2015-12-30 17:06:48 -05:00
|
|
|
unsafe
|
|
|
|
{
|
2016-01-02 14:54:03 -05:00
|
|
|
(*($buffer.as_ptr() as *const $returnType)).$convertFunc()
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles turning a given number into bytes
|
|
|
|
/// and writing them to a buffer.
|
|
|
|
macro_rules! write_bytes
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
($buffer: expr, $valueType: ident, $numBytes: expr, $num: expr, $convertFunc: ident) =>
|
2015-12-30 17:06:48 -05:00
|
|
|
({
|
2016-01-03 03:22:21 -05:00
|
|
|
assert!($buffer.len() >= $valueType::BYTES,
|
|
|
|
"Not enough room in the buffer to write to.");
|
2015-12-30 17:06:48 -05:00
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
let size: usize;
|
2016-01-06 23:37:18 -05:00
|
|
|
let bytes: [u8; $numBytes];
|
2015-12-30 17:06:48 -05:00
|
|
|
|
2016-01-06 23:37:18 -05:00
|
|
|
size = $valueType::BYTES;
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
bytes =
|
2016-01-06 23:37:18 -05:00
|
|
|
mem::transmute::<_, [u8; $numBytes]>($num.$convertFunc());
|
2016-01-02 14:54:03 -05:00
|
|
|
copy_nonoverlapping::<u8>((&bytes).as_ptr(),
|
|
|
|
$buffer.as_mut_ptr(),
|
|
|
|
size);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-01-05 17:46:31 -05:00
|
|
|
impl Converter for BigEndian
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
fn bytes_to_u16(buffer: &[u8]) -> u16
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u16, to_be)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bytes_to_u32(buffer: &[u8]) -> u32
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u32, to_be)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bytes_to_u64(buffer: &[u8]) -> u64
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u64, to_be)
|
|
|
|
}
|
|
|
|
|
2016-01-02 14:54:03 -05:00
|
|
|
fn bytes_to_usize(buffer: &[u8]) -> usize
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
let mut out: [u8; 8];
|
|
|
|
let ptr_out: *mut u8;
|
|
|
|
|
2016-01-02 23:16:39 -05:00
|
|
|
assert!(buffer.len() >= 1 && buffer.len() <= 8);
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
out = [0u8; 8];
|
|
|
|
ptr_out = out.as_mut_ptr();
|
|
|
|
unsafe
|
|
|
|
{
|
2016-01-02 14:54:03 -05:00
|
|
|
copy_nonoverlapping::<u8>(buffer.as_ptr(),
|
|
|
|
ptr_out.offset((8 - buffer.len()) as isize),
|
|
|
|
buffer.len());
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
(*(ptr_out as *const u64)).to_be() as usize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn u16_to_bytes(buffer: &mut [u8], num: u16)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u16, U16_BYTES, num, to_be);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn u32_to_bytes(buffer: &mut [u8], num: u32)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u32, U32_BYTES, num, to_be);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn u64_to_bytes(buffer: &mut [u8], num: u64)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u64, U64_BYTES, num, to_be);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
2016-01-02 14:54:03 -05:00
|
|
|
fn usize_to_bytes(buffer: &mut [u8], num: usize)
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
let bytes: [u8; 8];
|
2016-01-02 14:54:03 -05:00
|
|
|
let num_bytes: u8;
|
|
|
|
|
|
|
|
num_bytes = buffer.len() as u8;
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
assert!(determine_size(num as u64) <= num_bytes && num_bytes <= 8);
|
2016-01-02 23:16:39 -05:00
|
|
|
assert!(buffer.len() >= 1 && buffer.len() <= 8);
|
2016-01-02 14:54:03 -05:00
|
|
|
|
2015-12-30 17:06:48 -05:00
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
bytes = mem::transmute::<usize, [u8; 8]>(num.to_be());
|
2016-01-02 14:54:03 -05:00
|
|
|
copy_nonoverlapping::<u8>(
|
|
|
|
bytes.as_ptr().offset((8 - num_bytes) as isize),
|
|
|
|
buffer.as_mut_ptr(), num_bytes as usize);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-05 17:46:31 -05:00
|
|
|
impl Converter for LittleEndian
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
fn bytes_to_u16(buffer: &[u8]) -> u16
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u16, to_le)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bytes_to_u32(buffer: &[u8]) -> u32
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u32, to_le)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bytes_to_u64(buffer: &[u8]) -> u64
|
|
|
|
{
|
|
|
|
read_bytes!(buffer, u64, to_le)
|
|
|
|
}
|
|
|
|
|
2016-01-02 14:54:03 -05:00
|
|
|
fn bytes_to_usize(buffer: &[u8]) -> usize
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
let mut out: [u8; 8];
|
|
|
|
let ptr_out: *mut u8;
|
|
|
|
|
2016-01-02 23:16:39 -05:00
|
|
|
assert!(buffer.len() >= 1 && buffer.len() <= 8);
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
out = [0u8; 8];
|
|
|
|
ptr_out = out.as_mut_ptr();
|
|
|
|
unsafe
|
|
|
|
{
|
2016-01-02 14:54:03 -05:00
|
|
|
copy_nonoverlapping::<u8>(buffer.as_ptr(), ptr_out, buffer.len());
|
2015-12-30 17:06:48 -05:00
|
|
|
(*(ptr_out as *const u64)).to_le() as usize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn u16_to_bytes(buffer: &mut [u8], num: u16)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u16, U16_BYTES, num, to_le);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn u32_to_bytes(buffer: &mut [u8], num: u32)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u32, U32_BYTES, num, to_le);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn u64_to_bytes(buffer: &mut [u8], num: u64)
|
|
|
|
{
|
2016-01-06 23:37:18 -05:00
|
|
|
write_bytes!(buffer, u64, U64_BYTES, num, to_le);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
|
2016-01-02 14:54:03 -05:00
|
|
|
fn usize_to_bytes(buffer: &mut [u8], num: usize)
|
2015-12-30 17:06:48 -05:00
|
|
|
{
|
|
|
|
let bytes: [u8; 8];
|
2016-01-02 14:54:03 -05:00
|
|
|
let num_bytes: u8;
|
|
|
|
|
|
|
|
num_bytes = buffer.len() as u8;
|
2015-12-30 17:06:48 -05:00
|
|
|
|
|
|
|
assert!(determine_size(num as u64) <= num_bytes && num_bytes <= 8);
|
2016-01-02 23:16:39 -05:00
|
|
|
assert!(buffer.len() >= 1 && buffer.len() <= 8);
|
2016-01-02 14:54:03 -05:00
|
|
|
|
2015-12-30 17:06:48 -05:00
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
bytes = mem::transmute::<usize, [u8; 8]>(num.to_le());
|
2016-01-02 14:54:03 -05:00
|
|
|
copy_nonoverlapping::<u8>(bytes.as_ptr(), buffer.as_mut_ptr(),
|
|
|
|
num_bytes as usize);
|
2015-12-30 17:06:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Determine the amount of bytes required to
|
|
|
|
/// represent the given number.
|
|
|
|
fn determine_size(num: u64) -> u8
|
|
|
|
{
|
|
|
|
if num < (1 << 8)
|
|
|
|
{
|
|
|
|
1
|
|
|
|
}
|
|
|
|
else if num < (1 << 16)
|
|
|
|
{
|
|
|
|
2
|
|
|
|
}
|
|
|
|
else if num < (1 << 24)
|
|
|
|
{
|
|
|
|
3
|
|
|
|
}
|
|
|
|
else if num < (1 << 32)
|
|
|
|
{
|
|
|
|
4
|
|
|
|
}
|
|
|
|
else if num < (1 << 40)
|
|
|
|
{
|
|
|
|
5
|
|
|
|
}
|
|
|
|
else if num < (1 << 48)
|
|
|
|
{
|
|
|
|
6
|
|
|
|
}
|
|
|
|
else if num < (1 << 56)
|
|
|
|
{
|
|
|
|
7
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
8
|
|
|
|
}
|
|
|
|
}
|