Fixed the conversion code to use macros I wrote.

The previous code was relying on the to_be and to_le functions from the
standard library. These now rely on macros that I wrote to handle the
bit packing and unpacking. These were macros and not functions because
it is really hard to define the types and capabilities needed to
turn them into general functions. As such, the macros should never be
published publically and the Converters should be used for conversions.

The Transmutable property should be used for serialization and internally
the primitive types, Elements, all use the Converter functions and any
other objects should use the Transmutable primitives to build their
binary forms.
This commit is contained in:
2017-02-15 17:51:13 -05:00
parent 8988f9f9ae
commit 03e9484e52
12 changed files with 684 additions and 1260 deletions

View File

@ -1,8 +1,5 @@
use std::mem;
use std::ptr::copy_nonoverlapping;
use ::byte_sized::ByteSized;
use ::byte_sized::{U16_BYTES, U32_BYTES, U64_BYTES};
use ::byte_sized::U64_BYTES;
use ::converter::Converter;
use ::transmutable::Transmutable;
@ -112,108 +109,63 @@ impl Converter for BigEndian
{
fn bytes_to_u16(buffer: &[u8]) -> u16
{
read_bytes!(buffer, u16, to_be)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u16::BYTES);
pack_big_endian!(buffer, u16, u16::BYTES)
}
fn bytes_to_u32(buffer: &[u8]) -> u32
{
read_bytes!(buffer, u32, to_be)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u32::BYTES);
pack_big_endian!(buffer, u32, u32::BYTES)
}
fn bytes_to_u64(buffer: &[u8]) -> u64
{
read_bytes!(buffer, u64, to_be)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u64::BYTES);
pack_big_endian!(buffer, u64, u64::BYTES)
}
fn bytes_to_usize(buffer: &[u8]) -> usize
{
let mut out: [u8; 8];
let ptr_out: *mut u8;
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == usize::BYTES);
assert!(buffer.len() >= 1 && buffer.len() <= 8);
out = [0u8; 8];
ptr_out = out.as_mut_ptr();
unsafe
{
copy_nonoverlapping::<u8>(buffer.as_ptr(),
ptr_out.offset((8 - buffer.len()) as isize),
buffer.len());
(*(ptr_out as *const u64)).to_be() as usize
}
pack_big_endian!(buffer, usize, usize::BYTES)
}
fn u16_to_bytes(num: u16) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u16::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u16, U16_BYTES, num, to_be);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_big_endian!(num, u16::BYTES)
}
fn u32_to_bytes(num: u32) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u32::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u32, U32_BYTES, num, to_be);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_big_endian!(num, u32::BYTES)
}
fn u64_to_bytes(num: u64) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u64::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u64, U64_BYTES, num, to_be);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_big_endian!(num, u64::BYTES)
}
fn usize_to_bytes(num: usize) -> Vec<u8>
{
let bytes: [u8; 8];
let num_bytes: u8;
let mut buffer: Vec<u8>;
num_bytes = usize::BYTES as u8;
// Create a buffer with enough space for this type.
buffer = Vec::with_capacity(usize::BYTES);
assert!(determine_size(num as u64) <= num_bytes && num_bytes <= 8);
unsafe
{
bytes = mem::transmute::<usize, [u8; 8]>(num.to_be());
buffer.extend_from_slice(&bytes);
//copy_nonoverlapping::<u8>(
// bytes.as_ptr().offset((8 - num_bytes) as isize),
// buffer.as_mut_ptr(), num_bytes as usize);
}
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_big_endian!(num, usize::BYTES)
}
fn bytes_to_string(buffer: &[u8]) -> String
@ -285,104 +237,63 @@ impl Converter for LittleEndian
{
fn bytes_to_u16(buffer: &[u8]) -> u16
{
read_bytes!(buffer, u16, to_le)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u16::BYTES);
pack_little_endian!(buffer, u16, u16::BYTES)
}
fn bytes_to_u32(buffer: &[u8]) -> u32
{
read_bytes!(buffer, u32, to_le)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u32::BYTES);
pack_little_endian!(buffer, u32, u32::BYTES)
}
fn bytes_to_u64(buffer: &[u8]) -> u64
{
read_bytes!(buffer, u64, to_le)
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == u64::BYTES);
pack_little_endian!(buffer, u64, u64::BYTES)
}
fn bytes_to_usize(buffer: &[u8]) -> usize
{
let mut out: [u8; 8];
let ptr_out: *mut u8;
// Make sure that there is enough space to read
// a value from the buffer.
assert!(buffer.len() == usize::BYTES);
assert!(buffer.len() >= 1 && buffer.len() <= 8);
out = [0u8; 8];
ptr_out = out.as_mut_ptr();
unsafe
{
copy_nonoverlapping::<u8>(buffer.as_ptr(), ptr_out, buffer.len());
(*(ptr_out as *const u64)).to_le() as usize
}
pack_little_endian!(buffer, usize, usize::BYTES)
}
fn u16_to_bytes(num: u16) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u16::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u16, U16_BYTES, num, to_le);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_little_endian!(num, u16::BYTES)
}
fn u32_to_bytes(num: u32) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u32::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u32, U32_BYTES, num, to_le);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_little_endian!(num, u32::BYTES)
}
fn u64_to_bytes(num: u64) -> Vec<u8>
{
let mut buffer: Vec<u8>;
// Create the Vector to hold the bytes
// from this type.
buffer = Vec::with_capacity(u64::BYTES);
// Write the bytes to the Vector.
write_bytes!(buffer, u64, U64_BYTES, num, to_le);
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_little_endian!(num, u64::BYTES)
}
fn usize_to_bytes(num: usize) -> Vec<u8>
{
let bytes: [u8; 8];
let num_bytes: u8;
let mut buffer: Vec<u8>;
num_bytes = usize::BYTES as u8;
// Create a buffer with enough space for this type.
buffer = Vec::with_capacity(usize::BYTES);
assert!(determine_size(num as u64) <= num_bytes && num_bytes <= 8);
unsafe
{
bytes = mem::transmute::<usize, [u8; 8]>(num.to_le());
buffer.extend_from_slice(&bytes);
//copy_nonoverlapping::<u8>(bytes.as_ptr(), buffer.as_mut_ptr(),
// num_bytes as usize);
}
// Return the byte buffer.
buffer
// Unpack the value into it's byte form.
unpack_little_endian!(num, usize::BYTES)
}
fn bytes_to_string(buffer: &[u8]) -> String
@ -396,7 +307,7 @@ impl Converter for LittleEndian
// Strings start with the size of bytes to read as
// a u64. So read that in and then we know how many
// bytes make up the string.
byte_count = BigEndian::bytes_to_u64(&buffer[0..U64_BYTES]);
byte_count = LittleEndian::bytes_to_u64(&buffer[0..U64_BYTES]);
if byte_count > 0
{
@ -493,8 +404,6 @@ impl ::std::fmt::Display for Endianess
pub fn network_to_platform_order<T>(val: T) -> T
where T: Transmutable
{
let buffer: Vec<u8>;
// Determine what endianess the Platform is using.
if cfg!(target_endian="big")
{
@ -504,9 +413,7 @@ pub fn network_to_platform_order<T>(val: T) -> T
}
else
{
// Convert the value from Big endian to Little endian.
buffer = val.as_endian_bytes(Endianess::Network);
T::from_endian_bytes(buffer.as_slice(), Endianess::Platform)
T::from_endian_bytes(val.as_bytes().as_slice(), Endianess::Platform)
}
}
@ -514,8 +421,6 @@ pub fn network_to_platform_order<T>(val: T) -> T
pub fn platform_to_network_order<T>(val: T) -> T
where T: Transmutable
{
let buffer: Vec<u8>;
// Determine what endianess the Platform is using.
if cfg!(target_endian="big")
{
@ -525,9 +430,7 @@ pub fn platform_to_network_order<T>(val: T) -> T
}
else
{
// Convert the value from Little endian to Big endian.
buffer = val.as_endian_bytes(Endianess::Platform);
T::from_endian_bytes(buffer.as_slice(), Endianess::Network)
T::from_endian_bytes(val.as_bytes().as_slice(), Endianess::Platform)
}
}
@ -549,43 +452,3 @@ pub fn get_platform_endianess() -> Endianess
Endianess::Little
}
}
/// 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
}
}