use sigils::{Zero, Number}; use sigils::vector::{Vector, Vector2}; use ::byte_sized::ByteSized; use ::converter::Converter; use ::endian::{BigEndian, LittleEndian, PlatformEndian, Endianess}; /// Handles the repetative endianess matching /// for the primitive number types when converting /// a number to bytes. macro_rules! handle_endianess_to_bytes { ($buffer: ident, $val: ident, $endianess: ident, $func: ident) => { { let mut mut_buffer; mut_buffer = $buffer; match $endianess { Endianess::BIG => { BigEndian::$func(&mut mut_buffer, *$val); } Endianess::LITTLE => { LittleEndian::$func(&mut mut_buffer, *$val); } Endianess::PLATFORM => { PlatformEndian::$func(&mut mut_buffer, *$val); } } } } } /// Handles the repetative endianess matching /// for the primitive number types when converting /// a number from bytes. macro_rules! handle_endianess_from_bytes { ($buffer: ident, $endianess: ident, $func: ident) => { match $endianess { Endianess::BIG => { BigEndian::$func(&$buffer) } Endianess::LITTLE => { LittleEndian::$func(&$buffer) } Endianess::PLATFORM => { PlatformEndian::$func(&$buffer) } } } } // From and Into are not used because we need to also // know the endianess to use for converting. /// A type that can be converted to and from bytes. pub trait Transmutable { /// Transmute this type to an array of bytes. fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess); /// Transmute an array of bytes to this type. fn from_bytes(buffer: &[u8], endianess: Endianess) -> Self; } impl Transmutable for u8 { #[allow(unused_variables)] fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= u8::BYTES); // Convert this to bytes and add it to the buffer. // Endianess doesn't matter here. buffer[0] = *self; } #[allow(unused_variables)] fn from_bytes(buffer: &[u8], endianess: Endianess) -> u8 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= u8::BYTES); // Convert the given bytes to this type and return it. // Endianess doesn't matter here. buffer[0] } } impl Transmutable for u16 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= u16::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, u16_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> u16 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= u16::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_u16) } } impl Transmutable for u32 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= u32::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, u32_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> u32 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= u32::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_u32) } } impl Transmutable for u64 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= u64::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, u64_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> u64 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= u64::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_u64) } } impl Transmutable for usize { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= usize::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, usize_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> usize { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= usize::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_usize) } } impl Transmutable for i8 { #[allow(unused_variables)] fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= i8::BYTES); // Convert this to bytes and add it to the buffer. buffer[0] = *self as u8; } #[allow(unused_variables)] fn from_bytes(buffer: &[u8], endianess: Endianess) -> i8 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= i8::BYTES); // Convert the given bytes to this type and return it. // Endianess doesn't matter here. buffer[0] as i8 } } impl Transmutable for i16 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= i16::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, i16_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> i16 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= i16::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_i16) } } impl Transmutable for i32 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= i32::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, i32_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> i32 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= i32::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_i32) } } impl Transmutable for i64 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= i64::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, i64_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> i64 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= i64::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_i64) } } impl Transmutable for isize { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= isize::BYTES); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, isize_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> isize { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= isize::BYTES); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_isize) } } impl Transmutable for f32 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= 4); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, f32_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> f32 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= 4); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_f32) } } impl Transmutable for f64 { fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) { // Make sure that there is enough space to store // the bytes from this type. assert!(buffer.len() >= 8); // Convert this to bytes and add it to the buffer. handle_endianess_to_bytes!(buffer, self, endianess, f64_to_bytes); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> f64 { // Make sure that there is enough data to read // the bytes for this type. assert!(buffer.len() >= 8); // Convert the given bytes to this type and return it. handle_endianess_from_bytes!(buffer, endianess, bytes_to_f64) } } impl Transmutable for Vector2 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 Vector2. 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..num_bytes], endianess); } fn from_bytes(buffer: &[u8], endianess: Endianess) -> Vector2 { let byte_size: usize; let num_bytes: usize; let mut vec: Vector2; // Determine the number of bytes requires to // represent a Vector2. vec = Vector2::::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..num_bytes], endianess); vec } }