261 lines
7.3 KiB
Rust
261 lines
7.3 KiB
Rust
|
use std::mem;
|
||
|
|
||
|
|
||
|
/// Describes types that can transmute Numbers into bytes,
|
||
|
/// or bytes into Numbers. This means that they can also
|
||
|
/// transmute higher order mathematic types like Vectors,
|
||
|
/// Quaternions, Matrices, and such.
|
||
|
pub trait Transmutable
|
||
|
{
|
||
|
/// Converts an array of bytes to a signed 16-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_i16(buffer: &[u8]) -> i16
|
||
|
{
|
||
|
Self::bytes_to_u16(buffer) as i16
|
||
|
}
|
||
|
|
||
|
/// Converts an array of bytes to a signed 32-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_i32(buffer: &[u8]) -> i32
|
||
|
{
|
||
|
Self::bytes_to_u32(buffer) as i32
|
||
|
}
|
||
|
|
||
|
/// Converts an array of bytes to a signed 64-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_i64(buffer: &[u8]) -> i64
|
||
|
{
|
||
|
Self::bytes_to_u64(buffer) as i64
|
||
|
}
|
||
|
|
||
|
/// Converts an array of bytes to a signed integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
///
|
||
|
/// This will panic if the number of bytes
|
||
|
/// passed in is less than one or more than eight.
|
||
|
fn bytes_to_isize(buffer: &[u8], num_bytes: u8) -> isize
|
||
|
{
|
||
|
let temp_num: u64;
|
||
|
|
||
|
assert!(num_bytes > 1 && num_bytes < 8);
|
||
|
assert!(buffer.len() < (num_bytes as usize));
|
||
|
|
||
|
temp_num = Self::bytes_to_usize(buffer, num_bytes) as u64;
|
||
|
add_sign(temp_num, num_bytes) as isize
|
||
|
}
|
||
|
|
||
|
/// Converts an array of bytes to a 32-bit floating point number.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_f32(buffer: &[u8]) -> f32
|
||
|
{
|
||
|
unsafe
|
||
|
{
|
||
|
mem::transmute::<u32, f32>(Self::bytes_to_u32(buffer))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Converts an array of bytes to a 64-bit floating point number.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_f64(buffer: &[u8]) -> f64
|
||
|
{
|
||
|
unsafe
|
||
|
{
|
||
|
mem::transmute::<u64, f64>(Self::bytes_to_u64(buffer))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/// Converts a signed 16-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn i16_to_bytes(buffer: &mut [u8], num: i16)
|
||
|
{
|
||
|
Self::u16_to_bytes(buffer, num as u16)
|
||
|
}
|
||
|
|
||
|
/// Converts a signed 32-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn i32_to_bytes(buffer: &mut [u8], num: i32)
|
||
|
{
|
||
|
Self::u32_to_bytes(buffer, num as u32)
|
||
|
}
|
||
|
|
||
|
/// Converts a signed 64-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn i64_to_bytes(buffer: &mut [u8], num: i64)
|
||
|
{
|
||
|
Self::u64_to_bytes(buffer, num as u64)
|
||
|
}
|
||
|
|
||
|
/// Converts a signed integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
///
|
||
|
/// This will panic if the number of bytes
|
||
|
/// passed in is less than the byte size of the given number
|
||
|
/// or more than eight.
|
||
|
fn isize_to_bytes(buffer: &mut [u8], num: isize, num_bytes: u8)
|
||
|
{
|
||
|
let temp_num: usize;
|
||
|
|
||
|
assert!(num_bytes > 1 && num_bytes < 8);
|
||
|
assert!(buffer.len() < (num_bytes as usize));
|
||
|
|
||
|
temp_num = remove_sign(num as i64, num_bytes) as usize;
|
||
|
Self::usize_to_bytes(buffer, temp_num, num_bytes)
|
||
|
}
|
||
|
|
||
|
/// Converts a 32-bit floating point number to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn f32_to_bytes(buffer: &mut [u8], num: f32)
|
||
|
{
|
||
|
unsafe
|
||
|
{
|
||
|
Self::u32_to_bytes(buffer, mem::transmute::<f32, u32>(num));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Converts a 64-bit floating point number to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn f64_to_bytes(buffer: &mut [u8], num: f64)
|
||
|
{
|
||
|
unsafe
|
||
|
{
|
||
|
Self::u64_to_bytes(buffer, mem::transmute::<f64, u64>(num));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/// Converts an array of bytes to an unsigned 16-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_u16(buffer: &[u8]) -> u16;
|
||
|
|
||
|
/// Converts an array of bytes to an unsigned 32-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_u32(buffer: &[u8]) -> u32;
|
||
|
|
||
|
/// Converts an array of bytes to an unsigned 64-bit integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
fn bytes_to_u64(buffer: &[u8]) -> u64;
|
||
|
|
||
|
/// Converts an array of bytes to an unsigned integer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough information to convert.
|
||
|
///
|
||
|
/// This will panic if the number of bytes
|
||
|
/// passed in is less than one or more than eight.
|
||
|
fn bytes_to_usize(buffer: &[u8], num_bytes: u8) -> usize;
|
||
|
|
||
|
|
||
|
/// Converts an unsigned 16-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn u16_to_bytes(buffer: &mut [u8], num: u16);
|
||
|
|
||
|
/// Converts an unsigned 32-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn u32_to_bytes(buffer: &mut [u8], num: u32);
|
||
|
|
||
|
/// Converts an unsigned 64-bit integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
fn u64_to_bytes(buffer: &mut [u8], num: u64);
|
||
|
|
||
|
/// Converts an unsigned integer to bytes
|
||
|
/// and places them into the given buffer.
|
||
|
///
|
||
|
/// # Panics
|
||
|
/// This will panic if the buffer does not have
|
||
|
/// enough space to store the converted value.
|
||
|
///
|
||
|
/// This will panic if the number of bytes
|
||
|
/// passed in is less than the byte size of the given number
|
||
|
/// or more than eight.
|
||
|
fn usize_to_bytes(buffer: &mut [u8], num: usize, num_bytes: u8);
|
||
|
}
|
||
|
|
||
|
|
||
|
/// Switches an unsigned value into its signed equivalent.
|
||
|
///
|
||
|
/// NOTE: This seems messy for larger unsigned values.
|
||
|
fn add_sign(val: u64, num_bytes: u8) -> i64
|
||
|
{
|
||
|
let shift: u8;
|
||
|
|
||
|
shift = (8 - num_bytes) * 8;
|
||
|
(val << shift) as i64 >> shift
|
||
|
}
|
||
|
|
||
|
/// Switches a signed value into its unsigned equivalent.
|
||
|
///
|
||
|
/// NOTE: This seems messy for values under zero.
|
||
|
fn remove_sign(val: i64, num_bytes: u8) -> u64
|
||
|
{
|
||
|
let shift: u8;
|
||
|
|
||
|
shift = (8 - num_bytes) * 8;
|
||
|
(val << shift) as u64 >> shift
|
||
|
}
|