Int formatting working
+ Using num-bigint to support arbitrarily sized ints + Added formatting testspull/1/head
parent
b85ba31f91
commit
9e5b0aafbd
|
@ -22,6 +22,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -54,6 +60,7 @@ name = "formaty"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"num-bigint",
|
||||||
"serde",
|
"serde",
|
||||||
"structopt",
|
"structopt",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -89,6 +96,36 @@ version = "0.2.101"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
|
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|
|
@ -10,3 +10,4 @@ structopt = "0.3.23"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
toml = "0.5.8"
|
toml = "0.5.8"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
|
num-bigint = "0.4"
|
|
@ -3,7 +3,7 @@ pub enum ByteStreamError {
|
||||||
OutOfRange,
|
OutOfRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn bit_mask(mask: u8) -> u8 {
|
pub const fn bit_mask(mask: u8) -> u8 {
|
||||||
match mask {
|
match mask {
|
||||||
0 => 0x00,
|
0 => 0x00,
|
||||||
1 => 0x01,
|
1 => 0x01,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::byte_stream::ByteStream;
|
use crate::byte_stream::{ByteStream, bit_mask};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use num_bigint::{BigUint, BigInt};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
|
@ -24,18 +25,38 @@ pub struct Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
|
fn format_int(byte_stream: &ByteStream, bit_ndx: usize, bit_width: usize) -> (String, usize) {
|
||||||
|
let mut bytes = byte_stream.get_bytes(bit_ndx, bit_width).unwrap();
|
||||||
|
|
||||||
|
if let Some(last_byte) = bytes.last_mut() {
|
||||||
|
let last_bit = ((bit_width - 1) % 8) as u8;
|
||||||
|
let sign_bit = (*last_byte >> last_bit) & 0x1 == 1;
|
||||||
|
|
||||||
|
if sign_bit {
|
||||||
|
// Sign extend
|
||||||
|
*last_byte |= !bit_mask(last_bit + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
let big_int = BigInt::from_signed_bytes_be(&bytes);
|
||||||
|
|
||||||
|
(big_int.to_string(), bit_width)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
("".to_string(), bit_width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_uint(byte_stream: &ByteStream, bit_ndx: usize, bit_width: usize) -> (String, usize) {
|
||||||
|
let bytes = byte_stream.get_bytes(bit_ndx, bit_width).unwrap();
|
||||||
|
|
||||||
|
let big_int = BigUint::from_bytes_be(&bytes);
|
||||||
|
(big_int.to_string(), bit_width)
|
||||||
|
}
|
||||||
|
|
||||||
fn format_data(&self, byte_stream: &ByteStream, bit_ndx: usize) -> (String, usize) {
|
fn format_data(&self, byte_stream: &ByteStream, bit_ndx: usize) -> (String, usize) {
|
||||||
match self.field_type {
|
match self.field_type {
|
||||||
FieldType::UInt { bit_width } => {
|
FieldType::UInt { bit_width } => Self::format_uint(byte_stream, bit_ndx, bit_width),
|
||||||
let bytes = byte_stream.get_bytes(bit_ndx, bit_width).unwrap();
|
FieldType::Int { bit_width } => Self::format_int(byte_stream, bit_ndx, bit_width),
|
||||||
let mut string = String::with_capacity(bytes.len() * 2);
|
|
||||||
|
|
||||||
for byte in bytes.iter().rev() {
|
|
||||||
string.push_str(&format!("{:x}", byte))
|
|
||||||
}
|
|
||||||
|
|
||||||
(string, bit_width)
|
|
||||||
}
|
|
||||||
_ => ("".to_string(), 0),
|
_ => ("".to_string(), 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,3 +85,58 @@ impl Format {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::formatter::format::{FieldType, Field};
|
||||||
|
use crate::byte_stream::ByteStream;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_int_4_bits() {
|
||||||
|
let field = Field {field_type: FieldType::Int {bit_width: 4,}, name: "test".to_string()};
|
||||||
|
|
||||||
|
for i in 0i8..7i8 {
|
||||||
|
let mut byte_vec = Vec::new();
|
||||||
|
byte_vec.push(i as u8);
|
||||||
|
byte_vec.push((-i) as u8);
|
||||||
|
|
||||||
|
let byte_steam = ByteStream::from(byte_vec);
|
||||||
|
let (pos_output, _) = field.format_data(&byte_steam, 0);
|
||||||
|
let (neg_output, _) = field.format_data(&byte_steam, 8);
|
||||||
|
|
||||||
|
assert_eq!(pos_output, i.to_string());
|
||||||
|
assert_eq!(neg_output, (-i).to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_int_5_bits() {
|
||||||
|
let field = Field {field_type: FieldType::Int {bit_width: 5,}, name: "test".to_string()};
|
||||||
|
let byte_steam = ByteStream::from(vec![0x1B]);
|
||||||
|
let (output, _) = field.format_data(&byte_steam, 0);
|
||||||
|
|
||||||
|
assert_eq!(output, "-5")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_int_16_bits() {
|
||||||
|
let field = Field {field_type: FieldType::Int {bit_width: 16,}, name: "test".to_string()};
|
||||||
|
|
||||||
|
|
||||||
|
let byte_steam = ByteStream::from(vec![0xA5, 0xFC]);
|
||||||
|
let (output, _) = field.format_data(&byte_steam, 0);
|
||||||
|
|
||||||
|
assert_eq!(output, "-23044")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_int_16_bits_not_aligned() {
|
||||||
|
let field = Field {field_type: FieldType::Int {bit_width: 16,}, name: "test".to_string()};
|
||||||
|
|
||||||
|
|
||||||
|
let byte_steam = ByteStream::from(vec![0x50, 0xCA, 0x0F]);
|
||||||
|
let (output, _) = field.format_data(&byte_steam, 4);
|
||||||
|
|
||||||
|
assert_eq!(output, "-23044")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue