use crate::{
current_image, EfiChar, EfiString, File, FileAttributes, FileCreateError, Owned, Path,
PathNode, Status, DEBUG_WRITER,
};
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use core::cell::RefCell;
use core::fmt::Write;
use thiserror::Error;
#[macro_export]
macro_rules! debugln {
($($args:tt)*) => {
if let Some(w) = $crate::debug_writer() {
let mut w = w.borrow_mut();
w.write_fmt(::core::format_args!($($args)*)).unwrap();
w.write_char('\n').unwrap();
}
};
}
pub fn debug_writer() -> Option<&'static RefCell<Box<dyn Write>>> {
#[allow(static_mut_refs)]
unsafe {
DEBUG_WRITER.as_ref()
}
}
pub struct DebugFile {
file: Owned<File>,
}
impl DebugFile {
pub fn next_to_image(ext: &str) -> Result<Self, DebugFileError> {
let im = current_image().proto();
let fs = match im.device().file_system() {
Some(v) => v,
None => return Err(DebugFileError::UnsupportedImageLocation),
};
let root = match fs.open() {
Ok(v) => v,
Err(e) => return Err(DebugFileError::OpenRootFailed(im.file_path(), e)),
};
let mut path = match im.file_path().read() {
PathNode::MediaFilePath(v) => v.to_owned(),
};
path.push(EfiChar::FULL_STOP);
if path.push_str(ext).is_err() {
return Err(DebugFileError::UnsupportedExtension);
}
let file = match root.create(&path, FileAttributes::empty()) {
Ok(v) => v,
Err(e) => return Err(DebugFileError::CreateFileFailed(path, e)),
};
Ok(Self { file })
}
}
impl Write for DebugFile {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.file
.write(s.as_bytes())
.and_then(|_| self.file.flush())
.map_err(|_| core::fmt::Error)
}
}
#[derive(Debug, Error)]
pub enum DebugFileError {
#[error("the location of the current image is not supported")]
UnsupportedImageLocation,
#[error("cannot open the root directory of {}", .0.display())]
OpenRootFailed(&'static Path, #[source] Status),
#[error("file extension contains unsupported character")]
UnsupportedExtension,
#[error("cannot create {}", .0.display())]
CreateFileFailed(EfiString, #[source] FileCreateError),
}