use crate::error::{Converter, WRONG_OFFSET};
use crate::{Error, Result};
use std::io::{Read, Write};
pub enum PacketHeader {
Index(IndexPacketHeader),
Data(DataPacketHeader),
Ignored(IgnoredPacketHeader),
}
impl PacketHeader {
pub fn read(reader: &mut dyn Read) -> Result<Self> {
let mut buffer = [0_u8; 1];
reader
.read_exact(&mut buffer)
.read_err("Failed to read packet type ID")?;
if buffer[0] == IndexPacketHeader::ID {
Ok(PacketHeader::Index(IndexPacketHeader::read(reader)?))
} else if buffer[0] == DataPacketHeader::ID {
Ok(PacketHeader::Data(DataPacketHeader::read(reader)?))
} else if buffer[0] == IgnoredPacketHeader::ID {
Ok(PacketHeader::Ignored(IgnoredPacketHeader::read(reader)?))
} else {
Error::invalid("Found unknown packet ID when trying to read packet header")?
}
}
}
pub struct IndexPacketHeader {
pub packet_length: u64,
}
impl IndexPacketHeader {
pub const ID: u8 = 0;
pub fn read(reader: &mut dyn Read) -> Result<Self> {
let mut buffer = [0_u8; 15];
reader
.read_exact(&mut buffer)
.read_err("Failed to read index packet header")?;
if buffer[0] != 0 {
Error::invalid("The reserved bytes inside an index packet must be zero")?
}
for value in buffer.iter().skip(7) {
if *value != 0 {
Error::invalid("The reserved bytes inside an index packet must be zero")?
}
}
let packet_length =
u16::from_le_bytes(buffer[1..3].try_into().internal_err(WRONG_OFFSET)?) as u64 + 1;
let _entry_count = u16::from_le_bytes(buffer[3..5].try_into().internal_err(WRONG_OFFSET)?);
let _index_level = buffer[5];
if !packet_length.is_multiple_of(4) {
Error::invalid("Index packet length is not aligned and a multiple of four")?
}
Ok(Self { packet_length })
}
}
pub struct DataPacketHeader {
pub comp_restart_flag: bool,
pub packet_length: u64,
pub bytestream_count: u16,
}
impl DataPacketHeader {
pub const ID: u8 = 1;
pub const SIZE: usize = 6;
pub fn read(reader: &mut dyn Read) -> Result<Self> {
let mut buffer = [0_u8; 5];
reader
.read_exact(&mut buffer)
.read_err("Failed to read data packet header")?;
let comp_restart_flag = buffer[0] & 1 != 0;
let packet_length =
u16::from_le_bytes(buffer[1..3].try_into().internal_err(WRONG_OFFSET)?) as u64 + 1;
let bytestream_count =
u16::from_le_bytes(buffer[3..5].try_into().internal_err(WRONG_OFFSET)?);
if !packet_length.is_multiple_of(4) {
Error::invalid("Data packet length is not aligned and a multiple of four")?
}
if bytestream_count == 0 {
Error::invalid("A byte stream count of 0 is not allowed")?
}
Ok(Self {
comp_restart_flag,
packet_length,
bytestream_count,
})
}
pub fn write(&self, writer: &mut dyn Write) -> Result<()> {
let mut buffer = [0_u8; Self::SIZE];
buffer[0] = 1;
let flags = if self.comp_restart_flag { 1_u8 } else { 0_u8 };
buffer[1] = flags;
let length = (self.packet_length - 1) as u16;
buffer[2..4].copy_from_slice(&length.to_le_bytes());
buffer[4..6].copy_from_slice(&self.bytestream_count.to_le_bytes());
writer
.write_all(&buffer)
.write_err("Failed to write data packet header")
}
}
pub struct IgnoredPacketHeader {
pub packet_length: u64,
}
impl IgnoredPacketHeader {
pub const ID: u8 = 2;
pub fn read(reader: &mut dyn Read) -> Result<Self> {
let mut buffer = [0_u8; 3];
reader
.read_exact(&mut buffer)
.read_err("Failed to read ignore packet header")?;
if buffer[0] != 0 {
Error::invalid("The first byte inside ignored packets is reserved and must be zero")?
}
let packet_length =
u16::from_le_bytes(buffer[1..3].try_into().internal_err(WRONG_OFFSET)?) as u64 + 1;
if !packet_length.is_multiple_of(4) {
Error::invalid("Ignored packet length is not aligned and a multiple of four")?
}
Ok(Self { packet_length })
}
}