#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct FileHandle(u16); impl FileHandle { pub const fn new(id: u16) -> Self { Self(id) } pub const fn raw(&self) -> u16 { self.0 } } pub const MAX_FILE_NAME: usize = 32; #[derive(Debug, Clone, Copy)] pub struct FileName { bytes: [u8; MAX_FILE_NAME], len: u8, } impl FileName { pub fn empty() -> Self { Self { bytes: [0; MAX_FILE_NAME], len: 0 } } pub fn from_bytes(src: &[u8]) -> Self { let mut name = Self::empty(); let len = src.len().min(MAX_FILE_NAME); name.bytes[..len].copy_from_slice(&src[..len]); name.len = len as u8; name } pub fn as_bytes(&self) -> &[u8] { &self.bytes[..self.len as usize] } pub fn len(&self) -> usize { self.len as usize } } impl PartialEq<[u8]> for FileName { fn eq(&self, other: &[u8]) -> bool { self.as_bytes() == other } } #[derive(Debug, Clone, Copy)] pub struct DirEntry { pub name: FileName, pub size: usize, pub is_dir: bool, } impl DirEntry { pub fn empty() -> Self { Self { name: FileName::empty(), size: 0, is_dir: false, } } } pub trait FileSystem { fn open(&mut self, path: &[u8]) -> Option; fn read(&mut self, handle: FileHandle, buf: &mut [u8]) -> Option; fn write(&mut self, handle: FileHandle, buf: &[u8]) -> Option; fn close(&mut self, handle: FileHandle); fn list_dir(&mut self, path: &[u8], entries: &mut [DirEntry]) -> Option; fn create(&mut self, path: &[u8]) -> Option; fn delete(&mut self, path: &[u8]) -> bool; fn file_size(&mut self, handle: FileHandle) -> Option; }