use alloc::{boxed::Box, string::String}; use core::{any::Any, mem::MaybeUninit}; use yggdrasil_abi::{ error::Error, io::{DirectoryEntry, OpenOptions}, }; use crate::vfs::{ file::{DirectoryOpenPosition, InstanceData}, Filename, }; use super::{CreateInfo, Metadata, NodeRef}; /// Common interface shared by all filesystem nodes pub trait CommonImpl: Send + Sync { /// Returns `&self` as a reference to `dyn Any` fn as_any(&self) -> &dyn Any { unimplemented!(); } /// Fetches the metadata of the file from underlying storage fn metadata(&self, node: &NodeRef) -> Result { let _ = node; unreachable!("Kernel bug: .metadata() not implemented and no IN_MEMORY_PROPS set") } fn set_metadata(&self, node: &NodeRef, metadata: &Metadata) -> Result<(), Error> { let _ = node; let _ = metadata; unreachable!("Kernel bug: .set_metadata() not implemented and no IN_MEMORY_PROPS set") } /// Fetches the size of the file from underlying storage fn size(&self, node: &NodeRef) -> Result { let _ = node; Err(Error::NotImplemented) } } /// Regular file interface pub trait RegularImpl: CommonImpl { /// Opens the file for reading/writing and returns a `(start position, instance data)` tuple fn open( &self, node: &NodeRef, opts: OpenOptions, ) -> Result<(u64, Option), Error> { let _ = node; let _ = opts; Err(Error::NotImplemented) } /// Closes a file fn close(&self, node: &NodeRef, instance: Option<&InstanceData>) -> Result<(), Error> { let _ = node; let _ = instance; Ok(()) } /// Reads data from the file into given buffer fn read( &self, node: &NodeRef, instance: Option<&InstanceData>, pos: u64, buf: &mut [u8], ) -> Result { let _ = node; let _ = instance; let _ = pos; let _ = buf; Err(Error::NotImplemented) } /// Writes data to the file from given buffer fn write( &self, node: &NodeRef, instance: Option<&InstanceData>, pos: u64, buf: &[u8], ) -> Result { let _ = node; let _ = instance; let _ = pos; let _ = buf; Err(Error::NotImplemented) } /// Resizes the file to requested size fn truncate(&self, node: &NodeRef, new_size: u64) -> Result<(), Error> { let _ = node; let _ = new_size; Err(Error::NotImplemented) } } /// Directory implementation pub trait DirectoryImpl: CommonImpl { /// Opens a directory for reading its entries. Returns [DirectoryOpenPosition] to specify the /// starting position. fn open(&self, node: &NodeRef) -> Result { let _ = node; Err(Error::NotImplemented) } /// Fetches entries from a directory into given buffer fn read_entries( &self, node: &NodeRef, pos: u64, entries: &mut [MaybeUninit], ) -> Result<(usize, u64), Error> { let _ = node; let _ = pos; let _ = entries; Err(Error::NotImplemented) } /// Creates a child node, but does not associate it with the directory yet fn create_node(&self, parent: &NodeRef, info: &CreateInfo) -> Result { let _ = parent; let _ = info; Err(Error::ReadOnly) } /// Associates the given node with the directory, creating an entry for it inside fn attach_node(&self, parent: &NodeRef, child: &NodeRef, name: &Filename) -> Result<(), Error> { let _ = parent; let _ = child; let _ = name; Err(Error::NotImplemented) } /// Removes an entry of the directory with given name fn unlink_node(&self, parent: &NodeRef, child: &NodeRef, name: &Filename) -> Result<(), Error> { let _ = parent; let _ = child; let _ = name; Err(Error::NotImplemented) } /// Fetches the child of the directory with given name fn lookup(&self, node: &NodeRef, name: &Filename) -> Result { let _ = node; let _ = name; Err(Error::NotImplemented) } fn contains(&self, node: &NodeRef, name: &Filename) -> bool { match self.lookup(node, name) { Ok(_) => true, Err(_) => false, } } /// Returns the "length" of the directory in entries fn len(&self, node: &NodeRef) -> Result { let _ = node; Err(Error::NotImplemented) } } /// Symbolic link interface pub trait SymlinkImpl: CommonImpl { // /// Returns the target node (if such is available directly) of the link // fn target(&self, node: &NodeRef) -> Result { // Err(Error::NotImplemented) // } /// Fetches the contents of the symlink into a [String] fn read_to_string(&self) -> Result { let mut data = Box::new([0; 512]); let len = self.read_link(data.as_mut())?; if len == data.len() { return Err(Error::InvalidFile); } let str = core::str::from_utf8(&data[..len]).map_err(|_| Error::InvalidFile)?; Ok(String::from(str)) } /// Fetches the contents of the symlink into a buffer fn read_link(&self, buf: &mut [u8]) -> Result { let _ = buf; Err(Error::NotImplemented) } } /// Hard link interface pub trait HardlinkImpl: Sync + Send { fn target(&self, node: &NodeRef) -> Result { let _ = node; Err(Error::NotImplemented) } }