diff --git a/formats/ccsds.toml b/formats/ccsds.toml index 55c4397..c7c9d1e 100644 --- a/formats/ccsds.toml +++ b/formats/ccsds.toml @@ -7,34 +7,35 @@ [[formats]] name = "ccsds" +bit_flip = true [[formats.fields]] name = "Version Number" -field_type = {type = "UInt", bit_width = 3} +field_type = {type = "UInt", bit_width = 3, endianness = "BigEndian"} [[formats.fields]] name = "Packet Type" -field_type = {type = "UInt", bit_width = 1} +field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"} [[formats.fields]] name = "Secondary Header Flag" -field_type = {type = "UInt", bit_width = 1} +field_type = {type = "UInt", bit_width = 1, endianness = "BigEndian"} [[formats.fields]] name = "APID" -field_type = {type = "UInt", bit_width = 11} +field_type = {type = "UInt", bit_width = 11, endianness = "BigEndian"} [[formats.fields]] name = "Sequency Flags" -field_type = {type = "UInt", bit_width = 2} +field_type = {type = "UInt", bit_width = 2, endianness = "BigEndian"} [[formats.fields]] name = "Packet Sequence Count" -field_type = {type = "UInt", bit_width = 14} +field_type = {type = "UInt", bit_width = 14, endianness = "BigEndian"} [[formats.fields]] name = "Data Length" -field_type = {type = "UInt", bit_width = 16} +field_type = {type = "UInt", bit_width = 16, endianness = "BigEndian"} [[formats.fields]] name = "Data" diff --git a/src/formatter/format.rs b/src/formatter/format.rs index ec0a469..3997b00 100644 --- a/src/formatter/format.rs +++ b/src/formatter/format.rs @@ -1,12 +1,48 @@ use crate::byte_stream::{bit_mask, ByteStream, ByteStreamError}; use crate::formatter::printers::print_bytes_as_array; -use byteorder::{LittleEndian, ReadBytesExt}; +use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt}; use num_bigint::{BigInt, BigUint}; use serde::Deserialize; use std::fmt::{Display, Formatter, Write}; use std::io::Cursor; use std::string::FromUtf8Error; +pub trait LastByte: ByteOrder { + fn last_byte(buf: &mut Vec) -> Option<&mut u8>; + + fn big_int(buf: &[u8]) -> BigInt; + + fn big_uint(buf: &[u8]) -> BigUint; +} + +impl LastByte for BigEndian { + fn last_byte(buf: &mut Vec) -> Option<&mut u8> { + buf.first_mut() + } + + fn big_int(buf: &[u8]) -> BigInt { + BigInt::from_signed_bytes_be(buf) + } + + fn big_uint(buf: &[u8]) -> BigUint { + BigUint::from_bytes_be(buf) + } +} + +impl LastByte for LittleEndian { + fn last_byte(buf: &mut Vec) -> Option<&mut u8> { + buf.last_mut() + } + + fn big_int(buf: &[u8]) -> BigInt { + BigInt::from_signed_bytes_le(buf) + } + + fn big_uint(buf: &[u8]) -> BigUint { + BigUint::from_bytes_le(buf) + } +} + #[derive(Debug, Clone)] pub enum FormatError { ByteSteamError(ByteStreamError), @@ -41,36 +77,50 @@ impl Display for FormatError { #[serde(tag = "type")] pub enum FieldType { /// Unsigned Int - UInt { bit_width: usize }, + UInt { + bit_width: usize, + endianness: BigEndianness, + }, /// Unsigned Int - Int { bit_width: usize }, + Int { + bit_width: usize, + endianness: BigEndianness, + }, /// Single Precession Float - Float, + Float { endianness: BigEndianness }, /// Double Precession Float - Double, + Double { endianness: BigEndianness }, /// Null Terminated String Field String { max_len: usize }, /// Fixed Byte Length Field Bytes { max_len: usize }, } +#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq, Copy)] +pub enum BigEndianness { + LittleEndian, + BigEndian, +} + #[derive(Debug, Deserialize, Clone)] pub struct Field { /// Field Name pub name: String, /// Field Type pub field_type: FieldType, + /// Flip Bit Border + pub flip_bit_order: Option, } impl Field { - fn format_int( + fn format_int( byte_stream: &ByteStream, bit_ndx: usize, bit_width: usize, ) -> Result<(String, usize), FormatError> { let mut bytes = byte_stream.get_bytes(bit_ndx, bit_width)?; - if let Some(last_byte) = bytes.last_mut() { + if let Some(last_byte) = T::last_byte(&mut bytes) { let last_bit = ((bit_width - 1) % 8) as u8; let sign_bit = (*last_byte >> last_bit) & 0x1 == 1; @@ -79,7 +129,7 @@ impl Field { *last_byte |= !bit_mask(last_bit + 1) } - let big_int = BigInt::from_signed_bytes_le(&bytes); + let big_int = T::big_int(&bytes); Ok((big_int.to_string(), bit_width)) } else { @@ -87,35 +137,35 @@ impl Field { } } - fn format_uint( + fn format_uint( byte_stream: &ByteStream, bit_ndx: usize, bit_width: usize, ) -> Result<(String, usize), FormatError> { let bytes = byte_stream.get_bytes(bit_ndx, bit_width)?; - let big_int = BigUint::from_bytes_le(&bytes); + let big_int = T::big_uint(&bytes); Ok((big_int.to_string(), bit_width)) } - fn format_float( + fn format_float( 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)) + Ok((cursor.read_f32::().unwrap().to_string(), 4)) } - fn format_double( + fn format_double( 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)) + Ok((cursor.read_f64::().unwrap().to_string(), 4)) } fn format_string( @@ -164,10 +214,40 @@ impl Field { bit_ndx: usize, ) -> Result<(String, usize), FormatError> { match self.field_type { - 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::Float => Self::format_float(byte_stream, bit_ndx), - FieldType::Double => Self::format_double(byte_stream, bit_ndx), + FieldType::UInt { + bit_width, + endianness, + } => match endianness { + BigEndianness::LittleEndian => { + Self::format_uint::(byte_stream, bit_ndx, bit_width) + } + BigEndianness::BigEndian => { + Self::format_uint::(byte_stream, bit_ndx, bit_width) + } + }, + FieldType::Int { + bit_width, + endianness, + } => match endianness { + BigEndianness::LittleEndian => { + Self::format_int::(byte_stream, bit_ndx, bit_width) + } + BigEndianness::BigEndian => { + Self::format_int::(byte_stream, bit_ndx, bit_width) + } + }, + FieldType::Float { endianness } => match endianness { + BigEndianness::LittleEndian => { + Self::format_float::(byte_stream, bit_ndx) + } + BigEndianness::BigEndian => Self::format_float::(byte_stream, bit_ndx), + }, + FieldType::Double { endianness } => match endianness { + BigEndianness::LittleEndian => { + Self::format_double::(byte_stream, bit_ndx) + } + BigEndianness::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), } @@ -178,6 +258,8 @@ impl Field { pub struct Format { /// Format Name pub name: String, + /// Flip bits + pub bit_flip: bool, /// Elements of the format pub fields: Vec, } @@ -208,17 +290,21 @@ impl Format { #[cfg(test)] mod tests { use crate::byte_stream::ByteStream; - use crate::formatter::format::{Field, FieldType}; + use crate::formatter::format::{BigEndianness, Field, FieldType}; #[test] fn test_format_int_4_bits() { let field = Field { - field_type: FieldType::Int { bit_width: 4 }, + field_type: FieldType::Int { + bit_width: 4, + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; for i in 0i8..7i8 { - let mut byte_vec = Vec::new(); + let mut byte_vec = ::new(); byte_vec.push(i as u8); byte_vec.push((-i) as u8); @@ -234,8 +320,12 @@ mod tests { #[test] fn test_format_int_5_bits() { let field = Field { - field_type: FieldType::Int { bit_width: 5 }, + field_type: FieldType::Int { + bit_width: 5, + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![0x1B]); let (output, _) = field.format_data(&byte_steam, 0).unwrap(); @@ -246,8 +336,12 @@ mod tests { #[test] fn test_format_int_16_bits() { let field = Field { - field_type: FieldType::Int { bit_width: 16 }, + field_type: FieldType::Int { + bit_width: 16, + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![0xFC, 0xA5]); @@ -259,8 +353,12 @@ mod tests { #[test] fn test_format_int_16_bits_not_aligned() { let field = Field { - field_type: FieldType::Int { bit_width: 16 }, + field_type: FieldType::Int { + bit_width: 16, + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![0xC0, 0x5F, 0x0A]); @@ -272,8 +370,11 @@ mod tests { #[test] fn test_format_float() { let field = Field { - field_type: FieldType::Float, + field_type: FieldType::Float { + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec()); @@ -285,8 +386,11 @@ mod tests { #[test] fn test_format_double() { let field = Field { - field_type: FieldType::Double, + field_type: FieldType::Double { + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(b"\xD7\xA3\x70\x3D\x0A\x4B\x7A\xC0".to_vec()); @@ -298,8 +402,11 @@ mod tests { #[test] fn test_format_float_err() { let field = Field { - field_type: FieldType::Double, + field_type: FieldType::Double { + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(b"\x3D\x70\xA3\xD7".to_vec()); @@ -312,6 +419,7 @@ mod tests { let field = Field { field_type: FieldType::String { max_len: 16 }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(b"Hello World!\0".to_vec()); @@ -326,6 +434,7 @@ mod tests { let field = Field { field_type: FieldType::Bytes { max_len: 2 }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]); @@ -340,6 +449,7 @@ mod tests { let field = Field { field_type: FieldType::Bytes { max_len: 64 }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![0xDE, 0xAD]); @@ -352,8 +462,12 @@ mod tests { #[test] fn test_ccsds_apid_issue() { let field = Field { - field_type: FieldType::UInt { bit_width: 11 }, + field_type: FieldType::UInt { + bit_width: 11, + endianness: BigEndianness::LittleEndian, + }, name: "test".to_string(), + flip_bit_order: None, }; let byte_steam = ByteStream::from(vec![