read from multiple sources
cargo devel CI / cargo CI (push) Successful in 2m6s Details

implements #60
This commit is contained in:
Christoph J. Scherr 2024-01-17 23:02:41 +01:00
parent fd0d1e3c22
commit 2bc75970a4
Signed by: PlexSheep
GPG Key ID: 7CDD0B14851A08EF
2 changed files with 43 additions and 35 deletions

View File

@ -10,10 +10,10 @@ use anyhow::{bail, Result};
use libpt_log::{debug, error, trace, warn}; 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; pub const BYTES_PER_LINE: usize = 16;
const LINE_SEP_HORIZ: char = '─'; pub const LINE_SEP_HORIZ: char = '─';
const LINE_SEP_VERT: char = '│'; pub const LINE_SEP_VERT: char = '│';
const CHAR_BORDER: &'static str = "|"; pub const CHAR_BORDER: &'static str = "|";
#[derive(Debug)] #[derive(Debug)]
pub struct HeduConfig { pub struct HeduConfig {
@ -70,14 +70,12 @@ impl DataSource for std::fs::File {
} }
} }
pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> { pub fn dump(data: &mut dyn DataSource, config: &mut HeduConfig) -> Result<()> {
// prepare some variables
// 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)?;
config.data_idx += config.skip; config.data_idx += config.skip;
adjust_data_idx(&mut config); adjust_data_idx(config);
debug!("Skipped {}", humanbytes(config.skip)); debug!("Skipped {}", humanbytes(config.skip));
} }
@ -95,7 +93,7 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
config.display(); config.display();
// data dump loop // data dump loop
rd_data(data, &mut config)?; rd_data(data, config)?;
while config.len > 0 { while config.len > 0 {
config.display_buf += &format!("{:08X} {LINE_SEP_VERT} ", config.data_idx); config.display_buf += &format!("{:08X} {LINE_SEP_VERT} ", config.data_idx);
for i in 0..config.len { for i in 0..config.len {
@ -129,7 +127,7 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
} }
// after line logic // after line logic
rd_data(data, &mut config)?; rd_data(data, config)?;
config.alt_buf ^= 1; // toggle the alt buf config.alt_buf ^= 1; // toggle the alt buf
if config.buf[0] == config.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
{ {
@ -139,7 +137,7 @@ pub fn dump(data: &mut dyn DataSource, mut config: HeduConfig) -> Result<()> {
); );
let start_line = config.data_idx; let start_line = config.data_idx;
while config.buf[0] == config.buf[1] && config.len == BYTES_PER_LINE { while config.buf[0] == config.buf[1] && config.len == BYTES_PER_LINE {
rd_data(data, &mut config)?; rd_data(data, config)?;
} }
config.alt_buf ^= 1; // toggle the alt buf (now that we have a not same line) config.alt_buf ^= 1; // toggle the alt buf (now that we have a not same line)
config.display_buf += &format!( config.display_buf += &format!(

View File

@ -18,7 +18,7 @@ use libpt::{bintols::hedu::*, log::*};
use clap::Parser; use clap::Parser;
use clap_verbosity_flag::{InfoLevel, Verbosity}; use clap_verbosity_flag::{InfoLevel, Verbosity};
use std::{fs::File, io::IsTerminal}; use std::{fs::File, io::IsTerminal, path::PathBuf};
//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// //// TYPES /////////////////////////////////////////////////////////////////////////////////////////
@ -87,7 +87,7 @@ pub struct Cli {
/// ///
/// If left empty or set as "-", the program will read from stdin. /// If left empty or set as "-", the program will read from stdin.
// TODO: take many sources #60 // TODO: take many sources #60
pub data_source: Option<String>, pub data_source: Vec<String>,
} }
//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// //// IMPLEMENTATION ////////////////////////////////////////////////////////////////////////////////
@ -96,38 +96,48 @@ pub struct Cli {
//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// //// PRIVATE FUNCTIONS /////////////////////////////////////////////////////////////////////////////
fn main() { fn main() {
let cli = cli_parse(); let mut cli = cli_parse();
let mut source: Box<dyn DataSource>; let mut sources: Vec<Box<dyn DataSource>> = Vec::new();
if cli.data_source.is_some() && cli.data_source.clone().is_some_and(|val| val != "-") { if cli.data_source.len() > 0 && cli.data_source[0] != "-" {
let data_source = cli.data_source.unwrap(); for data_source in &cli.data_source {
trace!("Trying to open '{}'", data_source); let data_source: PathBuf = PathBuf::from(data_source);
source = match File::open(&data_source) { if !data_source.is_file() {
Ok(file) => Box::new(file), debug!("Not a regular file'{:?}'", data_source);
// std::process::exit(1);
continue
}
trace!("Trying to open '{:?}'", data_source);
match File::open(&data_source) {
Ok(file) => sources.push(Box::new(file)),
Err(err) => { Err(err) => {
error!("Could not open file '{}': {err}", data_source); error!("Could not open '{:?}': {err}", data_source);
std::process::exit(1); std::process::exit(1);
} }
}; };
}
} else { } else {
trace!("Trying to open stdout"); trace!("Trying to open stdin");
let stdin = std::io::stdin(); let stdin = std::io::stdin();
if stdin.is_terminal() { if stdin.is_terminal() {
warn!("Refusing to dump from interactive terminal"); warn!("Refusing to dump from interactive terminal");
std::process::exit(2) std::process::exit(2)
} }
source = Box::new(stdin); // just for the little header
cli.data_source = Vec::new();
cli.data_source.push(format!("stdin"));
sources.push(Box::new(stdin));
} }
for (i, source) in sources.iter_mut().enumerate() {
match dump( println!("{:=^59}", format!(" {} ", cli.data_source[i]));
&mut *source, let mut config = HeduConfig::new(cli.chars, cli.skip, cli.show_identical, cli.limit);
HeduConfig::new(cli.chars, cli.skip, cli.show_identical, cli.limit), match dump(&mut **source, &mut config) {
) {
Ok(_) => (), Ok(_) => (),
Err(err) => { Err(err) => {
error!("Could not dump data of file: {err}"); error!("Could not dump data of file: {err}");
std::process::exit(3); std::process::exit(3);
} }
} }
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
fn cli_parse() -> Cli { fn cli_parse() -> Cli {