generated from PlexSheep/baserepo
parent
23910f122e
commit
956e507e39
|
@ -3,17 +3,18 @@
|
||||||
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
//! This crate is part of [`pt`](../libpt/index.html), but can also be used as a standalone
|
||||||
//! module.
|
//! module.
|
||||||
//!
|
//!
|
||||||
//! This crate is currently empty.
|
//! Hedu is made for hexdumping data. `libpt` offers a cli application using this module.
|
||||||
|
|
||||||
use crate::display::humanbytes;
|
use crate::display::humanbytes;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use libpt_log::{debug, trace, warn, error};
|
use libpt_log::{debug, error, trace, warn};
|
||||||
use std::io::{prelude::*, Read, SeekFrom};
|
use std::io::{prelude::*, Read, SeekFrom};
|
||||||
|
|
||||||
const BYTES_PER_LINE: usize = 16;
|
const BYTES_PER_LINE: usize = 16;
|
||||||
const LINE_SEP_HORIZ: char = '─';
|
const LINE_SEP_HORIZ: char = '─';
|
||||||
const LINE_SEP_VERT: char = '│';
|
const LINE_SEP_VERT: char = '│';
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct HeduConfig {
|
pub struct HeduConfig {
|
||||||
pub chars: bool,
|
pub chars: bool,
|
||||||
pub skip: usize,
|
pub skip: usize,
|
||||||
|
@ -21,6 +22,10 @@ pub struct HeduConfig {
|
||||||
pub limit: usize,
|
pub limit: usize,
|
||||||
stop: bool,
|
stop: bool,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
data_idx: usize,
|
||||||
|
rd_counter: usize,
|
||||||
|
buf: [[u8; BYTES_PER_LINE]; 2],
|
||||||
|
alt_buf: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeduConfig {
|
impl HeduConfig {
|
||||||
|
@ -32,6 +37,10 @@ impl HeduConfig {
|
||||||
limit,
|
limit,
|
||||||
stop: false,
|
stop: false,
|
||||||
len: usize::MIN,
|
len: usize::MIN,
|
||||||
|
data_idx: usize::MIN,
|
||||||
|
rd_counter: usize::MIN,
|
||||||
|
buf: [[0; BYTES_PER_LINE]; 2],
|
||||||
|
alt_buf: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,14 +64,11 @@ impl DataSource for std::fs::File {
|
||||||
|
|
||||||
pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
||||||
// prepare some variables
|
// prepare some variables
|
||||||
let mut buf: [[u8; BYTES_PER_LINE]; 2] = [[0; BYTES_PER_LINE]; 2];
|
|
||||||
let mut alt_buf = 0usize;
|
|
||||||
let mut byte_counter: usize = 0;
|
|
||||||
|
|
||||||
// skip a given number of bytes
|
// skip a given number of bytes
|
||||||
if config.skip > 0 {
|
if config.skip > 0 {
|
||||||
data.skip(config.skip)?;
|
data.skip(config.skip)?;
|
||||||
byte_counter += config.skip;
|
config.data_idx += config.skip;
|
||||||
debug!("Skipped {}", humanbytes(config.skip));
|
debug!("Skipped {}", humanbytes(config.skip));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +85,14 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// data dump loop
|
// data dump loop
|
||||||
rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config)?;
|
rd_data(data, &mut config)?;
|
||||||
while config.len > 0 {
|
while config.len > 0 {
|
||||||
print!("{:08X} {LINE_SEP_VERT} ", byte_counter);
|
print!("{:08X} {LINE_SEP_VERT} ", config.data_idx);
|
||||||
for i in 0..config.len {
|
for i in 0..config.len {
|
||||||
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
if i as usize % BYTES_PER_LINE == BYTES_PER_LINE / 2 {
|
||||||
print!(" ");
|
print!(" ");
|
||||||
}
|
}
|
||||||
print!("{:02X} ", buf[alt_buf][i]);
|
print!("{:02X} ", config.buf[config.alt_buf][i]);
|
||||||
}
|
}
|
||||||
if config.len == BYTES_PER_LINE / 2 {
|
if config.len == BYTES_PER_LINE / 2 {
|
||||||
print!(" ")
|
print!(" ")
|
||||||
|
@ -100,7 +106,7 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
||||||
if config.chars {
|
if config.chars {
|
||||||
print!("{LINE_SEP_VERT} |");
|
print!("{LINE_SEP_VERT} |");
|
||||||
for i in 0..config.len {
|
for i in 0..config.len {
|
||||||
print!("{}", mask_chars(buf[alt_buf][i] as char));
|
print!("{}", mask_chars(config.buf[config.alt_buf][i] as char));
|
||||||
}
|
}
|
||||||
print!("|");
|
print!("|");
|
||||||
}
|
}
|
||||||
|
@ -112,23 +118,27 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// after line logic
|
// after line logic
|
||||||
rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config)?;
|
rd_data(data, &mut config)?;
|
||||||
alt_buf ^= 1; // toggle the alt buf
|
config.alt_buf ^= 1; // toggle the alt buf
|
||||||
if buf[0] == buf[1] && config.len == BYTES_PER_LINE && !config.show_identical {
|
if config.buf[0] == config.buf[1] && config.len == BYTES_PER_LINE && !config.show_identical
|
||||||
trace!(buf = format!("{:?}", buf), "found a duplicating line");
|
{
|
||||||
let start_line = byte_counter;
|
trace!(
|
||||||
while buf[0] == buf[1] && config.len == BYTES_PER_LINE {
|
buf = format!("{:?}", config.buf),
|
||||||
rd_data(data, &mut buf, &mut alt_buf, &mut byte_counter, &mut config)?;
|
"found a duplicating line"
|
||||||
byte_counter += BYTES_PER_LINE;
|
);
|
||||||
|
let start_line = config.data_idx;
|
||||||
|
while config.buf[0] == config.buf[1] && config.len == BYTES_PER_LINE {
|
||||||
|
rd_data(data, &mut config)?;
|
||||||
|
config.data_idx += BYTES_PER_LINE;
|
||||||
}
|
}
|
||||||
println!(
|
println!(
|
||||||
"^^^^^^^^ {LINE_SEP_VERT} (repeats {} lines)",
|
"^^^^^^^^ {LINE_SEP_VERT} (repeats {} lines)",
|
||||||
byte_counter - start_line
|
config.data_idx - start_line
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// switch to the second half of the buf, the original half is stored the old buffer
|
// switch to the second half of the buf, the original half is stored the old buffer
|
||||||
// We detect duplicate lines with this
|
// We detect duplicate lines with this
|
||||||
alt_buf ^= 1; // toggle the alt buf
|
config.alt_buf ^= 1; // toggle the alt buf
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -147,21 +157,22 @@ fn mask_chars(c: char) -> char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rd_data(
|
fn rd_data(data: &mut dyn DataSource, config: &mut HeduConfig) -> Result<()> {
|
||||||
data: &mut dyn DataSource,
|
config.rd_counter += config.len;
|
||||||
buf: &mut [[u8; BYTES_PER_LINE]; 2],
|
config.data_idx += config.len;
|
||||||
alt_buf: &mut usize,
|
match data.read(&mut config.buf[config.alt_buf]) {
|
||||||
byte_counter: &mut usize,
|
|
||||||
config: &mut HeduConfig,
|
|
||||||
) -> Result<()> {
|
|
||||||
*byte_counter += config.len;
|
|
||||||
match data.read(&mut buf[*alt_buf]) {
|
|
||||||
Ok(mut len) => {
|
Ok(mut len) => {
|
||||||
if config.limit != 0 && *byte_counter >= config.limit {
|
debug!(
|
||||||
|
conf = format!("{:?}", config),
|
||||||
|
dif = (config.rd_counter as i64 - config.skip as i64),
|
||||||
|
eval = (config.rd_counter as i64 - config.skip as i64) as usize >= config.limit,
|
||||||
|
"reached limit?"
|
||||||
|
);
|
||||||
|
if config.limit != 0
|
||||||
|
&& (config.rd_counter as i64 - config.skip as i64) as usize >= config.limit
|
||||||
|
{
|
||||||
trace!(
|
trace!(
|
||||||
byte_counter,
|
conf = format!("{:?}", config),
|
||||||
limit = config.limit,
|
|
||||||
len,
|
|
||||||
nlen = (config.limit % BYTES_PER_LINE),
|
nlen = (config.limit % BYTES_PER_LINE),
|
||||||
"byte counter is farther than limit"
|
"byte counter is farther than limit"
|
||||||
);
|
);
|
||||||
|
|
Reference in New Issue