Added string and bytes formatting

+ String fields are always null terminated and have a max length
+ Byte fields are made of raw bytes, and read data until they hit a max length or the end of data is reached
pull/1/head
Joey Hines 2021-10-09 10:05:32 -06:00
parent 652682cb19
commit 4e9f4bff1d
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
4 changed files with 80 additions and 3 deletions

View File

@ -72,6 +72,10 @@ impl ByteStream {
Ok(byte_stream) Ok(byte_stream)
} }
pub fn len(&self) -> usize {
self.data.len()
}
} }
impl From<&[u8]> for ByteStream { impl From<&[u8]> for ByteStream {

View File

@ -4,11 +4,15 @@ use std::fmt::{Write, Display, Formatter};
use num_bigint::{BigUint, BigInt}; use num_bigint::{BigUint, BigInt};
use std::io::Cursor; use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
use std::string::FromUtf8Error;
use crate::formatter::printers::print_bytes_as_array;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum FormatError { pub enum FormatError {
ByteSteamError(ByteStreamError), ByteSteamError(ByteStreamError),
NotSupported #[allow(dead_code)]
NotSupported,
StringParseError(FromUtf8Error),
} }
impl From<ByteStreamError> for FormatError { impl From<ByteStreamError> for FormatError {
@ -17,11 +21,18 @@ impl From<ByteStreamError> for FormatError {
} }
} }
impl From<FromUtf8Error> for FormatError {
fn from(e: FromUtf8Error) -> Self {
FormatError::StringParseError(e)
}
}
impl Display for FormatError { impl Display for FormatError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self { match self {
FormatError::ByteSteamError(e) => writeln!(f, "Byte steam error: {}", e), FormatError::ByteSteamError(e) => writeln!(f, "Byte steam error: {}", e),
FormatError::NotSupported => write!(f, "Field type not supported") FormatError::NotSupported => write!(f, "Field type not supported"),
FormatError::StringParseError(e) => write!(f, "String parse error: {}", e)
} }
} }
} }
@ -94,13 +105,47 @@ impl Field {
Ok((cursor.read_f64::<BigEndian>().unwrap().to_string(), 4)) Ok((cursor.read_f64::<BigEndian>().unwrap().to_string(), 4))
} }
fn format_string(byte_stream: &ByteStream, mut bit_ndx: usize, max_byte_len: usize) -> Result<(String, usize), FormatError> {
let mut string_bytes = Vec::new();
for _ in 0..max_byte_len {
let byte = byte_stream.get_bytes(bit_ndx, 8)?[0];
if byte == 0 {
break;
}
string_bytes.push(byte);
bit_ndx += 8;
}
let byte_count = string_bytes.len();
Ok((String::from_utf8(string_bytes)?, byte_count))
}
fn format_bytes(byte_stream: &ByteStream, bit_ndx: usize, max_byte_len: usize) -> Result<(String, usize), FormatError> {
let data_remaining = byte_stream.len() - bit_ndx/8;
let width = if max_byte_len < data_remaining {
max_byte_len*8
}
else {
data_remaining*8
};
let data = byte_stream.get_bytes(bit_ndx, width)?;
Ok((print_bytes_as_array(&data), width))
}
fn format_data(&self, byte_stream: &ByteStream, bit_ndx: usize) -> Result<(String, usize), FormatError> { fn format_data(&self, byte_stream: &ByteStream, bit_ndx: usize) -> Result<(String, usize), FormatError> {
match self.field_type { match self.field_type {
FieldType::UInt { bit_width } => Self::format_uint(byte_stream, bit_ndx, bit_width), FieldType::UInt { bit_width } => Self::format_uint(byte_stream, bit_ndx, bit_width),
FieldType::Int { bit_width } => Self::format_int(byte_stream, bit_ndx, bit_width), FieldType::Int { bit_width } => Self::format_int(byte_stream, bit_ndx, bit_width),
FieldType::Float => Self::format_float(byte_stream, bit_ndx), FieldType::Float => Self::format_float(byte_stream, bit_ndx),
FieldType::Double => Self::format_double(byte_stream, bit_ndx), FieldType::Double => Self::format_double(byte_stream, bit_ndx),
_ => Err(FormatError::NotSupported), FieldType::String {max_len} => Self::format_string(byte_stream, bit_ndx, max_len),
FieldType::Bytes {max_len} => Self::format_bytes(byte_stream, bit_ndx, max_len)
} }
} }
} }
@ -211,4 +256,26 @@ mod tests {
assert!(field.format_data(&byte_steam, 0).is_err()) assert!(field.format_data(&byte_steam, 0).is_err())
} }
#[test]
fn test_format_string() {
let field = Field {field_type: FieldType::String {max_len: 16}, name: "test".to_string()};
let byte_steam = ByteStream::from(b"Hello World!\0".to_vec());
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
assert_eq!(output, "Hello World!".to_string())
}
#[test]
fn test_format_bytes() {
let field = Field {field_type: FieldType::Bytes {max_len: 2}, name: "test".to_string()};
let byte_steam = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]);
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
assert_eq!(output, "[222, 173]")
}
} }

View File

@ -1,4 +1,5 @@
pub mod format; pub mod format;
mod printers;
use crate::formatter::format::Format; use crate::formatter::format::Format;
use serde::Deserialize; use serde::Deserialize;

View File

@ -0,0 +1,5 @@
pub fn print_bytes_as_array(data: &[u8]) -> String {
format!("{:?}", data)
}