use super::DG_BLOCK_SIZE;
use crate::{
Result,
blocks::common::{
BlockHeader, BlockParse, debug_assert_aligned, read_u8, read_u64, validate_block_id,
validate_block_length, validate_buffer_size,
},
};
use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone)]
pub struct DataGroupBlock {
pub header: BlockHeader,
pub next_dg_addr: u64,
pub first_cg_addr: u64,
pub data_block_addr: u64,
pub comment_addr: u64,
pub record_id_size: u8,
}
impl BlockParse<'_> for DataGroupBlock {
const ID: &'static str = "##DG";
fn from_bytes(bytes: &[u8]) -> Result<Self> {
let header = Self::parse_header(bytes)?;
validate_buffer_size(bytes, DG_BLOCK_SIZE)?;
Ok(Self {
header,
next_dg_addr: read_u64(bytes, 24),
first_cg_addr: read_u64(bytes, 32),
data_block_addr: read_u64(bytes, 40),
comment_addr: read_u64(bytes, 48),
record_id_size: read_u8(bytes, 56),
})
}
}
impl DataGroupBlock {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
validate_block_id(&self.header, "##DG")?;
validate_block_length(&self.header, DG_BLOCK_SIZE as u64)?;
let mut buffer = Vec::with_capacity(DG_BLOCK_SIZE);
buffer.extend_from_slice(&self.header.to_bytes()?);
buffer.extend_from_slice(&self.next_dg_addr.to_le_bytes());
buffer.extend_from_slice(&self.first_cg_addr.to_le_bytes());
buffer.extend_from_slice(&self.data_block_addr.to_le_bytes());
buffer.extend_from_slice(&self.comment_addr.to_le_bytes());
buffer.push(self.record_id_size);
buffer.extend_from_slice(&[0u8; 7]);
debug_assert_aligned(buffer.len());
Ok(buffer)
}
}
impl Default for DataGroupBlock {
fn default() -> Self {
Self {
header: BlockHeader {
id: String::from("##DG"),
reserved: 0,
length: DG_BLOCK_SIZE as u64,
link_count: 4,
},
next_dg_addr: 0,
first_cg_addr: 0,
data_block_addr: 0,
comment_addr: 0,
record_id_size: 0,
}
}
}