use super::super::super::{Read, Seek, SeekFrom};
use super::{DescriptorTag, ExtentDescriptor, TagIdentifier};
use crate::error::{UdfError, UdfResult};
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct AnchorVolumeDescriptorPointer {
pub tag: DescriptorTag,
pub main_vds_extent: ExtentDescriptor,
pub reserve_vds_extent: ExtentDescriptor,
reserved: [u8; 480],
}
unsafe impl bytemuck::Zeroable for AnchorVolumeDescriptorPointer {}
unsafe impl bytemuck::Pod for AnchorVolumeDescriptorPointer {}
io_transform! {
impl AnchorVolumeDescriptorPointer {
pub const LOCATION_256: u32 = 256;
pub async fn read<R: Read + Seek>(reader: &mut R, location: u32) -> UdfResult<Self> {
reader.seek(SeekFrom::Start((location as u64) * 2048)).await?;
let mut buffer = [0u8; 512];
reader.read_exact(&mut buffer).await?;
let avdp: Self = *bytemuck::from_bytes(&buffer);
avdp.validate(location)?;
Ok(avdp)
}
pub async fn find<R: Read + Seek>(reader: &mut R, total_sectors: Option<u64>) -> UdfResult<Self> {
if let Ok(avdp) = Self::read(reader, Self::LOCATION_256).await {
return Ok(avdp);
}
if let Some(n) = total_sectors {
if n > 256 {
if let Ok(avdp) = Self::read(reader, (n - 256) as u32).await {
return Ok(avdp);
}
}
if let Ok(avdp) = Self::read(reader, (n - 1) as u32).await {
return Ok(avdp);
}
}
Err(UdfError::NoAnchor)
}
fn validate(&self, location: u32) -> UdfResult<()> {
self.tag
.validate(TagIdentifier::AnchorVolumeDescriptorPointer, location)?;
if self.tag.descriptor_crc_length > 0 {
let data = bytemuck::bytes_of(self);
if !self.tag.verify_crc(&data[16..]) {
return Err(UdfError::CrcMismatch {
expected: self.tag.descriptor_crc,
computed: 0,
});
}
}
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
static_assertions::const_assert_eq!(size_of::<AnchorVolumeDescriptorPointer>(), 512);
}