Added endianness support
This commit is contained in:
		
							parent
							
								
									2697b4b848
								
							
						
					
					
						commit
						e822d9ff13
					
				| @ -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" | ||||
|  | ||||
| @ -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<u8>) -> 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<u8>) -> 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<u8>) -> 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<bool>, | ||||
| } | ||||
| 
 | ||||
| impl Field { | ||||
|     fn format_int( | ||||
|     fn format_int<T: LastByte>( | ||||
|         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<T: LastByte>( | ||||
|         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<T: LastByte>( | ||||
|         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::<LittleEndian>().unwrap().to_string(), 4)) | ||||
|         Ok((cursor.read_f32::<T>().unwrap().to_string(), 4)) | ||||
|     } | ||||
| 
 | ||||
|     fn format_double( | ||||
|     fn format_double<T: LastByte>( | ||||
|         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::<LittleEndian>().unwrap().to_string(), 4)) | ||||
|         Ok((cursor.read_f64::<T>().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::<LittleEndian>(byte_stream, bit_ndx, bit_width) | ||||
|                 } | ||||
|                 BigEndianness::BigEndian => { | ||||
|                     Self::format_uint::<BigEndian>(byte_stream, bit_ndx, bit_width) | ||||
|                 } | ||||
|             }, | ||||
|             FieldType::Int { | ||||
|                 bit_width, | ||||
|                 endianness, | ||||
|             } => match endianness { | ||||
|                 BigEndianness::LittleEndian => { | ||||
|                     Self::format_int::<LittleEndian>(byte_stream, bit_ndx, bit_width) | ||||
|                 } | ||||
|                 BigEndianness::BigEndian => { | ||||
|                     Self::format_int::<BigEndian>(byte_stream, bit_ndx, bit_width) | ||||
|                 } | ||||
|             }, | ||||
|             FieldType::Float { endianness } => match endianness { | ||||
|                 BigEndianness::LittleEndian => { | ||||
|                     Self::format_float::<LittleEndian>(byte_stream, bit_ndx) | ||||
|                 } | ||||
|                 BigEndianness::BigEndian => Self::format_float::<BigEndian>(byte_stream, bit_ndx), | ||||
|             }, | ||||
|             FieldType::Double { endianness } => match endianness { | ||||
|                 BigEndianness::LittleEndian => { | ||||
|                     Self::format_double::<LittleEndian>(byte_stream, bit_ndx) | ||||
|                 } | ||||
|                 BigEndianness::BigEndian => Self::format_double::<BigEndian>(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<Field>, | ||||
| } | ||||
| @ -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![ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user