use core::num::NonZeroUsize;
use core::ops;
use super::error::Error;
use super::payload::InstructionTrace;
use super::truncate::TruncateNum;
use super::unit::Unit;
use super::width::Widths;
use super::{encap, esp32, smi};
#[derive(Clone)]
pub struct Decoder<'d, U> {
data: &'d [u8],
bit_pos: usize,
field_widths: Widths,
unit: U,
hart_index_width: u8,
timestamp_width: u8,
trace_type_width: u8,
}
impl<'d, U> Decoder<'d, U> {
pub(super) fn new(
field_widths: Widths,
unit: U,
hart_index_width: u8,
timestamp_width: u8,
trace_type_width: u8,
) -> Self {
Self {
data: &[],
bit_pos: 0,
field_widths,
unit,
hart_index_width,
timestamp_width,
trace_type_width,
}
}
pub fn bytes_left(&self) -> usize {
self.data.len().saturating_sub(self.bit_pos >> 3)
}
pub fn byte_pos(&self) -> usize {
self.bit_pos >> 3
}
pub fn reset(&mut self, data: &'d [u8]) {
self.bit_pos = 0;
self.data = data;
}
pub fn decode<T: Decode<'d, U>>(&mut self) -> Result<T, Error> {
Decode::decode(self)
}
pub fn decode_encap_packet(&mut self) -> Result<encap::Packet<Self>, Error>
where
U: Clone,
{
Decode::decode(self)
}
pub fn decode_smi_packet(&mut self) -> Result<smi::Packet<Self>, Error>
where
U: Clone,
{
Decode::decode(self)
}
pub fn decode_esp32_packet(&mut self) -> Result<esp32::Packet<Self>, Error>
where
U: Clone,
{
Decode::decode(self)
}
pub fn decode_payload(&mut self) -> Result<InstructionTrace<U::IOptions, U::DOptions>, Error>
where
U: Unit,
{
Decode::decode(self)
}
pub fn unit(&self) -> &U {
&self.unit
}
pub(super) fn widths(&self) -> &Widths {
&self.field_widths
}
pub(super) fn hart_index_width(&self) -> u8 {
self.hart_index_width
}
pub(super) fn timestamp_width(&self) -> u8 {
self.timestamp_width
}
pub(super) fn trace_type_width(&self) -> u8 {
self.trace_type_width
}
pub(super) fn advance_to_byte(&mut self) {
if self.bit_pos & 0x7 != 0 {
self.bit_pos = (self.bit_pos & !0x7usize) + 8;
}
}
pub fn remaining_data(&self) -> &'d [u8] {
self.data
.split_at_checked(self.bit_pos >> 3)
.unwrap_or_default()
.1
}
pub fn split_off_to(&mut self, pos: usize) -> Result<Self, Error>
where
U: Clone,
{
let pos = self.byte_pos().saturating_add(pos);
if let Some((data, remaining)) = self.data.split_at_checked(pos) {
let mut res = self.clone();
res.data = data;
self.reset(remaining);
Ok(res)
} else {
let need = pos
.checked_sub(self.data.len())
.and_then(NonZeroUsize::new)
.unwrap_or(NonZeroUsize::MIN);
Err(Error::InsufficientData(need))
}
}
pub(super) fn read_bit(&mut self) -> Result<bool, Error> {
let res = (self.get_byte(self.bit_pos >> 3)? >> (self.bit_pos & 0x07)) & 0x1;
self.bit_pos += 1;
Ok(res != 0)
}
pub(super) fn read_differential_bit(&mut self) -> Result<bool, Error> {
let reference_pos = self
.bit_pos
.checked_sub(1)
.ok_or(Error::InsufficientData(NonZeroUsize::MIN))?;
let reference_bit = (self.get_byte(reference_pos >> 3)? >> (reference_pos & 0x07)) & 0x1;
let raw_bit = (self.get_byte(self.bit_pos >> 3)? >> (self.bit_pos & 0x07)) & 0x1;
self.bit_pos += 1;
Ok(reference_bit ^ raw_bit != 0)
}
pub(super) fn read_bits<T>(&mut self, bit_count: u8) -> Result<T, Error>
where
T: From<u8>
+ ops::Shl<usize, Output = T>
+ ops::Shr<usize, Output = T>
+ ops::BitOrAssign<T>
+ TruncateNum,
{
let lowest_bits = self.bit_pos & 0x07;
let mut byte_pos = self.bit_pos >> 3;
let mut res = T::from(self.get_byte(byte_pos)?) >> lowest_bits;
let mut bits_extracted = 8 - lowest_bits;
while bits_extracted < bit_count.into() {
byte_pos += 1;
res |= T::from(self.get_byte(byte_pos)?) << bits_extracted;
bits_extracted += 8;
}
self.bit_pos += usize::from(bit_count);
Ok(res.truncated(bit_count))
}
fn get_byte(&self, pos: usize) -> Result<u8, Error> {
if let Some(byte) = self.data.get(pos) {
Ok(*byte)
} else {
self.data
.last()
.map(|b| if b & 0x80 != 0 { 0xFF } else { 0x00 })
.ok_or(Error::InsufficientData(NonZeroUsize::MIN))
}
}
}
pub trait Decode<'d, U>: Sized {
fn decode(decoder: &mut Decoder<'d, U>) -> Result<Self, Error>;
}