Skip to main content

fs_core/
callback_device.rs

1//! `BlockDevice` backed by host-process-owned callbacks. Used when the
2//! caller already holds the underlying resource (an FSKit
3//! `FSBlockDeviceResource`, a Go file handle, a C-side fd) and the Rust
4//! side just needs a trait surface to feed into a driver.
5
6use crate::block::{BlockDevice, BlockRead};
7use crate::error::{Error, Result};
8
9pub type ReadCb = Box<dyn Fn(u64, &mut [u8]) -> std::io::Result<()> + Send + Sync>;
10pub type WriteCb = Box<dyn Fn(u64, &[u8]) -> std::io::Result<()> + Send + Sync>;
11pub type FlushCb = Box<dyn Fn() -> std::io::Result<()> + Send + Sync>;
12
13pub struct CallbackDevice {
14    pub size: u64,
15    pub read: ReadCb,
16    pub write: Option<WriteCb>,
17    pub flush: Option<FlushCb>,
18}
19
20impl BlockRead for CallbackDevice {
21    fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
22        (self.read)(offset, buf)?;
23        Ok(())
24    }
25    fn size_bytes(&self) -> u64 {
26        self.size
27    }
28}
29
30impl BlockDevice for CallbackDevice {
31    fn write_at(&self, offset: u64, buf: &[u8]) -> Result<()> {
32        match &self.write {
33            Some(f) => {
34                f(offset, buf)?;
35                Ok(())
36            }
37            None => Err(Error::ReadOnly),
38        }
39    }
40    fn flush(&self) -> Result<()> {
41        match &self.flush {
42            Some(f) => {
43                f()?;
44                Ok(())
45            }
46            None => Ok(()),
47        }
48    }
49    fn is_writable(&self) -> bool {
50        self.write.is_some()
51    }
52}