use super::VfsResult;
use async_trait::async_trait;
use std::os::unix::io::RawFd;
use std::sync::Arc;
/// File operations trait for VFS implementations.
///
/// This trait provides a VFS-level abstraction over file operations,
/// allowing different implementations (passthrough, bind mount, SQLite VFS, etc.)
/// to handle file I/O differently.
#[async_trait]
pub trait FileOps: Send + Sync {
/// Read from the file at the current offset
async fn read(&self, buf: &mut [u8]) -> VfsResult<usize>;
/// Write to the file at the current offset
async fn write(&self, buf: &[u8]) -> VfsResult<usize>;
/// Seek to a position in the file
async fn seek(&self, offset: i64, whence: i32) -> VfsResult<i64>;
/// Get file status
async fn fstat(&self) -> VfsResult<libc::stat>;
/// Sync file data to storage
async fn fsync(&self) -> VfsResult<()>;
/// Sync file data (but not metadata) to storage
async fn fdatasync(&self) -> VfsResult<()>;
/// Perform file control operations
fn fcntl(&self, cmd: i32, arg: i64) -> VfsResult<i64>;
/// Perform device-specific I/O operations
fn ioctl(&self, request: u64, arg: u64) -> VfsResult<i64>;
/// Get the underlying kernel file descriptor (if any)
///
/// Returns None for virtualized files that don't have a real kernel FD.
/// Some operations may need to fall back to the kernel FD.
fn as_raw_fd(&self) -> Option<RawFd>;
/// Close the file
async fn close(&self) -> VfsResult<()>;
/// Get flags associated with this file descriptor
fn get_flags(&self) -> i32;
/// Set flags associated with this file descriptor
fn set_flags(&self, flags: i32) -> VfsResult<()>;
/// Read directory entries (for directories only)
///
/// This is used to implement getdents64. Returns a vector of (inode, name, type) tuples.
/// Returns an error if this is not a directory.
async fn getdents(&self) -> VfsResult<Vec<(u64, String, u8)>> {
Err(super::VfsError::Other("Not a directory".to_string()))
}
}
/// A boxed FileOps trait object for dynamic dispatch
pub type BoxedFileOps = Arc<dyn FileOps>;