2021-10-09 20:00:49 +00:00
|
|
|
use crate::byte_stream::{bit_mask, ByteStream, ByteStreamError};
|
|
|
|
use crate::formatter::printers::print_bytes_as_array;
|
2022-04-06 02:45:58 +00:00
|
|
|
use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};
|
2021-10-09 20:00:49 +00:00
|
|
|
use num_bigint::{BigInt, BigUint};
|
2021-09-11 18:21:34 +00:00
|
|
|
use serde::Deserialize;
|
2021-10-09 20:00:49 +00:00
|
|
|
use std::fmt::{Display, Formatter, Write};
|
2021-10-09 15:30:02 +00:00
|
|
|
use std::io::Cursor;
|
2021-10-09 16:05:32 +00:00
|
|
|
use std::string::FromUtf8Error;
|
2021-10-09 15:30:02 +00:00
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
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;
|
2022-04-09 17:25:09 +00:00
|
|
|
|
|
|
|
fn big_u_int_to_bytes(big_int: BigUint) -> Vec<u8>;
|
|
|
|
|
|
|
|
fn big_int_to_bytes(big_int: BigInt) -> Vec<u8>;
|
2022-04-06 02:45:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
|
|
|
|
fn big_u_int_to_bytes(big_int: BigUint) -> Vec<u8> {
|
|
|
|
big_int.to_bytes_be()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn big_int_to_bytes(big_int: BigInt) -> Vec<u8> {
|
|
|
|
big_int.to_signed_bytes_be()
|
|
|
|
}
|
2022-04-06 02:45:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
|
|
|
|
fn big_u_int_to_bytes(big_int: BigUint) -> Vec<u8> {
|
|
|
|
big_int.to_bytes_le()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn big_int_to_bytes(big_int: BigInt) -> Vec<u8> {
|
|
|
|
big_int.to_signed_bytes_le()
|
|
|
|
}
|
2022-04-06 02:45:58 +00:00
|
|
|
}
|
|
|
|
|
2021-10-09 15:30:02 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum FormatError {
|
|
|
|
ByteSteamError(ByteStreamError),
|
2021-10-09 16:05:32 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
NotSupported,
|
|
|
|
StringParseError(FromUtf8Error),
|
2021-10-09 15:30:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ByteStreamError> for FormatError {
|
|
|
|
fn from(e: ByteStreamError) -> Self {
|
|
|
|
FormatError::ByteSteamError(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-09 16:05:32 +00:00
|
|
|
impl From<FromUtf8Error> for FormatError {
|
|
|
|
fn from(e: FromUtf8Error) -> Self {
|
|
|
|
FormatError::StringParseError(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-09 15:30:02 +00:00
|
|
|
impl Display for FormatError {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
2021-10-09 16:57:34 +00:00
|
|
|
FormatError::ByteSteamError(e) => writeln!(f, "Byte stream error: {}", e),
|
2021-10-09 16:05:32 +00:00
|
|
|
FormatError::NotSupported => write!(f, "Field type not supported"),
|
2021-10-09 20:00:49 +00:00
|
|
|
FormatError::StringParseError(e) => write!(f, "String parse error: {}", e),
|
2021-10-09 15:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-11 18:21:34 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
#[serde(tag = "type")]
|
|
|
|
pub enum FieldType {
|
|
|
|
/// Unsigned Int
|
2022-04-06 02:45:58 +00:00
|
|
|
UInt {
|
|
|
|
bit_width: usize,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-09-11 18:21:34 +00:00
|
|
|
/// Unsigned Int
|
2022-04-06 02:45:58 +00:00
|
|
|
Int {
|
|
|
|
bit_width: usize,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 15:30:02 +00:00
|
|
|
/// Single Precession Float
|
2022-04-09 17:25:09 +00:00
|
|
|
Float { endianness: Endianness },
|
2021-10-09 15:30:02 +00:00
|
|
|
/// Double Precession Float
|
2022-04-09 17:25:09 +00:00
|
|
|
Double { endianness: Endianness },
|
2021-09-11 18:21:34 +00:00
|
|
|
/// Null Terminated String Field
|
2022-04-09 17:25:09 +00:00
|
|
|
String {
|
|
|
|
max_len: usize,
|
|
|
|
endianness: Endianness,
|
|
|
|
},
|
2021-09-11 18:21:34 +00:00
|
|
|
/// Fixed Byte Length Field
|
2022-04-09 17:25:09 +00:00
|
|
|
Bytes {
|
|
|
|
max_len: usize,
|
|
|
|
endianness: Endianness,
|
|
|
|
},
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq, Copy)]
|
2022-04-09 17:25:09 +00:00
|
|
|
pub enum Endianness {
|
2022-04-06 02:45:58 +00:00
|
|
|
LittleEndian,
|
|
|
|
BigEndian,
|
|
|
|
}
|
|
|
|
|
2021-09-11 18:21:34 +00:00
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
pub struct Field {
|
|
|
|
/// Field Name
|
|
|
|
pub name: String,
|
|
|
|
/// Field Type
|
|
|
|
pub field_type: FieldType,
|
2022-04-09 17:25:09 +00:00
|
|
|
/// Flip Bit Order
|
|
|
|
pub bit_flip: Option<bool>,
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
fn format_int<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
bit_ndx: usize,
|
|
|
|
bit_width: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2022-04-09 17:25:09 +00:00
|
|
|
let mut bytes = byte_stream.get_bytes::<T>(bit_ndx, bit_width)?;
|
2021-09-11 18:21:34 +00:00
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
if let Some(last_byte) = T::last_byte(&mut bytes) {
|
2021-10-09 14:42:17 +00:00
|
|
|
let last_bit = ((bit_width - 1) % 8) as u8;
|
|
|
|
let sign_bit = (*last_byte >> last_bit) & 0x1 == 1;
|
2021-09-11 18:21:34 +00:00
|
|
|
|
2021-10-09 14:42:17 +00:00
|
|
|
if sign_bit {
|
|
|
|
// Sign extend
|
|
|
|
*last_byte |= !bit_mask(last_bit + 1)
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
2021-10-09 14:42:17 +00:00
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
let big_int = T::big_int(&bytes);
|
2021-10-09 14:42:17 +00:00
|
|
|
|
2021-10-09 15:30:02 +00:00
|
|
|
Ok((big_int.to_string(), bit_width))
|
2021-10-09 20:00:49 +00:00
|
|
|
} else {
|
2021-10-09 15:30:02 +00:00
|
|
|
Err(ByteStreamError::OutOfRange.into())
|
2021-10-09 14:42:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
fn format_uint<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
bit_ndx: usize,
|
|
|
|
bit_width: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2022-04-09 17:25:09 +00:00
|
|
|
let bytes = byte_stream.get_bytes::<T>(bit_ndx, bit_width)?;
|
2021-10-09 14:42:17 +00:00
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
let big_int = T::big_uint(&bytes);
|
2021-10-09 15:30:02 +00:00
|
|
|
Ok((big_int.to_string(), bit_width))
|
|
|
|
}
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
fn format_float<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
bit_ndx: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2022-04-09 17:25:09 +00:00
|
|
|
let bytes = byte_stream.get_bytes::<T>(bit_ndx, 32)?;
|
2021-10-09 15:30:02 +00:00
|
|
|
let mut cursor = Cursor::new(bytes);
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
Ok((cursor.read_f32::<T>().unwrap().to_string(), 4))
|
2021-10-09 15:30:02 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
fn format_double<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
bit_ndx: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2022-04-09 17:25:09 +00:00
|
|
|
let bytes = byte_stream.get_bytes::<T>(bit_ndx, 64)?;
|
2021-10-09 15:30:02 +00:00
|
|
|
let mut cursor = Cursor::new(bytes);
|
|
|
|
|
2022-04-06 02:45:58 +00:00
|
|
|
Ok((cursor.read_f64::<T>().unwrap().to_string(), 4))
|
2021-10-09 14:42:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-09 17:25:09 +00:00
|
|
|
fn format_string<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
mut bit_ndx: usize,
|
|
|
|
max_byte_len: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2021-10-09 16:05:32 +00:00
|
|
|
let mut string_bytes = Vec::new();
|
|
|
|
|
|
|
|
for _ in 0..max_byte_len {
|
2022-04-09 17:25:09 +00:00
|
|
|
let byte = byte_stream.get_bytes::<T>(bit_ndx, 8)?[0];
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
if byte == 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
string_bytes.push(byte);
|
|
|
|
bit_ndx += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
let byte_count = string_bytes.len();
|
|
|
|
Ok((String::from_utf8(string_bytes)?, byte_count))
|
|
|
|
}
|
|
|
|
|
2022-04-09 17:25:09 +00:00
|
|
|
fn format_bytes<T: LastByte>(
|
2021-10-09 20:00:49 +00:00
|
|
|
byte_stream: &ByteStream,
|
|
|
|
bit_ndx: usize,
|
|
|
|
max_byte_len: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
|
|
|
let data_remaining = byte_stream.len() - bit_ndx / 8;
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
let width = if max_byte_len < data_remaining {
|
2021-10-09 20:00:49 +00:00
|
|
|
max_byte_len * 8
|
|
|
|
} else {
|
|
|
|
data_remaining * 8
|
2021-10-09 16:05:32 +00:00
|
|
|
};
|
|
|
|
|
2022-04-09 17:25:09 +00:00
|
|
|
let data = byte_stream.get_bytes::<T>(bit_ndx, width)?;
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
Ok((print_bytes_as_array(&data), width))
|
|
|
|
}
|
|
|
|
|
2021-10-09 20:00:49 +00:00
|
|
|
fn format_data(
|
|
|
|
&self,
|
2022-04-09 17:25:09 +00:00
|
|
|
byte_stream: &mut ByteStream,
|
2021-10-09 20:00:49 +00:00
|
|
|
bit_ndx: usize,
|
|
|
|
) -> Result<(String, usize), FormatError> {
|
2022-04-09 17:25:09 +00:00
|
|
|
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 {
|
2022-04-06 02:45:58 +00:00
|
|
|
FieldType::UInt {
|
|
|
|
bit_width,
|
|
|
|
endianness,
|
|
|
|
} => match endianness {
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::LittleEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_uint::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::BigEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_uint::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
FieldType::Int {
|
|
|
|
bit_width,
|
|
|
|
endianness,
|
|
|
|
} => match endianness {
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::LittleEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_int::<LittleEndian>(byte_stream, bit_ndx, bit_width)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::BigEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_int::<BigEndian>(byte_stream, bit_ndx, bit_width)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
FieldType::Float { endianness } => match endianness {
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::LittleEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_float::<LittleEndian>(byte_stream, bit_ndx)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::BigEndian => Self::format_float::<BigEndian>(byte_stream, bit_ndx),
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
|
|
|
FieldType::Double { endianness } => match endianness {
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::LittleEndian => {
|
2022-04-06 02:45:58 +00:00
|
|
|
Self::format_double::<LittleEndian>(byte_stream, bit_ndx)
|
|
|
|
}
|
2022-04-09 17:25:09 +00:00
|
|
|
Endianness::BigEndian => Self::format_double::<BigEndian>(byte_stream, bit_ndx),
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2022-04-09 17:25:09 +00:00
|
|
|
FieldType::String {
|
|
|
|
max_len,
|
|
|
|
endianness,
|
|
|
|
} => match endianness {
|
|
|
|
Endianness::LittleEndian => {
|
|
|
|
Self::format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
|
|
|
}
|
|
|
|
Endianness::BigEndian => {
|
|
|
|
Self::format_string::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
FieldType::Bytes {
|
|
|
|
max_len,
|
|
|
|
endianness,
|
|
|
|
} => match endianness {
|
|
|
|
Endianness::LittleEndian => {
|
|
|
|
Self::format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
|
|
|
}
|
|
|
|
Endianness::BigEndian => {
|
|
|
|
Self::format_bytes::<LittleEndian>(byte_stream, bit_ndx, max_len)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}?;
|
|
|
|
|
|
|
|
byte_stream.set_reverse_bits(global_bit_flip);
|
|
|
|
|
|
|
|
Ok(fmt)
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
pub struct Format {
|
|
|
|
/// Format Name
|
|
|
|
pub name: String,
|
2022-04-06 02:45:58 +00:00
|
|
|
/// Flip bits
|
|
|
|
pub bit_flip: bool,
|
2021-09-11 18:21:34 +00:00
|
|
|
/// Elements of the format
|
|
|
|
pub fields: Vec<Field>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Format {
|
2021-10-09 15:30:02 +00:00
|
|
|
pub fn format_data(&self, data: &[u8]) -> Result<String, FormatError> {
|
|
|
|
let mut format_str = String::new();
|
2022-04-09 17:25:09 +00:00
|
|
|
let mut byte_stream = ByteStream::from(data);
|
2021-09-11 18:21:34 +00:00
|
|
|
let mut bit_ndx: usize = 0;
|
|
|
|
|
2022-04-09 17:25:09 +00:00
|
|
|
byte_stream.set_reverse_bits(self.bit_flip);
|
|
|
|
|
2021-09-11 18:21:34 +00:00
|
|
|
for field in &self.fields {
|
2022-04-09 17:25:09 +00:00
|
|
|
match field.format_data(&mut byte_stream, bit_ndx) {
|
2021-10-09 16:57:34 +00:00
|
|
|
Ok((data_str, bit_width)) => {
|
|
|
|
bit_ndx += bit_width;
|
|
|
|
writeln!(format_str, "{}: {}", field.name, data_str).unwrap();
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
println!("Error formatting field: \"{}\": {}", field.name, e);
|
|
|
|
return Err(e);
|
|
|
|
}
|
|
|
|
}
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-09 15:30:02 +00:00
|
|
|
Ok(format_str)
|
2021-09-11 18:21:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::byte_stream::ByteStream;
|
2022-04-09 17:25:09 +00:00
|
|
|
use crate::formatter::format::{Endianness, Field, FieldType};
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_int_4_bits() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Int {
|
|
|
|
bit_width: 4,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
for i in 0i8..7i8 {
|
2022-04-06 02:45:58 +00:00
|
|
|
let mut byte_vec = ::new();
|
2021-10-09 14:42:17 +00:00
|
|
|
byte_vec.push(i as u8);
|
|
|
|
byte_vec.push((-i) as u8);
|
|
|
|
|
|
|
|
let byte_steam = ByteStream::from(byte_vec);
|
2021-10-09 15:30:02 +00:00
|
|
|
let (pos_output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
let (neg_output, _) = field.format_data(&byte_steam, 8).unwrap();
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
assert_eq!(pos_output, i.to_string());
|
|
|
|
assert_eq!(neg_output, (-i).to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_int_5_bits() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Int {
|
|
|
|
bit_width: 5,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 14:42:17 +00:00
|
|
|
let byte_steam = ByteStream::from(vec![0x1B]);
|
2021-10-09 15:30:02 +00:00
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
assert_eq!(output, "-5")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_int_16_bits() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Int {
|
|
|
|
bit_width: 16,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 14:42:17 +00:00
|
|
|
|
2021-10-09 19:58:41 +00:00
|
|
|
let byte_steam = ByteStream::from(vec![0xFC, 0xA5]);
|
2021-10-09 15:30:02 +00:00
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
assert_eq!(output, "-23044")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_int_16_bits_not_aligned() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Int {
|
|
|
|
bit_width: 16,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 14:42:17 +00:00
|
|
|
|
2021-10-09 20:00:49 +00:00
|
|
|
let byte_steam = ByteStream::from(vec![0xC0, 0x5F, 0x0A]);
|
2021-10-09 15:30:02 +00:00
|
|
|
let (output, _) = field.format_data(&byte_steam, 4).unwrap();
|
2021-10-09 14:42:17 +00:00
|
|
|
|
|
|
|
assert_eq!(output, "-23044")
|
|
|
|
}
|
2021-10-09 15:30:02 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_float() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Float {
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 15:30:02 +00:00
|
|
|
|
2021-10-09 19:58:41 +00:00
|
|
|
let byte_steam = ByteStream::from(b"\x52\x58\xd2\xc3".to_vec());
|
2021-10-09 15:30:02 +00:00
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "-420.69")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_double() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Double {
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 15:30:02 +00:00
|
|
|
|
2021-10-09 19:58:41 +00:00
|
|
|
let byte_steam = ByteStream::from(b"\xD7\xA3\x70\x3D\x0A\x4B\x7A\xC0".to_vec());
|
2021-10-09 15:30:02 +00:00
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "-420.69")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_float_err() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::Double {
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 15:30:02 +00:00
|
|
|
|
|
|
|
let byte_steam = ByteStream::from(b"\x3D\x70\xA3\xD7".to_vec());
|
|
|
|
|
|
|
|
assert!(field.format_data(&byte_steam, 0).is_err())
|
|
|
|
}
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_string() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
|
|
|
field_type: FieldType::String { max_len: 16 },
|
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
let byte_steam = ByteStream::from(b"Hello World!\0".to_vec());
|
|
|
|
|
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "Hello World!".to_string())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_bytes() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
|
|
|
field_type: FieldType::Bytes { max_len: 2 },
|
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 16:05:32 +00:00
|
|
|
|
|
|
|
let byte_steam = ByteStream::from(vec![0xDE, 0xAD, 0xBE, 0xEF]);
|
|
|
|
|
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "[222, 173]")
|
|
|
|
}
|
2021-10-09 16:57:34 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_format_bytes_max_len_bigger_than_data() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
|
|
|
field_type: FieldType::Bytes { max_len: 64 },
|
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 16:57:34 +00:00
|
|
|
|
|
|
|
let byte_steam = ByteStream::from(vec![0xDE, 0xAD]);
|
|
|
|
|
|
|
|
let (output, _) = field.format_data(&byte_steam, 0).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "[222, 173]")
|
|
|
|
}
|
2021-10-09 19:58:41 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_ccsds_apid_issue() {
|
2021-10-09 20:00:49 +00:00
|
|
|
let field = Field {
|
2022-04-06 02:45:58 +00:00
|
|
|
field_type: FieldType::UInt {
|
|
|
|
bit_width: 11,
|
2022-04-09 17:25:09 +00:00
|
|
|
endianness: Endianness::LittleEndian,
|
2022-04-06 02:45:58 +00:00
|
|
|
},
|
2021-10-09 20:00:49 +00:00
|
|
|
name: "test".to_string(),
|
2022-04-09 17:25:09 +00:00
|
|
|
bit_flip: None,
|
2021-10-09 20:00:49 +00:00
|
|
|
};
|
2021-10-09 19:58:41 +00:00
|
|
|
|
2021-10-09 20:00:49 +00:00
|
|
|
let byte_steam = ByteStream::from(vec![
|
|
|
|
0xe0, 0xa1, 0xc0, 0x00, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
|
|
|
]);
|
2021-10-09 19:58:41 +00:00
|
|
|
|
|
|
|
let (output, _) = field.format_data(&byte_steam, 5).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(output, "1295")
|
|
|
|
}
|
2021-10-09 14:42:17 +00:00
|
|
|
}
|