utility for performing small hex dumps

This commit is contained in:
Numbers
2025-06-02 09:55:02 +02:00
parent d1318f8d3a
commit d4b8ef032b
4 changed files with 123 additions and 3 deletions

87
sub/xpat/src/hexdump.rs Normal file
View File

@@ -0,0 +1,87 @@
use crate::scannable::{ChunkIter, Scannable};
use core::ops::{Bound, Range, RangeBounds, RangeFull};
use core::fmt::{Display, Formatter};
const SEP: &str = " | ";
pub struct HexDump<'s, T: Scannable + ?Sized, R: RangeBounds<usize>>(pub &'s T, pub R);
pub fn hex<
's,
T: Scannable + ?Sized,
R: RangeBounds<usize>
>(
data: &'s T,
range:R
) -> HexDump<'s, T, R> {
HexDump(data, range)
}
impl<'s, T: Scannable> HexDump<'s, T, RangeFull> {
pub fn new(scannable: &'s T) -> Self {
Self(scannable, ..)
}
}
impl<'s, T: Scannable + ?Sized, R: RangeBounds<usize>> Display for HexDump<'s, T, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
// calculate the end and the start addresses
let (start, end) = {
let r = self.0.range();
let start = match self.1.start_bound() {
Bound::Included(i) => *i,
Bound::Excluded(i) => i.saturating_add(1),
Bound::Unbounded => 0,
}.max(r.start);
let end = match self.1.end_bound() {
Bound::Included(i) => *i,
Bound::Excluded(i) => i.saturating_sub(1),
Bound::Unbounded => usize::MAX,
}.min(r.end);
(start, end)
};
// the number of digits the address column should have
let digits = (end.ilog(16) as usize + 1).max(4);
for (mut addr, chunk) in ChunkIter::new(self.0, start) {
for chunk in chunk.chunks(16) {
//╶───╴Column╶────────────────────────────────╴
write!(f, "{:0digits$X}{SEP}", addr, digits = digits)?;
//╶───╴Bytes╶─────────────────────────────────╴
for (i, byte) in chunk.iter().enumerate() {
if i != 0 { write!(f, " ")?; }
write!(f, "{byte:02X}")?;
}
for i in (chunk.len()..16) {
match i {
0 => write!(f, " ")?,
_ => write!(f, " ")?,
}
}
//╶───╴Text╶──────────────────────────────────╴
write!(f, "{SEP}")?;
for &byte in chunk {
match byte {
0x20..0x7e => write!(f, "{}", char::from(byte))?,
_ => write!(f, ".")?,
}
}
writeln!(f)?;
addr += chunk.len()
}
}
let mut last_addr = 0usize;
let fchunk = self.0.chunk_at(0);
Ok(())
}
}