From bb6f331c7555e35f6c3a6a347c199470dc262097 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Sat, 9 Oct 2021 13:58:41 -0600 Subject: [PATCH] Cleared up issue with parsing ints + Endianness was all out of whack + Everything is currently handled as little endian, easy to add a config for endianness later + num-bigint comes in clutch, it now handles the shifting of bits --- formats/ccsds.toml | 2 +- src/byte_stream/mod.rs | 26 ++++++++++---------------- src/formatter/format.rs | 29 ++++++++++++++++++++--------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/formats/ccsds.toml b/formats/ccsds.toml index 9d5766d..55c4397 100644 --- a/formats/ccsds.toml +++ b/formats/ccsds.toml @@ -3,7 +3,7 @@ # Ref: https://public.ccsds.org/Pubs/133x0b2e1.pdfa # # Example Packet: -# [0x08, 0x55, 0xc0, 0x00, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05] +# [0xe0, 0xa1, 0xc0, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05] [[formats]] name = "ccsds" diff --git a/src/byte_stream/mod.rs b/src/byte_stream/mod.rs index 02fcf1a..a746b53 100644 --- a/src/byte_stream/mod.rs +++ b/src/byte_stream/mod.rs @@ -1,4 +1,5 @@ use std::fmt::{Display, Formatter}; +use num_bigint::BigUint; #[derive(Clone, Debug)] pub enum ByteStreamError { @@ -32,13 +33,14 @@ pub struct ByteStream { data: Vec, } + impl ByteStream { 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; - let byte_count = if bit_count >= 8 { bit_count / 8 } else { 1 }; - let bytes_needed = if bits_before != 0 { + let byte_count = ((bit_count as f32) / (8.0)).ceil() as usize; + let bytes_needed = if (bits_before as usize + bit_count) % 8 != 0 && !(bits_before as usize + bit_count < 8){ byte_count + 1 } else { byte_count @@ -48,21 +50,13 @@ impl ByteStream { return Err(ByteStreamError::OutOfRange); } - let mut byte_stream = self.data[byte_ndx..byte_ndx + bytes_needed].to_vec(); + let byte_stream = self.data[byte_ndx..byte_ndx + bytes_needed].to_vec(); - if bits_before != 0 { - let mut carry: u8 = 0; - for _ in 0..bits_before { - for k in (0..bytes_needed).rev() { - let next: u8 = (byte_stream[k] & 0x01) << 7; - byte_stream[k] = (byte_stream[k] >> 1) | carry; + let number = BigUint::from_bytes_le(&byte_stream) >> bits_before; - carry = next; - } - } - } + let mut byte_stream = number.to_bytes_le(); - if bytes_needed > byte_count { + if bytes_needed > byte_count && bytes_needed == byte_stream.len() { byte_stream.pop(); } @@ -105,11 +99,11 @@ mod tests { #[test] fn test_get_bytes_with_shift_in_byte() { - let bytes: Vec = vec![0xff, 0x00, 0x55]; + let bytes: Vec = vec![0x5f, 0x00, 0x55]; let bit_stream = ByteStream::from(bytes.clone()); let new_bytes = bit_stream.get_bytes(4, 4).unwrap(); - assert_eq!(vec![0x0f], new_bytes); + assert_eq!(vec![0x05], new_bytes); } #[test] diff --git a/src/formatter/format.rs b/src/formatter/format.rs index da5a4ef..ef1ccf1 100644 --- a/src/formatter/format.rs +++ b/src/formatter/format.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use std::fmt::{Write, Display, Formatter}; use num_bigint::{BigUint, BigInt}; use std::io::Cursor; -use byteorder::{BigEndian, ReadBytesExt}; +use byteorder::{LittleEndian, ReadBytesExt}; use std::string::FromUtf8Error; use crate::formatter::printers::print_bytes_as_array; @@ -75,7 +75,7 @@ impl Field { *last_byte |= !bit_mask(last_bit + 1) } - let big_int = BigInt::from_signed_bytes_be(&bytes); + let big_int = BigInt::from_signed_bytes_le(&bytes); Ok((big_int.to_string(), bit_width)) } @@ -87,7 +87,7 @@ impl Field { 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_be(&bytes); + let big_int = BigUint::from_bytes_le(&bytes); Ok((big_int.to_string(), bit_width)) } @@ -95,14 +95,14 @@ impl Field { 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(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(byte_stream: &ByteStream, mut bit_ndx: usize, max_byte_len: usize) -> Result<(String, usize), FormatError> { @@ -218,7 +218,7 @@ mod tests { let field = Field {field_type: FieldType::Int {bit_width: 16,}, name: "test".to_string()}; - let byte_steam = ByteStream::from(vec![0xA5, 0xFC]); + let byte_steam = ByteStream::from(vec![0xFC, 0xA5]); let (output, _) = field.format_data(&byte_steam, 0).unwrap(); assert_eq!(output, "-23044") @@ -229,7 +229,7 @@ mod tests { let field = Field {field_type: FieldType::Int {bit_width: 16,}, name: "test".to_string()}; - let byte_steam = ByteStream::from(vec![0x50, 0xCA, 0x0F]); + let byte_steam = ByteStream::from(vec![0xC0, 0x5F, 0x0A]); let (output, _) = field.format_data(&byte_steam, 4).unwrap(); assert_eq!(output, "-23044") @@ -239,7 +239,7 @@ mod tests { fn test_format_float() { let field = Field {field_type: FieldType::Float, name: "test".to_string()}; - let byte_steam = ByteStream::from(b"\xc3\xd2\x58\x52".to_vec()); + let byte_steam = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec()); let (output, _) = field.format_data(&byte_steam, 0).unwrap(); assert_eq!(output, "-420.69") @@ -249,7 +249,7 @@ mod tests { fn test_format_double() { let field = Field {field_type: FieldType::Double, name: "test".to_string()}; - let byte_steam = ByteStream::from(b"\xC0\x7A\x4B\x0A\x3D\x70\xA3\xD7".to_vec()); + 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(); assert_eq!(output, "-420.69") @@ -296,4 +296,15 @@ mod tests { assert_eq!(output, "[222, 173]") } + + #[test] + fn test_ccsds_apid_issue() { + let field = Field {field_type: FieldType::UInt {bit_width: 11}, name: "test".to_string()}; + + let byte_steam = ByteStream::from(vec![0xe0, 0xa1, 0xc0, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05]); + + let (output, _) = field.format_data(&byte_steam, 5).unwrap(); + + assert_eq!(output, "1295") + } }