use super::super::super::{Read, Seek, SeekFrom};
use super::{DescriptorTag, ExtentDescriptor, TagIdentifier};
use crate::error::{Error, Result};
#[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) -> Result<Self> {
reader.seek(SeekFrom::Start((location as u64) * 2048)).await?;
let mut buffer = [0u8; 512];
reader.read_exact(&mut buffer).await?;
DescriptorTag::validate_bytes(
&buffer,
TagIdentifier::AnchorVolumeDescriptorPointer,
location,
)?;
let avdp = (*bytemuck::from_bytes::<Self>(&buffer)).into_native();
avdp.validate(location)?;
Ok(avdp)
}
pub async fn find<R: Read + Seek>(reader: &mut R, total_sectors: Option<u64>) -> Result<Self> {
if let Ok(avdp) = Self::read(reader, Self::LOCATION_256).await {
return Ok(avdp);
}
if let Some(n) = total_sectors {
if n > 256
&& 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(Error::NoAnchor)
}
fn validate(&self, location: u32) -> Result<()> {
self.tag
.validate(TagIdentifier::AnchorVolumeDescriptorPointer, location)?;
Ok(())
}
pub(crate) fn into_native(mut self) -> Self {
self.tag = DescriptorTag::from_disk_bytes(bytemuck::bytes_of(&self.tag))
.expect("DescriptorTag has its fixed on-disk size");
self.main_vds_extent = self.main_vds_extent.into_native();
self.reserve_vds_extent = self.reserve_vds_extent.into_native();
self
}
}
}
#[cfg(test)]
mod tests {
use super::*;
static_assertions::const_assert_eq!(size_of::<AnchorVolumeDescriptorPointer>(), 512);
}