use core::{fmt, ptr};
use crate::start_info::reader::{MemMap, ModlistEntryReader, StartInfoReader};
use crate::start_info::{MemmapTableEntry, ModlistEntry};
impl<M: MemMap> fmt::Debug for StartInfoReader<'_, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StartInfoReader")
.field("paddr", &ptr::from_ref(self.start_info))
.field("version", &self.start_info.version)
.field("flags", &self.start_info.flags)
.field("modlist", &self.modlist_debug())
.field(
"cmdline_paddr",
&DebugU64AsPointer(self.start_info.cmdline_paddr),
)
.field("cmdline_vaddr", &self.cmdline_vaddr())
.field("cmdline", &self.cmdline())
.field("rsdp_paddr", &DebugU64AsPointer(self.start_info.rsdp_paddr))
.field("memmap", &MemmapTableDebug(self.memmap()))
.finish()
}
}
impl<M: MemMap> StartInfoReader<'_, M> {
#[must_use]
fn modlist_debug(&self) -> ModlistDebug<'_, &M> {
let modlist = self.raw_modlist();
let mem_map = &self.mem_map;
ModlistDebug { modlist, mem_map }
}
}
impl<M: MemMap> fmt::Debug for ModlistEntryReader<'_, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ModlistEntryReader")
.field("paddr", &DebugU64AsPointer(self.modlist_entry.paddr))
.field("vaddr", &self.vaddr())
.field("size", &DebugU64AsPointer(self.modlist_entry.size))
.field(
"cmdline_paddr",
&DebugU64AsPointer(self.modlist_entry.cmdline_paddr),
)
.field("cmdline_vaddr", &self.cmdline_vaddr())
.field("cmdline", &self.cmdline())
.finish()
}
}
struct MemmapTableEntryDebug<'a>(&'a MemmapTableEntry);
impl fmt::Debug for MemmapTableEntryDebug<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MemmapTableEntryDebug")
.field("addr", &DebugU64AsPointer(self.0.addr))
.field("size", &DebugU64AsPointer(self.0.size))
.field("type", &self.0.ty())
.finish()
}
}
struct MemmapTableDebug<'a>(&'a [MemmapTableEntry]);
impl fmt::Debug for MemmapTableDebug<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entries = self.0.iter().map(MemmapTableEntryDebug);
f.debug_list().entries(entries).finish()
}
}
struct ModlistDebug<'a, M> {
modlist: &'a [ModlistEntry],
mem_map: M,
}
impl<M: MemMap> fmt::Debug for ModlistDebug<'_, M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mem_map = &self.mem_map;
let entries = self
.modlist
.iter()
.map(move |modlist_entry| ModlistEntryReader {
modlist_entry,
mem_map,
});
f.debug_list().entries(entries).finish()
}
}
struct DebugU64AsPointer(u64);
impl fmt::Debug for DebugU64AsPointer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr_addr = self.0;
if f.alternate() {
let width = (u64::BITS / 4) as usize + 2;
return write!(f, "{ptr_addr:#0width$x}");
}
write!(f, "{ptr_addr:#x}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(target_pointer_width = "64")]
#[test]
fn debug_u64_as_pointer() {
for ptr_addr in 0..0x10 {
let ptr = ptr::without_provenance::<()>(ptr_addr);
let debug = DebugU64AsPointer(ptr_addr as u64);
assert_eq!(format!("{ptr:p}"), format!("{debug:?}"));
assert_eq!(format!("{ptr:#p}"), format!("{debug:#?}"));
}
}
}