use super::{File, FileHandle, FileInfo, FromUefi, RegularFile};
use crate::Result;
use crate::data_types::Align;
use core::ffi::c_void;
#[cfg(feature = "alloc")]
use {crate::mem::make_boxed, alloc::boxed::Box};
#[repr(transparent)]
#[derive(Debug)]
pub struct Directory(RegularFile);
impl Directory {
#[must_use]
pub const unsafe fn new(handle: FileHandle) -> Self {
Self(unsafe { RegularFile::new(handle) })
}
pub fn read_entry<'buf>(
&mut self,
buffer: &'buf mut [u8],
) -> Result<Option<&'buf mut FileInfo>, Option<usize>> {
FileInfo::assert_aligned(buffer);
self.0.read_unchunked(buffer).map(|read_bytes| {
let last_directory_entry_read = read_bytes == 0;
if last_directory_entry_read {
None
} else {
unsafe { Some(FileInfo::from_uefi(buffer.as_mut_ptr().cast::<c_void>())) }
}
})
}
#[cfg(feature = "alloc")]
pub fn read_entry_boxed(&mut self) -> Result<Option<Box<FileInfo>>> {
let read_entry_res = self.read_entry(&mut []);
if read_entry_res == Ok(None) {
return Ok(None);
}
let fetch_data_fn = |buf| {
self.read_entry(buf)
.map(|maybe_info: Option<&mut FileInfo>| {
maybe_info.expect("Should have more entries")
})
};
let file_info = make_boxed::<FileInfo, _>(fetch_data_fn)?;
Ok(Some(file_info))
}
pub fn reset_entry_readout(&mut self) -> Result {
self.0.set_position(0)
}
}
impl File for Directory {
#[inline]
fn handle(&mut self) -> &mut FileHandle {
self.0.handle()
}
fn is_regular_file(&self) -> Result<bool> {
Ok(false)
}
fn is_directory(&self) -> Result<bool> {
Ok(true)
}
}