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
pull/1/head
Joey Hines 2021-10-09 13:58:41 -06:00
parent 6daf3a55f2
commit bb6f331c75
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
3 changed files with 31 additions and 26 deletions

View File

@ -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"

View File

@ -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<u8>,
}
impl ByteStream {
pub fn get_bytes(&self, bit_ndx: usize, bit_count: usize) -> Result<Vec<u8>, 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<u8> = vec![0xff, 0x00, 0x55];
let bytes: Vec<u8> = 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]

View File

@ -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::<BigEndian>().unwrap().to_string(), 4))
Ok((cursor.read_f32::<LittleEndian>().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::<BigEndian>().unwrap().to_string(), 4))
Ok((cursor.read_f64::<LittleEndian>().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")
}
}