From aa4bb78f660f41a4920ed76e09d3bbb5130a0c91 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Thu, 7 Jan 2016 05:10:50 -0500 Subject: [PATCH] Vector types are now Transmutable. A Vector can now be converted to and from bytes of data. I'm not entirely sure that the structure bytes do not have to be handled for endianess, but the underlying basic types are correctly handled. Tests and and example have also be created. The tests lib file was split into a converter test file and a transmutable test file. --- examples/convert_f32.rs | 42 ++++++++++++++- examples/convert_vector2.rs | 86 ++++++++++++++++++++++++++++++ src/transmutable.rs | 96 +++++++++++++++++++++++++++++++++- tests/{lib.rs => converter.rs} | 8 ++- tests/transmutable.rs | 50 ++++++++++++++++++ 5 files changed, 274 insertions(+), 8 deletions(-) create mode 100644 examples/convert_vector2.rs rename tests/{lib.rs => converter.rs} (98%) create mode 100644 tests/transmutable.rs diff --git a/examples/convert_f32.rs b/examples/convert_f32.rs index 4ba1759..e698501 100644 --- a/examples/convert_f32.rs +++ b/examples/convert_f32.rs @@ -4,11 +4,11 @@ extern crate alchemy; use alchemy::F32_BYTES; -use alchemy::{Converter, PlatformEndian}; +use alchemy::{Converter, Endianess, PlatformEndian, Transmutable}; -pub fn main() +fn use_converter() { let num: f32; let final_num: f32; @@ -31,6 +31,31 @@ pub fn main() println!("The buffer converts back to: {}", final_num); } +pub fn use_transmutable() +{ + let num: f32; + let final_num: f32; + let endianess: Endianess; + let mut buffer: [u8; F32_BYTES]; + + // Initialize the variables. + num = 6.291985f32; + buffer = [0u8; F32_BYTES]; + endianess = Endianess::PLATFORM; + + println!("Converting the value {} into and out of an array of bytes.", num); + println!("Buffer starts as: {}", stringify_array(&buffer)); + + // Convert the floating point number into an array of bytes. + num.to_bytes(&mut buffer, endianess); + + println!("Buffer contains: {}", stringify_array(&buffer)); + + // Convert the array of bytes into a floating point number. + final_num = f32::from_bytes(&buffer, endianess); + println!("The buffer converts back to: {}", final_num); +} + /// This just help pretty up the printing of an array of bytes. fn stringify_array(buffer: &[u8]) -> String { @@ -68,3 +93,16 @@ fn stringify_array(buffer: &[u8]) -> String result.push_str("]"); result } + + +pub fn main() +{ + println!("Using converter:"); + use_converter(); + + println!(""); + + println!("Using transmutable:"); + use_transmutable(); +} + diff --git a/examples/convert_vector2.rs b/examples/convert_vector2.rs new file mode 100644 index 0000000..1679afb --- /dev/null +++ b/examples/convert_vector2.rs @@ -0,0 +1,86 @@ +#![feature(convert)] + +extern crate alchemy; +extern crate sigils; + + + +use alchemy::U64_BYTES; +use alchemy::{Endianess, Transmutable}; +use sigils::vector::Vector2; + + + +/// The size of 2 u64 whole numbers. +/// This would be different if the contained type +/// was something different, like an i16 or f32. +const SIZE_OF_VECTOR_2: usize = U64_BYTES * 2; + + + +/// This just help pretty up the printing of an array of bytes. +fn stringify_array(buffer: &[u8]) -> String +{ + let mut result: String; + let mut count: usize; + + // Create a new string that starts with just + // the array opening bracket. + result = String::new(); + result.push_str("["); + + // Loop through the buffer keeping track + // of our place in it. + count = 0usize; + for byte in buffer + { + // Handle priting the last value differently. + if count >= buffer.len() - 1 + { + result.push_str(byte.to_string().as_str()); + } + else + { + result.push_str(byte.to_string().as_str()); + result.push_str(", "); + } + + // Mark that we are going to look at + // the next byte in the array. + count += 1; + } + + // Add the array closing bracket and + // return the new String. + result.push_str("]"); + result +} + + +pub fn main() +{ + let vec: Vector2; + let final_vec: Vector2; + let endianess: Endianess; + let mut buffer: [u8; SIZE_OF_VECTOR_2]; + + // Initialize the variables. + vec = Vector2::::new(629u64, 1985u64); + buffer = [0u8; SIZE_OF_VECTOR_2]; + endianess = Endianess::PLATFORM; + + println!("Transmuting a Vector2:"); + + println!("Converting the value [{}, {}] into and out of an array of bytes.", + vec.x, vec.y); + println!("Buffer starts as: {}", stringify_array(&buffer)); + + // Convert the Vector2 into an array of bytes. + vec.to_bytes(&mut buffer, endianess); + + println!("Buffer contains: {}", stringify_array(&buffer)); + + // Convert the array of bytes into a Vector2. + final_vec = Vector2::from_bytes(&buffer, endianess); + println!("The buffer converts back to: [{}, {}]", final_vec.x, final_vec.y); +} diff --git a/src/transmutable.rs b/src/transmutable.rs index 4ab6b80..dbba8d7 100644 --- a/src/transmutable.rs +++ b/src/transmutable.rs @@ -1,5 +1,5 @@ use sigils::{Zero, Number}; -use sigils::vector::{Vector, Vector2}; +use sigils::vector::{Vector, Vector2, Vector3, Vector4}; use ::byte_sized::ByteSized; use ::converter::Converter; @@ -408,3 +408,97 @@ impl Transmutable for Vector2 where T: Number + ByteSized + Transmutable vec } } + +impl Transmutable for Vector3 where T: Number + ByteSized + Transmutable +{ + fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) + { + let byte_size: usize; + let num_bytes: usize; + + // Determine the number of bytes requires to + // represent a Vector3. + byte_size = T::get_byte_size(); + num_bytes = byte_size * self.get_size() as usize; + + // Make sure that there is enough space to store + // the bytes from this type. + assert!(buffer.len() >= num_bytes); + + // Convert this to bytes and add it to the buffer. + self.x.to_bytes(&mut buffer[0..byte_size], endianess); + self.y.to_bytes(&mut buffer[byte_size..(byte_size*2)], endianess); + self.z.to_bytes(&mut buffer[(byte_size*2)..num_bytes], endianess); + } + + fn from_bytes(buffer: &[u8], endianess: Endianess) -> Vector3 + { + let byte_size: usize; + let num_bytes: usize; + let mut vec: Vector3; + + // Determine the number of bytes requires to + // represent a Vector3. + vec = Vector3::::zero(); + byte_size = T::get_byte_size(); + num_bytes = byte_size * vec.get_size() as usize; + + // Make sure that there is enough data to read + // the bytes for this type. + assert!(buffer.len() >= num_bytes); + + // Convert the given bytes to this type and return it. + vec.x = T::from_bytes(&buffer[0..byte_size], endianess); + vec.y = T::from_bytes(&buffer[byte_size..(byte_size*2)], endianess); + vec.z = T::from_bytes(&buffer[(byte_size*2)..num_bytes], endianess); + vec + } +} + +impl Transmutable for Vector4 where T: Number + ByteSized + Transmutable +{ + fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) + { + let byte_size: usize; + let num_bytes: usize; + + // Determine the number of bytes requires to + // represent a Vector4. + byte_size = T::get_byte_size(); + num_bytes = byte_size * self.get_size() as usize; + + // Make sure that there is enough space to store + // the bytes from this type. + assert!(buffer.len() >= num_bytes); + + // Convert this to bytes and add it to the buffer. + self.x.to_bytes(&mut buffer[0..byte_size], endianess); + self.y.to_bytes(&mut buffer[byte_size..(byte_size*2)], endianess); + self.z.to_bytes(&mut buffer[(byte_size*2)..(byte_size*3)], endianess); + self.w.to_bytes(&mut buffer[(byte_size*3)..num_bytes], endianess); + } + + fn from_bytes(buffer: &[u8], endianess: Endianess) -> Vector4 + { + let byte_size: usize; + let num_bytes: usize; + let mut vec: Vector4; + + // Determine the number of bytes requires to + // represent a Vector4. + vec = Vector4::::zero(); + byte_size = T::get_byte_size(); + num_bytes = byte_size * vec.get_size() as usize; + + // Make sure that there is enough data to read + // the bytes for this type. + assert!(buffer.len() >= num_bytes); + + // Convert the given bytes to this type and return it. + vec.x = T::from_bytes(&buffer[0..byte_size], endianess); + vec.y = T::from_bytes(&buffer[byte_size..(byte_size*2)], endianess); + vec.z = T::from_bytes(&buffer[(byte_size*2)..(byte_size*3)], endianess); + vec.w = T::from_bytes(&buffer[(byte_size*3)..num_bytes], endianess); + vec + } +} diff --git a/tests/lib.rs b/tests/converter.rs similarity index 98% rename from tests/lib.rs rename to tests/converter.rs index 311c62c..8c7f87c 100644 --- a/tests/lib.rs +++ b/tests/converter.rs @@ -1,5 +1,3 @@ -#![feature(zero_one)] - extern crate rand; extern crate alchemy; @@ -49,6 +47,7 @@ macro_rules! full_check_impl ($T: ident, $read_func: ident, $write_func: ident, $numBytes: expr) => { { + use std::$T; use rand::ThreadRng; use rand::distributions::{IndependentSample, Range}; use alchemy::{Converter, BigEndian, LittleEndian}; @@ -57,7 +56,7 @@ macro_rules! full_check_impl let mut rng: ThreadRng; rng = rand::thread_rng(); - range = Range::new(std::$T::MIN, std::$T::MAX); + range = Range::new($T::MIN, $T::MAX); for _ in 0..EXHAUSTIVE_RUNS { let val: $T; @@ -116,7 +115,7 @@ macro_rules! overflow_impl $read_func: ident, $write_func: ident) => { use alchemy::{Converter, BigEndian, LittleEndian}; - + use sigils::Zero; #[test] @@ -171,7 +170,6 @@ macro_rules! test_buffer_overflow mod $mod_name { use alchemy::$numBytes; - use std::num::Zero; overflow_impl!($numBytes, $T, $read_func, $write_func); } diff --git a/tests/transmutable.rs b/tests/transmutable.rs new file mode 100644 index 0000000..a6a8c1a --- /dev/null +++ b/tests/transmutable.rs @@ -0,0 +1,50 @@ +extern crate rand; + +extern crate alchemy; +extern crate sigils; + + + +macro_rules! transmutation_test +{ + ($modName: ident, $varType: ident, $numBytes: expr, [$($var: ident)*]) => + { + mod $modName + { + use rand::{thread_rng, Rng, ThreadRng}; + + use alchemy::{Endianess, Transmutable}; + use sigils::Zero; + use sigils::vector::$varType; + + + + #[test] + pub fn transmutation() + { + let mut vec: $varType; + let final_vec: $varType; + let endianess: Endianess; + let mut rng: ThreadRng; + let mut buffer: [u8; $numBytes]; + + // Initialize the variables. + rng = thread_rng(); + vec = $varType::::zero(); + $(vec.$var = rng.next_u64();)* + buffer = [0u8; $numBytes]; + endianess = Endianess::PLATFORM; + + vec.to_bytes(&mut buffer, endianess); + final_vec = $varType::from_bytes(&buffer, endianess); + + $(assert_eq!(vec.$var, final_vec.$var);)* + } + } + } +} + + +transmutation_test!(vec2, Vector2, 16, [x y]); +transmutation_test!(vec3, Vector3, 24, [x y z]); +transmutation_test!(vec4, Vector4, 32, [x y z w]);