io_transform! {
#[cfg(feature = "read")]
use super::super::Read;
#[cfg(any(feature = "read", feature = "write"))]
use super::super::{Seek, SeekFrom};
#[cfg(feature = "write")]
use super::super::Write;
#[cfg(any(feature = "read", feature = "write"))]
use crate::gpt::{GptHeader, GptHeaderRaw};
#[cfg(feature = "read")]
#[cfg_attr(docsrs, doc(cfg(feature = "read")))]
pub trait GptHeaderReadExt: Sized {
async fn read_from<R: Read>(reader: &mut R) -> crate::error::Result<Self>;
async fn read_from_lba<R: Read + Seek>(
reader: &mut R,
lba: u64,
block_size: u32,
) -> crate::error::Result<Self>;
}
#[cfg(feature = "read")]
impl GptHeaderReadExt for GptHeader {
async fn read_from<R: Read>(reader: &mut R) -> crate::error::Result<Self> {
let mut buf = [0u8; GptHeaderRaw::SIZE];
reader
.read_exact(&mut buf)
.await
.map_err(crate::error::Error::from)?;
let raw: GptHeaderRaw = bytemuck::cast(buf);
let header = Self::from_raw(&raw);
if !header.has_valid_signature() {
return Err(crate::error::Error::InvalidGptSignature {
found: header.signature,
});
}
Ok(header)
}
async fn read_from_lba<R: Read + Seek>(
reader: &mut R,
lba: u64,
block_size: u32,
) -> crate::error::Result<Self> {
reader
.seek(SeekFrom::Start(lba.saturating_mul(u64::from(block_size))))
.await
.map_err(crate::error::Error::from)?;
Self::read_from(reader).await
}
}
#[cfg(feature = "write")]
#[cfg_attr(docsrs, doc(cfg(feature = "write")))]
pub trait GptHeaderWriteExt {
async fn write_to<W: Write>(&self, writer: &mut W) -> crate::error::Result<()>;
async fn write_to_lba<W: Write + Seek>(
&self,
writer: &mut W,
lba: u64,
block_size: u32,
) -> crate::error::Result<()>;
}
#[cfg(feature = "write")]
impl GptHeaderWriteExt for GptHeader {
async fn write_to<W: Write>(&self, writer: &mut W) -> crate::error::Result<()> {
let raw = self.to_raw();
writer
.write_all(bytemuck::bytes_of(&raw))
.await
.map_err(crate::error::Error::from)
}
async fn write_to_lba<W: Write + Seek>(
&self,
writer: &mut W,
lba: u64,
block_size: u32,
) -> crate::error::Result<()> {
if block_size < GptHeaderRaw::SIZE as u32 {
return Err(crate::error::Error::InvalidBlockSize {
size: block_size,
minimum: GptHeaderRaw::SIZE as u32,
});
}
let Some(offset) = lba.checked_mul(u64::from(block_size)) else {
return Err(crate::error::Error::lba_offset_overflow());
};
writer
.seek(SeekFrom::Start(offset))
.await
.map_err(crate::error::Error::from)?;
let raw = self.to_raw();
writer
.write_all(bytemuck::bytes_of(&raw))
.await
.map_err(crate::error::Error::from)?;
let mut padding_size = block_size as usize - GptHeaderRaw::SIZE;
let padding = [0u8; 512];
while padding_size > 0 {
let chunk = padding_size.min(padding.len());
writer
.write_all(&padding[..chunk])
.await
.map_err(crate::error::Error::from)?;
padding_size -= chunk;
}
Ok(())
}
}
}