Strings can now be transmuted or converted into binary data.

This also added the scribe library so that this library can use
the logging system.
This commit is contained in:
Jason Travis Smith 2016-04-13 23:57:40 -04:00
parent d1c4b3e053
commit e9ab0bdece
7 changed files with 225 additions and 1 deletions

6
Cargo.lock generated
View File

@ -3,6 +3,7 @@ name = "alchemy"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"scribe 0.1.0 (git+https://gitlab.com/CyberMages/scribe.git)",
"sigils 0.1.0 (git+https://gitlab.com/CyberMages/sigils.git)", "sigils 0.1.0 (git+https://gitlab.com/CyberMages/sigils.git)",
] ]
@ -30,6 +31,11 @@ dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "scribe"
version = "0.1.0"
source = "git+https://gitlab.com/CyberMages/scribe.git#e52418d3bfc28cd1f03cc7f31af06fce2e03f844"
[[package]] [[package]]
name = "sigils" name = "sigils"
version = "0.1.0" version = "0.1.0"

View File

@ -2,6 +2,15 @@
name = "alchemy" name = "alchemy"
version = "0.1.0" version = "0.1.0"
authors = ["Jason Travis Smith <Jason@CyberMagesLLC.com>"] authors = ["Jason Travis Smith <Jason@CyberMagesLLC.com>"]
description = "Handles converting values to and from a binary format."
license = ""
repository = "https://gitlab.com/CyberMages/alchemy.git"
documentation = ""
keywords = ["converter", "binary"]
[dependencies.scribe]
git = "https://gitlab.com/CyberMages/scribe.git"
[dependencies.sigils] [dependencies.sigils]
git = "https://gitlab.com/CyberMages/sigils.git" git = "https://gitlab.com/CyberMages/sigils.git"

View File

@ -115,3 +115,20 @@ byte_sized_impl!((i8, I8_BYTES) (i16, I16_BYTES));
byte_sized_impl!((i32, I32_BYTES) (i64, U64_BYTES)); byte_sized_impl!((i32, I32_BYTES) (i64, U64_BYTES));
byte_sized_impl!((f32, F32_BYTES) (f64, F64_BYTES)); byte_sized_impl!((f32, F32_BYTES) (f64, F64_BYTES));
byte_sized_impl!((usize, USIZE_BYTES) (isize, ISIZE_BYTES)); byte_sized_impl!((usize, USIZE_BYTES) (isize, ISIZE_BYTES));
/// This returns the amount of bytes it takes to store a string
/// in a binary format. This includes the u64 size we prepend to
/// store the amount of bytes of data in the String.
pub fn get_byte_size_of_string(string: &String) -> usize
{
let bytes: &[u8];
// Turn the string into a byte array.
bytes = string.as_bytes();
// Determine how many bytes will be written
// for this string and add the amount of
// bytes needed for the u64 size.
bytes.len() + U64_BYTES
}

View File

@ -231,6 +231,26 @@ pub trait Converter
/// passed in is less than the byte size of the given number /// passed in is less than the byte size of the given number
/// or more than eight. /// or more than eight.
fn usize_to_bytes(buffer: &mut [u8], num: usize); fn usize_to_bytes(buffer: &mut [u8], num: usize);
/// Converts a String 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 String.
fn bytes_to_string(buffer: &[u8]) -> String;
/// Converts an array of bytes to a String.
///
/// # Panics
/// This will panic if the buffer does not have
/// enough information to convert.
fn string_to_bytes(buffer: &mut [u8], string: String);
} }

View File

@ -74,7 +74,8 @@ macro_rules! read_bytes
/// and writing them to a buffer. /// and writing them to a buffer.
macro_rules! write_bytes macro_rules! write_bytes
{ {
($buffer: expr, $valueType: ident, $numBytes: expr, $num: expr, $convertFunc: ident) => ($buffer: expr, $valueType: ident, $numBytes: expr,
$num: expr, $convertFunc: ident) =>
({ ({
assert!($buffer.len() >= $valueType::BYTES, assert!($buffer.len() >= $valueType::BYTES,
"Not enough room in the buffer to write to."); "Not enough room in the buffer to write to.");
@ -166,6 +167,67 @@ impl Converter for BigEndian
buffer.as_mut_ptr(), num_bytes as usize); buffer.as_mut_ptr(), num_bytes as usize);
} }
} }
fn bytes_to_string(buffer: &[u8]) -> String
{
let byte_count: u64;
let new_string: String;
// A string array should have atleast a u64 size byte count.
assert!(buffer.len() >= U64_BYTES);
// 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);
if byte_count > 0
{
match String::from_utf8(buffer[U64_BYTES..(buffer.len()-1)].to_vec())
{
Ok(string) =>
{
new_string = string;
}
Err(error) =>
{
error!("{}", error);
}
}
}
else
{
new_string = String::new();
}
new_string
}
fn string_to_bytes(buffer: &mut [u8], string: String)
{
let bytes: &[u8];
let byte_count: u64;
// Turn the string into a byte array.
bytes = string.as_bytes();
// Determine how many bytes will be written
// for this string.
byte_count = bytes.len() as u64;
// Make sure the buffer has enough space for this string.
assert!(buffer.len() as u64 >= byte_count + U64_BYTES as u64);
// Add the count to the buffer.
BigEndian::u64_to_bytes(&mut buffer[0..U64_BYTES], byte_count);
// Add each byte of the string to the buffer.
for (i, byte) in bytes.iter().enumerate()
{
buffer[U64_BYTES + i] = byte.clone();
}
}
} }
impl Converter for LittleEndian impl Converter for LittleEndian
@ -234,6 +296,67 @@ impl Converter for LittleEndian
num_bytes as usize); num_bytes as usize);
} }
} }
fn bytes_to_string(buffer: &[u8]) -> String
{
let byte_count: u64;
let new_string: String;
// A string array should have atleast a u64 size byte count.
assert!(buffer.len() >= U64_BYTES);
// 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);
if byte_count > 0
{
match String::from_utf8(buffer[U64_BYTES..(buffer.len()-1)].to_vec())
{
Ok(string) =>
{
new_string = string;
}
Err(error) =>
{
error!("{}", error);
}
}
}
else
{
new_string = String::new();
}
new_string
}
fn string_to_bytes(buffer: &mut [u8], string: String)
{
let bytes: &[u8];
let byte_count: u64;
// Turn the string into a byte array.
bytes = string.as_bytes();
// Determine how many bytes will be written
// for this string.
byte_count = bytes.len() as u64 + U64_BYTES as u64;
// Make sure the buffer has enough space for this string.
assert!(buffer.len() as u64 >= byte_count);
// Add the count to the buffer.
LittleEndian::u64_to_bytes(&mut buffer[0..U64_BYTES], byte_count);
// Add each byte of the string to the buffer.
for (i, byte) in bytes.iter().enumerate()
{
buffer[U64_BYTES + i] = byte.clone();
}
}
} }

View File

@ -1,9 +1,15 @@
//! The Alchemy library is a data type to byte converter library. //! The Alchemy library is a data type to byte converter library.
//! Alchemy handles converting numbers to and from bytes //! Alchemy handles converting numbers to and from bytes
//! in either big or little endian format. //! in either big or little endian format.
#![doc(html_logo_url="http://cybermagesllc.com/wp-content/uploads/2012/06/logo-300x300.png",
html_favicon_url="http://cybermagesllc.com/favicon.ico",
html_root_url="http://cybermagesllc.com")]
#![feature(associated_consts)] #![feature(associated_consts)]
#![warn(missing_docs)] #![warn(missing_docs)]
#[macro_use]
extern crate scribe;
extern crate sigils; extern crate sigils;
@ -19,6 +25,7 @@ pub use ::byte_sized::ByteSized;
pub use ::byte_sized::{U8_BYTES, U16_BYTES, U32_BYTES, U64_BYTES, USIZE_BYTES}; pub use ::byte_sized::{U8_BYTES, U16_BYTES, U32_BYTES, U64_BYTES, USIZE_BYTES};
pub use ::byte_sized::{I8_BYTES, I16_BYTES, I32_BYTES, I64_BYTES, ISIZE_BYTES}; pub use ::byte_sized::{I8_BYTES, I16_BYTES, I32_BYTES, I64_BYTES, ISIZE_BYTES};
pub use ::byte_sized::{F32_BYTES, F64_BYTES}; pub use ::byte_sized::{F32_BYTES, F64_BYTES};
pub use ::byte_sized::get_byte_size_of_string;
pub use ::converter::Converter; pub use ::converter::Converter;
pub use ::endian::{BigEndian, LittleEndian, PlatformEndian, Endianess}; pub use ::endian::{BigEndian, LittleEndian, PlatformEndian, Endianess};
pub use ::transmutable::Transmutable; pub use ::transmutable::Transmutable;

View File

@ -366,6 +366,48 @@ impl Transmutable for f64
} }
} }
impl Transmutable for String
{
fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess)
{
let temp: String;
let mut mut_buffer;
// Create a mutable handle to the buffer.
mut_buffer = buffer;
// Clone the string so that we can use its data.
// We have to do this because Strings don't implement Copy.
temp = self.clone();
// Convert this to bytes and add it to the buffer.
// We are not using the macro because *String is a str.
match endianess
{
Endianess::BIG =>
{
BigEndian::string_to_bytes(&mut mut_buffer, temp);
}
Endianess::LITTLE =>
{
LittleEndian::string_to_bytes(&mut mut_buffer, temp);
}
Endianess::PLATFORM =>
{
PlatformEndian::string_to_bytes(&mut mut_buffer, temp);
}
}
}
fn from_bytes(buffer: &[u8], endianess: Endianess) -> String
{
// Convert the given bytes to this type and return it.
handle_endianess_from_bytes!(buffer, endianess, bytes_to_string)
}
}
impl<T> Transmutable for Vector2<T> where T: Number + ByteSized + Transmutable impl<T> Transmutable for Vector2<T> where T: Number + ByteSized + Transmutable
{ {
fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess) fn to_bytes(&self, buffer: &mut [u8], endianess: Endianess)