diff --git a/formats/ccsds.toml b/formats/ccsds.toml index c7c9d1e..5e91140 100644 --- a/formats/ccsds.toml +++ b/formats/ccsds.toml @@ -3,34 +3,40 @@ # Ref: https://public.ccsds.org/Pubs/133x0b2e1.pdfa # # Example Packet: -# [0xe0, 0xa1, 0xc0, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05] +# [0xe0, 0xa1, 0xc0, 0x00, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05] [[formats]] name = "ccsds" -bit_flip = true +bit_flip = false [[formats.fields]] name = "Version Number" +bit_flip = true field_type = {type = "UInt", bit_width = 3, endianness = "BigEndian"} [[formats.fields]] name = "Packet Type" +bit_flip = true field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"} [[formats.fields]] name = "Secondary Header Flag" +bit_flip = true field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"} [[formats.fields]] name = "APID" +bit_flip = true field_type = {type = "UInt", bit_width = 11, endianness = "BigEndian"} [[formats.fields]] -name = "Sequency Flags" +name = "Sequence Flags" +bit_flip = true field_type = {type = "UInt", bit_width = 2, endianness = "BigEndian"} [[formats.fields]] name = "Packet Sequence Count" +bit_flip = true field_type = {type = "UInt", bit_width = 14, endianness = "BigEndian"} [[formats.fields]] @@ -40,5 +46,4 @@ field_type = {type = "UInt", bit_width = 16, endianness = "BigEndian"} [[formats.fields]] name = "Data" # Allow payloads up to the max size that can be specfied in "Data Length" -field_type = {type = "Bytes", max_len = 65535} - +field_type = {type = "Bytes", max_len = 65535, endianness = "BigEndian"} diff --git a/src/byte_stream/mod.rs b/src/byte_stream/mod.rs index 1c95060..dfe3d92 100644 --- a/src/byte_stream/mod.rs +++ b/src/byte_stream/mod.rs @@ -1,4 +1,4 @@ -use num_bigint::BigUint; +use crate::formatter::format::LastByte; use std::fmt::{Display, Formatter}; #[derive(Clone, Debug)] @@ -31,10 +31,23 @@ pub const fn bit_mask(mask: u8) -> u8 { #[derive(Default, Clone, Debug)] pub struct ByteStream { data: Vec, + reverse_bits: bool, } impl ByteStream { - pub fn get_bytes(&self, bit_ndx: usize, bit_count: usize) -> Result, ByteStreamError> { + pub fn set_reverse_bits(&mut self, reverse_bits: bool) { + self.reverse_bits = reverse_bits; + } + + pub fn get_reverse_bits(&self) -> bool { + self.reverse_bits + } + + pub fn get_bytes( + &self, + bit_ndx: usize, + bit_count: usize, + ) -> Result, ByteStreamError> { let byte_ndx = bit_ndx / 8; let bits_before = (bit_ndx % 8) as u8; let bits_in_last_byte = ((bit_ndx + bit_count - bits_before as usize) % 8) as u8; @@ -51,11 +64,17 @@ impl ByteStream { return Err(ByteStreamError::OutOfRange); } - let byte_stream = self.data[byte_ndx..byte_ndx + bytes_needed].to_vec(); + let mut byte_stream = self.data[byte_ndx..byte_ndx + bytes_needed].to_vec(); - let number = BigUint::from_bytes_le(&byte_stream) >> bits_before; + if self.reverse_bits { + for byte in &mut byte_stream { + *byte = byte.reverse_bits(); + } + } - let mut byte_stream = number.to_bytes_le(); + let number = T::big_uint(&byte_stream) >> bits_before; + + let mut byte_stream = T::big_u_int_to_bytes(number); if bytes_needed > byte_count && bytes_needed == byte_stream.len() { byte_stream.pop(); @@ -81,20 +100,26 @@ impl From<&[u8]> for ByteStream { impl From> for ByteStream { fn from(vec: Vec) -> Self { - ByteStream { data: vec } + ByteStream { + data: vec, + reverse_bits: false, + } } } #[cfg(test)] mod tests { use super::ByteStream; + use byteorder::BigEndian; #[test] fn test_get_bytes_no_shift() { let bytes: Vec = vec![0xff, 0x00, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes(0, bytes.len() * 8).unwrap(); + let new_bytes = bit_stream + .get_bytes::(0, bytes.len() * 8) + .unwrap(); assert_eq!(bytes, new_bytes); } @@ -103,7 +128,7 @@ mod tests { let bytes: Vec = vec![0x5f, 0x00, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes(4, 4).unwrap(); + let new_bytes = bit_stream.get_bytes::(4, 4).unwrap(); assert_eq!(vec![0x05], new_bytes); } @@ -112,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); } @@ -121,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); } @@ -130,7 +155,7 @@ mod tests { let bytes: Vec = vec![0xff, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes(8, 8).unwrap(); + let new_bytes = bit_stream.get_bytes::(8, 8).unwrap(); assert_eq!(vec![0x55], new_bytes); } @@ -139,7 +164,7 @@ mod tests { let bytes: Vec = vec![0x55]; let bit_stream = ByteStream::from(bytes.clone()); - let new_bytes = bit_stream.get_bytes(0, 3).unwrap(); + let new_bytes = bit_stream.get_bytes::(0, 3).unwrap(); assert_eq!(vec![0x05], new_bytes); } } diff --git a/src/formatter/format.rs b/src/formatter/format.rs index 3997b00..f6c27a2 100644 --- a/src/formatter/format.rs +++ b/src/formatter/format.rs @@ -13,6 +13,10 @@ pub trait LastByte: ByteOrder { fn big_int(buf: &[u8]) -> BigInt; fn big_uint(buf: &[u8]) -> BigUint; + + fn big_u_int_to_bytes(big_int: BigUint) -> Vec; + + fn big_int_to_bytes(big_int: BigInt) -> Vec; } impl LastByte for BigEndian { @@ -27,6 +31,14 @@ impl LastByte for BigEndian { fn big_uint(buf: &[u8]) -> BigUint { BigUint::from_bytes_be(buf) } + + fn big_u_int_to_bytes(big_int: BigUint) -> Vec { + big_int.to_bytes_be() + } + + fn big_int_to_bytes(big_int: BigInt) -> Vec { + big_int.to_signed_bytes_be() + } } impl LastByte for LittleEndian { @@ -41,6 +53,14 @@ impl LastByte for LittleEndian { fn big_uint(buf: &[u8]) -> BigUint { BigUint::from_bytes_le(buf) } + + fn big_u_int_to_bytes(big_int: BigUint) -> Vec { + big_int.to_bytes_le() + } + + fn big_int_to_bytes(big_int: BigInt) -> Vec { + big_int.to_signed_bytes_le() + } } #[derive(Debug, Clone)] @@ -79,25 +99,31 @@ pub enum FieldType { /// Unsigned Int UInt { bit_width: usize, - endianness: BigEndianness, + endianness: Endianness, }, /// Unsigned Int Int { bit_width: usize, - endianness: BigEndianness, + endianness: Endianness, }, /// Single Precession Float - Float { endianness: BigEndianness }, + Float { endianness: Endianness }, /// Double Precession Float - Double { endianness: BigEndianness }, + Double { endianness: Endianness }, /// Null Terminated String Field - String { max_len: usize }, + String { + max_len: usize, + endianness: Endianness, + }, /// Fixed Byte Length Field - Bytes { max_len: usize }, + Bytes { + max_len: usize, + endianness: Endianness, + }, } #[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq, Copy)] -pub enum BigEndianness { +pub enum Endianness { LittleEndian, BigEndian, } @@ -108,8 +134,8 @@ pub struct Field { pub name: String, /// Field Type pub field_type: FieldType, - /// Flip Bit Border - pub flip_bit_order: Option, + /// Flip Bit Order + pub bit_flip: Option, } impl Field { @@ -118,7 +144,7 @@ impl Field { bit_ndx: usize, bit_width: usize, ) -> Result<(String, usize), FormatError> { - let mut bytes = byte_stream.get_bytes(bit_ndx, bit_width)?; + let mut bytes = byte_stream.get_bytes::(bit_ndx, bit_width)?; if let Some(last_byte) = T::last_byte(&mut bytes) { let last_bit = ((bit_width - 1) % 8) as u8; @@ -142,7 +168,7 @@ impl Field { bit_ndx: usize, bit_width: usize, ) -> Result<(String, usize), FormatError> { - let bytes = byte_stream.get_bytes(bit_ndx, bit_width)?; + let bytes = byte_stream.get_bytes::(bit_ndx, bit_width)?; let big_int = T::big_uint(&bytes); Ok((big_int.to_string(), bit_width)) @@ -152,7 +178,7 @@ impl Field { byte_stream: &ByteStream, bit_ndx: usize, ) -> Result<(String, usize), FormatError> { - let bytes = byte_stream.get_bytes(bit_ndx, 32)?; + let bytes = byte_stream.get_bytes::(bit_ndx, 32)?; let mut cursor = Cursor::new(bytes); Ok((cursor.read_f32::().unwrap().to_string(), 4)) @@ -162,13 +188,13 @@ impl Field { byte_stream: &ByteStream, bit_ndx: usize, ) -> Result<(String, usize), FormatError> { - let bytes = byte_stream.get_bytes(bit_ndx, 64)?; + let bytes = byte_stream.get_bytes::(bit_ndx, 64)?; let mut cursor = Cursor::new(bytes); Ok((cursor.read_f64::().unwrap().to_string(), 4)) } - fn format_string( + fn format_string( byte_stream: &ByteStream, mut bit_ndx: usize, max_byte_len: usize, @@ -176,7 +202,7 @@ impl Field { let mut string_bytes = Vec::new(); for _ in 0..max_byte_len { - let byte = byte_stream.get_bytes(bit_ndx, 8)?[0]; + let byte = byte_stream.get_bytes::(bit_ndx, 8)?[0]; if byte == 0 { break; @@ -190,7 +216,7 @@ impl Field { Ok((String::from_utf8(string_bytes)?, byte_count)) } - fn format_bytes( + fn format_bytes( byte_stream: &ByteStream, bit_ndx: usize, max_byte_len: usize, @@ -203,25 +229,31 @@ impl Field { data_remaining * 8 }; - let data = byte_stream.get_bytes(bit_ndx, width)?; + let data = byte_stream.get_bytes::(bit_ndx, width)?; Ok((print_bytes_as_array(&data), width)) } fn format_data( &self, - byte_stream: &ByteStream, + byte_stream: &mut ByteStream, bit_ndx: usize, ) -> Result<(String, usize), FormatError> { - match self.field_type { + let global_bit_flip = byte_stream.get_reverse_bits(); + + if let Some(bit_flip) = self.bit_flip { + byte_stream.set_reverse_bits(bit_flip); + } + + let fmt = match self.field_type { FieldType::UInt { bit_width, endianness, } => match endianness { - BigEndianness::LittleEndian => { + Endianness::LittleEndian => { Self::format_uint::(byte_stream, bit_ndx, bit_width) } - BigEndianness::BigEndian => { + Endianness::BigEndian => { Self::format_uint::(byte_stream, bit_ndx, bit_width) } }, @@ -229,28 +261,52 @@ impl Field { bit_width, endianness, } => match endianness { - BigEndianness::LittleEndian => { + Endianness::LittleEndian => { Self::format_int::(byte_stream, bit_ndx, bit_width) } - BigEndianness::BigEndian => { + Endianness::BigEndian => { Self::format_int::(byte_stream, bit_ndx, bit_width) } }, FieldType::Float { endianness } => match endianness { - BigEndianness::LittleEndian => { + Endianness::LittleEndian => { Self::format_float::(byte_stream, bit_ndx) } - BigEndianness::BigEndian => Self::format_float::(byte_stream, bit_ndx), + Endianness::BigEndian => Self::format_float::(byte_stream, bit_ndx), }, FieldType::Double { endianness } => match endianness { - BigEndianness::LittleEndian => { + Endianness::LittleEndian => { Self::format_double::(byte_stream, bit_ndx) } - BigEndianness::BigEndian => Self::format_double::(byte_stream, bit_ndx), + Endianness::BigEndian => Self::format_double::(byte_stream, bit_ndx), }, - 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), - } + FieldType::String { + max_len, + endianness, + } => match endianness { + Endianness::LittleEndian => { + Self::format_string::(byte_stream, bit_ndx, max_len) + } + Endianness::BigEndian => { + Self::format_string::(byte_stream, bit_ndx, max_len) + } + }, + FieldType::Bytes { + max_len, + endianness, + } => match endianness { + Endianness::LittleEndian => { + Self::format_bytes::(byte_stream, bit_ndx, max_len) + } + Endianness::BigEndian => { + Self::format_bytes::(byte_stream, bit_ndx, max_len) + } + }, + }?; + + byte_stream.set_reverse_bits(global_bit_flip); + + Ok(fmt) } } @@ -267,11 +323,13 @@ pub struct Format { impl Format { pub fn format_data(&self, data: &[u8]) -> Result { let mut format_str = String::new(); - let byte_stream = ByteStream::from(data); + let mut byte_stream = ByteStream::from(data); let mut bit_ndx: usize = 0; + byte_stream.set_reverse_bits(self.bit_flip); + for field in &self.fields { - match field.format_data(&byte_stream, bit_ndx) { + match field.format_data(&mut byte_stream, bit_ndx) { Ok((data_str, bit_width)) => { bit_ndx += bit_width; writeln!(format_str, "{}: {}", field.name, data_str).unwrap(); @@ -290,17 +348,17 @@ impl Format { #[cfg(test)] mod tests { use crate::byte_stream::ByteStream; - use crate::formatter::format::{BigEndianness, Field, FieldType}; + use crate::formatter::format::{Endianness, Field, FieldType}; #[test] fn test_format_int_4_bits() { let field = Field { field_type: FieldType::Int { bit_width: 4, - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; for i in 0i8..7i8 { @@ -322,10 +380,10 @@ mod tests { let field = Field { field_type: FieldType::Int { bit_width: 5, - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![0x1B]); let (output, _) = field.format_data(&byte_steam, 0).unwrap(); @@ -338,10 +396,10 @@ mod tests { let field = Field { field_type: FieldType::Int { bit_width: 16, - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![0xFC, 0xA5]); @@ -355,10 +413,10 @@ mod tests { let field = Field { field_type: FieldType::Int { bit_width: 16, - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![0xC0, 0x5F, 0x0A]); @@ -371,10 +429,10 @@ mod tests { fn test_format_float() { let field = Field { field_type: FieldType::Float { - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec()); @@ -387,10 +445,10 @@ mod tests { fn test_format_double() { let field = Field { field_type: FieldType::Double { - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(b"\xD7\xA3\x70\x3D\x0A\x4B\x7A\xC0".to_vec()); @@ -403,10 +461,10 @@ mod tests { fn test_format_float_err() { let field = Field { field_type: FieldType::Double { - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(b"\x3D\x70\xA3\xD7".to_vec()); @@ -419,7 +477,7 @@ mod tests { let field = Field { field_type: FieldType::String { max_len: 16 }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(b"Hello World!\0".to_vec()); @@ -434,7 +492,7 @@ mod tests { let field = Field { field_type: FieldType::Bytes { max_len: 2 }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]); @@ -449,7 +507,7 @@ mod tests { let field = Field { field_type: FieldType::Bytes { max_len: 64 }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![0xDE, 0xAD]); @@ -464,10 +522,10 @@ mod tests { let field = Field { field_type: FieldType::UInt { bit_width: 11, - endianness: BigEndianness::LittleEndian, + endianness: Endianness::LittleEndian, }, name: "test".to_string(), - flip_bit_order: None, + bit_flip: None, }; let byte_steam = ByteStream::from(vec![