diff --git a/formats/ccsds.toml b/formats/ccsds.toml index b8b4047..b6c49aa 100644 --- a/formats/ccsds.toml +++ b/formats/ccsds.toml @@ -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]] diff --git a/src/byte_stream/mod.rs b/src/byte_stream/mod.rs index dfe3d92..2f08f55 100644 --- a/src/byte_stream/mod.rs +++ b/src/byte_stream/mod.rs @@ -110,7 +110,7 @@ impl From> 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 = vec![0xff, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes::(4, 8).unwrap(); + let new_bytes = bit_stream.get_bytes::(4, 8).unwrap(); assert_eq!(vec![0x5f], new_bytes); } @@ -146,7 +146,7 @@ mod tests { let bytes: Vec = vec![0xff, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes::(7, 2).unwrap(); + let new_bytes = bit_stream.get_bytes::(7, 2).unwrap(); assert_eq!(vec![0x03], new_bytes); } diff --git a/src/formatter/format.rs b/src/formatter/format.rs index f6c27a2..de9d858 100644 --- a/src/formatter/format.rs +++ b/src/formatter/format.rs @@ -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(&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(&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(&self, float: f32) -> String { + match self { + PrintType::ByteArray => { + let mut bytes = Vec::with_capacity(4); + bytes.write_f32::(float).unwrap(); + print_bytes_as_array(&bytes) + } + _ => float.to_string(), + } + } + + pub fn print_double(&self, double: f64) -> String { + match self { + PrintType::ByteArray => { + let mut bytes = Vec::with_capacity(8); + bytes.write_f64::(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, } impl Field { fn format_int( + &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::(big_int), bit_width)) } else { Err(ByteStreamError::OutOfRange.into()) } } fn format_uint( + &self, byte_stream: &ByteStream, bit_ndx: usize, bit_width: usize, @@ -171,30 +245,35 @@ impl Field { let bytes = byte_stream.get_bytes::(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::(big_int), bit_width)) } fn format_float( + &self, byte_stream: &ByteStream, bit_ndx: usize, ) -> Result<(String, usize), FormatError> { let bytes = byte_stream.get_bytes::(bit_ndx, 32)?; let mut cursor = Cursor::new(bytes); - Ok((cursor.read_f32::().unwrap().to_string(), 4)) + let float = cursor.read_f32::().unwrap(); + Ok((self.print_type.print_float::(float), 4)) } fn format_double( + &self, byte_stream: &ByteStream, bit_ndx: usize, ) -> Result<(String, usize), FormatError> { let bytes = byte_stream.get_bytes::(bit_ndx, 64)?; let mut cursor = Cursor::new(bytes); - Ok((cursor.read_f64::().unwrap().to_string(), 4)) + let double = cursor.read_f64::().unwrap(); + Ok((self.print_type.print_double::(double), 4)) } fn format_string( + &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( + &self, byte_stream: &ByteStream, bit_ndx: usize, max_byte_len: usize, @@ -231,7 +313,7 @@ impl Field { let data = byte_stream.get_bytes::(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::(byte_stream, bit_ndx, bit_width) + self.format_uint::(byte_stream, bit_ndx, bit_width) } Endianness::BigEndian => { - Self::format_uint::(byte_stream, bit_ndx, bit_width) + self.format_uint::(byte_stream, bit_ndx, bit_width) } }, FieldType::Int { @@ -262,33 +344,31 @@ impl Field { endianness, } => match endianness { Endianness::LittleEndian => { - Self::format_int::(byte_stream, bit_ndx, bit_width) + self.format_int::(byte_stream, bit_ndx, bit_width) } Endianness::BigEndian => { - Self::format_int::(byte_stream, bit_ndx, bit_width) + self.format_int::(byte_stream, bit_ndx, bit_width) } }, FieldType::Float { endianness } => match endianness { - Endianness::LittleEndian => { - Self::format_float::(byte_stream, bit_ndx) - } - Endianness::BigEndian => Self::format_float::(byte_stream, bit_ndx), + Endianness::LittleEndian => self.format_float::(byte_stream, bit_ndx), + Endianness::BigEndian => self.format_float::(byte_stream, bit_ndx), }, FieldType::Double { endianness } => match endianness { Endianness::LittleEndian => { - Self::format_double::(byte_stream, bit_ndx) + self.format_double::(byte_stream, bit_ndx) } - Endianness::BigEndian => Self::format_double::(byte_stream, bit_ndx), + Endianness::BigEndian => self.format_double::(byte_stream, bit_ndx), }, FieldType::String { max_len, endianness, } => match endianness { Endianness::LittleEndian => { - Self::format_string::(byte_stream, bit_ndx, max_len) + self.format_string::(byte_stream, bit_ndx, max_len) } Endianness::BigEndian => { - Self::format_string::(byte_stream, bit_ndx, max_len) + self.format_string::(byte_stream, bit_ndx, max_len) } }, FieldType::Bytes { @@ -296,10 +376,10 @@ impl Field { endianness, } => match endianness { Endianness::LittleEndian => { - Self::format_bytes::(byte_stream, bit_ndx, max_len) + self.format_bytes::(byte_stream, bit_ndx, max_len) } Endianness::BigEndian => { - Self::format_bytes::(byte_stream, bit_ndx, max_len) + self.format_bytes::(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") } diff --git a/src/formatter/printers.rs b/src/formatter/printers.rs index 04edfdd..c253741 100644 --- a/src/formatter/printers.rs +++ b/src/formatter/printers.rs @@ -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), + } +}