io_transform! {
use super::super::{Read, Write, Seek, SeekFrom};
use crate::gpt::{GptHeader, GptHeaderRaw};
#[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::PartitionError::Io)?;
let raw: GptHeaderRaw = bytemuck::cast(buf);
let header = Self::from_raw(&raw);
if !header.has_valid_signature() {
return Err(crate::error::PartitionError::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 * block_size as u64))
.await
.map_err(|_| crate::error::PartitionError::Io)?;
Self::read_from(reader).await
}
}
#[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::PartitionError::Io)
}
async fn write_to_lba<W: Write + Seek>(
&self,
writer: &mut W,
lba: u64,
block_size: u32,
) -> crate::error::Result<()> {
writer
.seek(SeekFrom::Start(lba * block_size as u64))
.await
.map_err(|_| crate::error::PartitionError::Io)?;
let raw = self.to_raw();
writer
.write_all(bytemuck::bytes_of(&raw))
.await
.map_err(|_| crate::error::PartitionError::Io)?;
let padding_size = block_size as usize - GptHeaderRaw::SIZE;
if padding_size > 0 {
let padding = [0u8; 512]; writer
.write_all(&padding[..padding_size.min(512)])
.await
.map_err(|_| crate::error::PartitionError::Io)?;
}
Ok(())
}
}
}