use super::primitives::*;
macro_rules! read_multi_byte_num {
($num_type:ty, $length:expr, $raw:ident, $pos:expr, $order:expr, $default:expr) => {{
let pos_after_read = *$pos + $length;
if pos_after_read <= $raw.len() {
let mut tmp = [0u8; $length];
tmp.copy_from_slice(&$raw[*$pos..pos_after_read]);
*$pos = pos_after_read;
match $order {
ByteOrder::LittleEndian => <$num_type>::from_le_bytes(tmp),
ByteOrder::BigEndian => <$num_type>::from_be_bytes(tmp),
}
} else {
$default
}
}};
}
macro_rules! read_multi_element {
($count:expr, $func:ident($($arg:tt)+)) => {
{
let mut value = Vec::with_capacity($count as usize);
for _ in 0..$count {
value.push( $func($($arg)+) );
}
value
}
}
}
#[inline(always)]
pub(crate) fn read_uint8(raw_data: &[u8], pos: &mut usize) -> u8 {
if *pos < raw_data.len() {
let value = (*raw_data)[*pos];
*pos += 1;
value
} else {
0
}
}
#[inline(always)]
pub(crate) fn read_u2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U2 {
read_multi_byte_num!(U2, 2, raw_data, pos, order, 0)
}
#[inline(always)]
pub(crate) fn read_u4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U4 {
read_multi_byte_num!(U4, 4, raw_data, pos, order, 0)
}
#[inline(always)]
pub(crate) fn read_u8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> U8 {
read_multi_byte_num!(U8, 8, raw_data, pos, order, 0)
}
#[inline(always)]
pub(crate) fn read_i1(raw_data: &[u8], pos: &mut usize) -> I1 {
if *pos < raw_data.len() {
let value = (*raw_data)[*pos] as I1;
*pos += 1;
value
} else {
0
}
}
#[inline(always)]
pub(crate) fn read_i2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> I2 {
read_multi_byte_num!(I2, 2, raw_data, pos, order, 0)
}
#[inline(always)]
pub(crate) fn read_i4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> I4 {
read_multi_byte_num!(I4, 4, raw_data, pos, order, 0)
}
#[inline(always)]
pub(crate) fn read_r4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> R4 {
read_multi_byte_num!(R4, 4, raw_data, pos, order, 0.0)
}
#[inline(always)]
pub(crate) fn read_r8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> R8 {
read_multi_byte_num!(R8, 8, raw_data, pos, order, 0.0)
}
#[inline(always)]
pub(crate) fn read_cn(raw_data: &[u8], pos: &mut usize) -> Cn {
let count = read_uint8(raw_data, pos) as usize;
let mut value = String::default();
if count != 0 {
let min_pos = std::cmp::min(*pos + count, raw_data.len());
value = bytes_to_string(&raw_data[*pos..min_pos]);
*pos = min_pos;
}
value
}
#[inline(always)]
pub(crate) fn read_sn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> Sn {
let count = read_u2(raw_data, pos, order) as usize;
let mut value = String::default();
if count != 0 {
let min_pos = std::cmp::min(*pos + count, raw_data.len());
value = bytes_to_string(&raw_data[*pos..min_pos]);
*pos = min_pos;
}
value
}
#[inline(always)]
pub(crate) fn read_cf(raw_data: &[u8], pos: &mut usize, f: u8) -> Cf {
let mut value = String::default();
if f != 0 {
let pos_after_read = *pos + (f as usize);
if pos_after_read <= raw_data.len() {
value = bytes_to_string(&raw_data[*pos..pos_after_read]);
*pos = pos_after_read;
} else {
value = bytes_to_string(&raw_data[*pos..]);
*pos = raw_data.len();
}
}
value
}
#[inline(always)]
pub(crate) fn read_bn(raw_data: &[u8], pos: &mut usize) -> Bn {
let count = read_uint8(raw_data, pos) as usize;
if count != 0 {
let min_pos = std::cmp::min(*pos + count, raw_data.len());
let data_slice = &raw_data[*pos..min_pos];
*pos = min_pos;
let mut value = vec![0u8; data_slice.len()];
value.copy_from_slice(data_slice);
value
} else {
vec![0u8; 0]
}
}
#[inline(always)]
pub(crate) fn read_dn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> Dn {
let bitcount = read_u2(raw_data, pos, order) as usize;
let bytecount = bitcount.div_ceil(8);
if bytecount != 0 {
let min_pos = std::cmp::min(*pos + bytecount, raw_data.len());
let data_slice = &raw_data[*pos..min_pos];
*pos = min_pos;
let mut value = vec![0u8; data_slice.len()];
value.copy_from_slice(data_slice);
value
} else {
vec![0u8; 0]
}
}
#[inline(always)]
pub(crate) fn read_kx_cn(raw_data: &[u8], pos: &mut usize, k: u16) -> KxCn {
read_multi_element!(k, read_cn(raw_data, pos))
}
#[inline(always)]
pub(crate) fn read_kx_sn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxSn {
read_multi_element!(k, read_sn(raw_data, pos, order))
}
#[inline(always)]
pub(crate) fn read_kx_cf(raw_data: &[u8], pos: &mut usize, k: u16, f: u8) -> KxCf {
let mut value = Vec::with_capacity(k as usize);
for _ in 0..k {
value.push(read_cf(raw_data, pos, f));
}
value
}
#[inline(always)]
pub(crate) fn read_kx_u1(raw_data: &[u8], pos: &mut usize, k: u16) -> KxU1 {
read_multi_element!(k, read_uint8(raw_data, pos))
}
#[inline(always)]
pub(crate) fn read_kx_u2(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU2 {
read_multi_element!(k, read_u2(raw_data, pos, order))
}
#[inline(always)]
pub(crate) fn read_kx_u4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU4 {
read_multi_element!(k, read_u4(raw_data, pos, order))
}
#[inline(always)]
pub(crate) fn read_kx_u8(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxU8 {
read_multi_element!(k, read_u8(raw_data, pos, order))
}
#[inline(always)]
pub(crate) fn read_kx_uf(
raw_data: &[u8],
pos: &mut usize,
order: &ByteOrder,
k: u16,
f: u8,
) -> KxUf {
if k != 0 {
match f {
1 => KxUf::F1(read_kx_u1(raw_data, pos, k)),
2 => KxUf::F2(read_kx_u2(raw_data, pos, order, k)),
4 => KxUf::F4(read_kx_u4(raw_data, pos, order, k)),
8 => KxUf::F8(read_kx_u8(raw_data, pos, order, k)),
_ => KxUf::F1(vec![0u8; 0]),
}
} else {
KxUf::F1(vec![0u8; 0])
}
}
#[inline(always)]
pub(crate) fn read_kx_r4(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> KxR4 {
read_multi_element!(k, read_r4(raw_data, pos, order))
}
#[inline(always)]
pub(crate) fn read_kx_n1(raw_data: &[u8], pos: &mut usize, k: u16) -> KxN1 {
if k != 0 {
let bytecount = k / 2 + k % 2; let mut value = Vec::with_capacity(k as usize);
for i in 0..bytecount {
let tmp = read_uint8(raw_data, pos);
value.push(tmp & 0x0F);
if (2 * i + 1) < k {
value.push((tmp & 0xF0) >> 4);
}
}
value
} else {
vec![0u8; 0]
}
}
#[inline(always)]
pub(crate) fn read_v1(raw_data: &[u8], pos: &mut usize, order: &ByteOrder) -> V1 {
let type_byte = if *pos < raw_data.len() {
read_uint8(raw_data, pos)
} else {
0xF
};
match type_byte {
0 => V1::B0,
1 => V1::U1(read_uint8(raw_data, pos)),
2 => V1::U2(read_u2(raw_data, pos, order)),
3 => V1::U4(read_u4(raw_data, pos, order)),
4 => V1::I1(read_i1(raw_data, pos)),
5 => V1::I2(read_i2(raw_data, pos, order)),
6 => V1::I4(read_i4(raw_data, pos, order)),
7 => V1::R4(read_r4(raw_data, pos, order)),
8 => V1::R8(read_r8(raw_data, pos, order)),
10 => V1::Cn(read_cn(raw_data, pos)),
11 => V1::Bn(read_bn(raw_data, pos)),
12 => V1::Dn(read_dn(raw_data, pos, order)),
13 => V1::N1(read_uint8(raw_data, pos) & 0x0F),
_ => V1::Invalid,
}
}
#[inline(always)]
pub(crate) fn read_vn(raw_data: &[u8], pos: &mut usize, order: &ByteOrder, k: u16) -> Vn {
read_multi_element!(k, read_v1(raw_data, pos, order))
}