pub mod error { use thiserror::Error; #[derive(Debug, Error)] pub enum Error { #[error("read failed")] ReadFailed, #[error("invalid magic signature")] InvalidMagic, #[error("invalid offset")] InvalidOffset, #[error("Expected an internal node")] ExpectedInternalNode, #[error("Expected a leaf node")] ExpectedLeafNode, #[error("Failed to read with logical offset")] BadLogicalAddress, #[error("Default subvolume root could not be found")] NoDefaultSubvolRoot, #[error("Default subvolume root fs tree could not be found")] NoDefaultSubvolFsRoot, #[error("INode could not be found in FsTree")] INodeNotFound, #[error("attempted to access {index}th item out of bounds {range:?}")] OutOfBounds { range: core::ops::Range, index: usize, }, #[error("Invalid checksum: expected {expected:#?} but got {actual:#?}")] InvalidChecksum { expected: [u8; 32], actual: [u8; 32], }, #[error("{0}")] ScrollError(scroll::Error), } impl From for Error { fn from(value: scroll::Error) -> Self { Self::ScrollError(value) } } pub type Result = core::result::Result; } pub trait Read { fn read(&self, dst: &mut [u8], address: u64) -> error::Result<()>; fn alignment(&self) -> usize { 1 } } impl Read for &[u8] { fn read(&self, dst: &mut [u8], address: u64) -> error::Result<()> { let src = self .get(address as usize..address as usize + dst.len()) .ok_or(error::Error::ReadFailed)?; dst.copy_from_slice(src); Ok(()) } } #[cfg(all(any(feature = "std", test), unix))] impl Read for std::fs::File { fn read(&self, dst: &mut [u8], address: u64) -> error::Result<()> { use std::os::unix::prelude::FileExt; self.read_at(dst, address) .map_err(|_| error::Error::ReadFailed)?; Ok(()) } } pub mod file; pub mod tree; pub mod volume;