Added additional printers
+ Data types can be printed in different formats + The formats respect endianness + Fixed tests + clippy+fmtpull/1/head
parent
6407335362
commit
1cf7f06230
|
@ -28,6 +28,7 @@ field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"}
|
|||
[[formats.fields]]
|
||||
name = "APID"
|
||||
bit_flip = true
|
||||
print_type = {print = "Base", base = 16}
|
||||
field_type = {type = "UInt", bit_width = 11, endianness = "BigEndian"}
|
||||
|
||||
[[formats.fields]]
|
||||
|
@ -72,6 +73,7 @@ field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"}
|
|||
[[formats.fields]]
|
||||
name = "APID"
|
||||
bit_flip = true
|
||||
print_type = {print = "Base", base = 16}
|
||||
field_type = {type = "UInt", bit_width = 11, endianness = "BigEndian"}
|
||||
|
||||
[[formats.fields]]
|
||||
|
|
|
@ -110,7 +110,7 @@ impl From<Vec<u8>> for ByteStream {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ByteStream;
|
||||
use byteorder::BigEndian;
|
||||
use byteorder::{BigEndian, LittleEndian};
|
||||
|
||||
#[test]
|
||||
fn test_get_bytes_no_shift() {
|
||||
|
@ -137,7 +137,7 @@ mod tests {
|
|||
let bytes: Vec<u8> = vec![0xff, 0x55];
|
||||
let bit_stream = ByteStream::from(bytes.clone());
|
||||
|
||||
let new_bytes = bit_stream.get_bytes::<BigEndian>(4, 8).unwrap();
|
||||
let new_bytes = bit_stream.get_bytes::<LittleEndian>(4, 8).unwrap();
|
||||
assert_eq!(vec![0x5f], new_bytes);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ mod tests {
|
|||
let bytes: Vec<u8> = vec![0xff, 0x55];
|
||||
let bit_stream = ByteStream::from(bytes.clone());
|
||||
|
||||
let new_bytes = bit_stream.get_bytes::<BigEndian>(7, 2).unwrap();
|
||||
let new_bytes = bit_stream.get_bytes::<LittleEndian>(7, 2).unwrap();
|
||||
assert_eq!(vec![0x03], new_bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::byte_stream::{bit_mask, ByteStream, ByteStreamError};
|
||||
use crate::formatter::printers::print_bytes_as_array;
|
||||
use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};
|
||||
use crate::formatter::printers::{base_notation, print_bytes_as_array};
|
||||
use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use num_bigint::{BigInt, BigUint};
|
||||
use serde::Deserialize;
|
||||
use std::fmt::{Display, Formatter, Write};
|
||||
|
@ -122,6 +122,75 @@ pub enum FieldType {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(tag = "print")]
|
||||
pub enum PrintType {
|
||||
Base { base: u32 },
|
||||
ByteArray,
|
||||
Default,
|
||||
}
|
||||
|
||||
impl Default for PrintType {
|
||||
fn default() -> Self {
|
||||
PrintType::Default
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintType {
|
||||
pub fn print_big_int<T: LastByte>(&self, big_int: BigInt) -> String {
|
||||
match self {
|
||||
PrintType::Base { base: b } => {
|
||||
format!("{}{}", base_notation(*b), big_int.to_str_radix(*b))
|
||||
}
|
||||
PrintType::ByteArray => print_bytes_as_array(&T::big_int_to_bytes(big_int)),
|
||||
PrintType::Default => big_int.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_big_u_int<T: LastByte>(&self, big_int: BigUint) -> String {
|
||||
match self {
|
||||
PrintType::Base { base: b } => {
|
||||
format!("{}{}", base_notation(*b), big_int.to_str_radix(*b))
|
||||
}
|
||||
PrintType::ByteArray => print_bytes_as_array(&T::big_u_int_to_bytes(big_int)),
|
||||
PrintType::Default => big_int.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_float<T: LastByte>(&self, float: f32) -> String {
|
||||
match self {
|
||||
PrintType::ByteArray => {
|
||||
let mut bytes = Vec::with_capacity(4);
|
||||
bytes.write_f32::<T>(float).unwrap();
|
||||
print_bytes_as_array(&bytes)
|
||||
}
|
||||
_ => float.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_double<T: LastByte>(&self, double: f64) -> String {
|
||||
match self {
|
||||
PrintType::ByteArray => {
|
||||
let mut bytes = Vec::with_capacity(8);
|
||||
bytes.write_f64::<T>(double).unwrap();
|
||||
print_bytes_as_array(&bytes)
|
||||
}
|
||||
_ => double.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_bytes(&self, bytes: &[u8]) -> String {
|
||||
print_bytes_as_array(bytes)
|
||||
}
|
||||
|
||||
pub fn print_string(&self, s: &str) -> String {
|
||||
match self {
|
||||
PrintType::ByteArray => print_bytes_as_array(s.as_bytes()),
|
||||
_ => s.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq, Copy)]
|
||||
pub enum Endianness {
|
||||
LittleEndian,
|
||||
|
@ -134,12 +203,16 @@ pub struct Field {
|
|||
pub name: String,
|
||||
/// Field Type
|
||||
pub field_type: FieldType,
|
||||
/// How to display the field
|
||||
#[serde(default = "PrintType::default")]
|
||||
pub print_type: PrintType,
|
||||
/// Flip Bit Order
|
||||
pub bit_flip: Option<bool>,
|
||||
}
|
||||
|
||||
impl Field {
|
||||
fn format_int<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
bit_ndx: usize,
|
||||
bit_width: usize,
|
||||
|
@ -157,13 +230,14 @@ impl Field {
|
|||
|
||||
let big_int = T::big_int(&bytes);
|
||||
|
||||
Ok((big_int.to_string(), bit_width))
|
||||
Ok((self.print_type.print_big_int::<T>(big_int), bit_width))
|
||||
} else {
|
||||
Err(ByteStreamError::OutOfRange.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn format_uint<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
bit_ndx: usize,
|
||||
bit_width: usize,
|
||||
|
@ -171,30 +245,35 @@ impl Field {
|
|||
let bytes = byte_stream.get_bytes::<T>(bit_ndx, bit_width)?;
|
||||
|
||||
let big_int = T::big_uint(&bytes);
|
||||
Ok((big_int.to_string(), bit_width))
|
||||
Ok((self.print_type.print_big_u_int::<T>(big_int), bit_width))
|
||||
}
|
||||
|
||||
fn format_float<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
bit_ndx: usize,
|
||||
) -> Result<(String, usize), FormatError> {
|
||||
let bytes = byte_stream.get_bytes::<T>(bit_ndx, 32)?;
|
||||
let mut cursor = Cursor::new(bytes);
|
||||
|
||||
Ok((cursor.read_f32::<T>().unwrap().to_string(), 4))
|
||||
let float = cursor.read_f32::<T>().unwrap();
|
||||
Ok((self.print_type.print_float::<T>(float), 4))
|
||||
}
|
||||
|
||||
fn format_double<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
bit_ndx: usize,
|
||||
) -> Result<(String, usize), FormatError> {
|
||||
let bytes = byte_stream.get_bytes::<T>(bit_ndx, 64)?;
|
||||
let mut cursor = Cursor::new(bytes);
|
||||
|
||||
Ok((cursor.read_f64::<T>().unwrap().to_string(), 4))
|
||||
let double = cursor.read_f64::<T>().unwrap();
|
||||
Ok((self.print_type.print_double::<T>(double), 4))
|
||||
}
|
||||
|
||||
fn format_string<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
mut bit_ndx: usize,
|
||||
max_byte_len: usize,
|
||||
|
@ -213,10 +292,13 @@ impl Field {
|
|||
}
|
||||
|
||||
let byte_count = string_bytes.len();
|
||||
Ok((String::from_utf8(string_bytes)?, byte_count))
|
||||
|
||||
let s = String::from_utf8(string_bytes)?;
|
||||
Ok((self.print_type.print_string(&s), byte_count))
|
||||
}
|
||||
|
||||
fn format_bytes<T: LastByte>(
|
||||
&self,
|
||||
byte_stream: &ByteStream,
|
||||
bit_ndx: usize,
|
||||
max_byte_len: usize,
|
||||
|
@ -231,7 +313,7 @@ impl Field {
|
|||
|
||||
let data = byte_stream.get_bytes::<T>(bit_ndx, width)?;
|
||||
|
||||
Ok((print_bytes_as_array(&data), width))
|
||||
Ok((self.print_type.print_bytes(&data), width))
|
||||
}
|
||||
|
||||
fn format_data(
|
||||
|
@ -251,10 +333,10 @@ impl Field {
|
|||
endianness,
|
||||
} => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_uint::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
||||
self.format_uint::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
||||
}
|
||||
Endianness::BigEndian => {
|
||||
Self::format_uint::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
||||
self.format_uint::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
||||
}
|
||||
},
|
||||
FieldType::Int {
|
||||
|
@ -262,33 +344,31 @@ impl Field {
|
|||
endianness,
|
||||
} => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_int::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
||||
self.format_int::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
||||
}
|
||||
Endianness::BigEndian => {
|
||||
Self::format_int::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
||||
self.format_int::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
||||
}
|
||||
},
|
||||
FieldType::Float { endianness } => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_float::<LittleEndian>(byte_stream, bit_ndx)
|
||||
}
|
||||
Endianness::BigEndian => Self::format_float::<BigEndian>(byte_stream, bit_ndx),
|
||||
Endianness::LittleEndian => self.format_float::<LittleEndian>(byte_stream, bit_ndx),
|
||||
Endianness::BigEndian => self.format_float::<BigEndian>(byte_stream, bit_ndx),
|
||||
},
|
||||
FieldType::Double { endianness } => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_double::<LittleEndian>(byte_stream, bit_ndx)
|
||||
self.format_double::<LittleEndian>(byte_stream, bit_ndx)
|
||||
}
|
||||
Endianness::BigEndian => Self::format_double::<BigEndian>(byte_stream, bit_ndx),
|
||||
Endianness::BigEndian => self.format_double::<BigEndian>(byte_stream, bit_ndx),
|
||||
},
|
||||
FieldType::String {
|
||||
max_len,
|
||||
endianness,
|
||||
} => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
self.format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
}
|
||||
Endianness::BigEndian => {
|
||||
Self::format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
self.format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
}
|
||||
},
|
||||
FieldType::Bytes {
|
||||
|
@ -296,10 +376,10 @@ impl Field {
|
|||
endianness,
|
||||
} => match endianness {
|
||||
Endianness::LittleEndian => {
|
||||
Self::format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
self.format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
}
|
||||
Endianness::BigEndian => {
|
||||
Self::format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
self.format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
||||
}
|
||||
},
|
||||
}?;
|
||||
|
@ -359,16 +439,17 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
for i in 0i8..7i8 {
|
||||
let mut byte_vec = ::new();
|
||||
let mut byte_vec = Vec::new();
|
||||
byte_vec.push(i as u8);
|
||||
byte_vec.push((-i) as u8);
|
||||
|
||||
let byte_steam = ByteStream::from(byte_vec);
|
||||
let (pos_output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let (neg_output, _) = field.format_data(&byte_steam, 8).unwrap();
|
||||
let mut byte_stream = ByteStream::from(byte_vec);
|
||||
let (pos_output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
let (neg_output, _) = field.format_data(&mut byte_stream, 8).unwrap();
|
||||
|
||||
assert_eq!(pos_output, i.to_string());
|
||||
assert_eq!(neg_output, (-i).to_string());
|
||||
|
@ -384,9 +465,10 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
let byte_steam = ByteStream::from(vec![0x1B]);
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let mut byte_stream = ByteStream::from(vec![0x1B]);
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "-5")
|
||||
}
|
||||
|
@ -400,10 +482,11 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(vec![0xFC, 0xA5]);
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let mut byte_stream = ByteStream::from(vec![0xFC, 0xA5]);
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "-23044")
|
||||
}
|
||||
|
@ -417,10 +500,11 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(vec![0xC0, 0x5F, 0x0A]);
|
||||
let (output, _) = field.format_data(&byte_steam, 4).unwrap();
|
||||
let mut byte_stream = ByteStream::from(vec![0xC0, 0x5F, 0x0A]);
|
||||
let (output, _) = field.format_data(&mut byte_stream, 4).unwrap();
|
||||
|
||||
assert_eq!(output, "-23044")
|
||||
}
|
||||
|
@ -433,10 +517,11 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec());
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let mut byte_stream = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec());
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "-420.69")
|
||||
}
|
||||
|
@ -449,10 +534,11 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(b"\xD7\xA3\x70\x3D\x0A\x4B\x7A\xC0".to_vec());
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let mut byte_stream = ByteStream::from(b"\xD7\xA3\x70\x3D\x0A\x4B\x7A\xC0".to_vec());
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "-420.69")
|
||||
}
|
||||
|
@ -465,24 +551,26 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(b"\x3D\x70\xA3\xD7".to_vec());
|
||||
let mut byte_stream = ByteStream::from(b"\x3D\x70\xA3\xD7".to_vec());
|
||||
|
||||
assert!(field.format_data(&byte_steam, 0).is_err())
|
||||
assert!(field.format_data(&mut byte_stream, 0).is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_string() {
|
||||
let field = Field {
|
||||
field_type: FieldType::String { max_len: 16 },
|
||||
field_type: FieldType::String { max_len: 16, endianness: Endianness::LittleEndian },
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(b"Hello World!\0".to_vec());
|
||||
let mut byte_stream = ByteStream::from(b"Hello World!\0".to_vec());
|
||||
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "Hello World!".to_string())
|
||||
}
|
||||
|
@ -490,14 +578,15 @@ mod tests {
|
|||
#[test]
|
||||
fn test_format_bytes() {
|
||||
let field = Field {
|
||||
field_type: FieldType::Bytes { max_len: 2 },
|
||||
field_type: FieldType::Bytes { max_len: 2, endianness: Endianness::LittleEndian },
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]);
|
||||
let mut byte_stream = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]);
|
||||
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "[222, 173]")
|
||||
}
|
||||
|
@ -505,14 +594,15 @@ mod tests {
|
|||
#[test]
|
||||
fn test_format_bytes_max_len_bigger_than_data() {
|
||||
let field = Field {
|
||||
field_type: FieldType::Bytes { max_len: 64 },
|
||||
field_type: FieldType::Bytes { max_len: 64, endianness: Endianness::LittleEndian },
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(vec![0xDE, 0xAD]);
|
||||
let mut byte_stream = ByteStream::from(vec![0xDE, 0xAD]);
|
||||
|
||||
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
||||
let (output, _) = field.format_data(&mut byte_stream, 0).unwrap();
|
||||
|
||||
assert_eq!(output, "[222, 173]")
|
||||
}
|
||||
|
@ -526,13 +616,14 @@ mod tests {
|
|||
},
|
||||
name: "test".to_string(),
|
||||
bit_flip: None,
|
||||
print_type: Default::default()
|
||||
};
|
||||
|
||||
let byte_steam = ByteStream::from(vec![
|
||||
let mut byte_stream = ByteStream::from(vec![
|
||||
0xe0, 0xa1, 0xc0, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||
]);
|
||||
|
||||
let (output, _) = field.format_data(&byte_steam, 5).unwrap();
|
||||
let (output, _) = field.format_data(&mut byte_stream, 5).unwrap();
|
||||
|
||||
assert_eq!(output, "1295")
|
||||
}
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
pub fn print_bytes_as_array(data: &[u8]) -> String {
|
||||
format!("{:?}", data)
|
||||
}
|
||||
|
||||
pub fn base_notation(b: u32) -> String {
|
||||
match b {
|
||||
2 => "0b".to_string(),
|
||||
8 => "0".to_string(),
|
||||
10 => "".to_string(),
|
||||
16 => "0x".to_string(),
|
||||
_ => format!("Base({}) ", b),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue