use crate::Error; use commonware_utils::{hex, StableBuf}; use std::{fs::File, os::unix::fs::FileExt, sync::Arc}; use tokio::task; #[derive(Clone)] pub struct Blob { partition: String, name: Vec, file: Arc, } impl Blob { pub fn new(partition: String, name: &[u8], file: File) -> Self { Self { partition, name: name.into(), file: Arc::new(file), } } } impl crate::Blob for Blob { async fn read_at( &self, buf: impl Into + Send, offset: u64, ) -> Result { let mut buf = buf.into(); let file = self.file.clone(); task::spawn_blocking(move || { file.read_exact_at(buf.as_mut(), offset)?; Ok(buf) }) .await .map_err(|_| Error::ReadFailed)? } async fn write_at(&self, buf: impl Into + Send, offset: u64) -> Result<(), Error> { let buf = buf.into(); let file = self.file.clone(); task::spawn_blocking(move || { file.write_all_at(buf.as_ref(), offset)?; Ok(()) }) .await .map_err(|_| Error::WriteFailed)? } async fn resize(&self, len: u64) -> Result<(), Error> { let file = self.file.clone(); task::spawn_blocking(move || file.set_len(len)) .await .map_err(|e| e.into()) .and_then(|r| r) .map_err(|e| Error::BlobResizeFailed(self.partition.clone(), hex(&self.name), e))?; Ok(()) } async fn sync(&self) -> Result<(), Error> { let file = self.file.clone(); task::spawn_blocking(move || file.sync_all()) .await .map_err(|e| e.into()) .and_then(|r| r) .map_err(|e| Error::BlobSyncFailed(self.partition.clone(), hex(&self.name), e))?; Ok(()) } }