summaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorJulian Sitkevich <sitkevij@gmail.com>2020-04-20 22:15:40 -0700
committerGitHub <noreply@github.com>2020-04-20 22:15:40 -0700
commit8d531a39df1b63f4c700273b8d1a4322393f121d (patch)
treedcbccca4d2e8faec3b105e347bf5cd6bac16f1cd /src/lib.rs
parent66f0a6dab366c5d8f143fcaf3dcd8ec9edde0479 (diff)
parentdcfebef40ffc79192f2fa93dc71c54a4b3e2a083 (diff)
Merge pull request #18 from sitkevij/feature/stdin-supportv0.3.0
Feature/stdin support
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs239
1 files changed, 159 insertions, 80 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c3798c6..3fb1e71 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
#![deny(
+ dead_code,
missing_docs,
missing_debug_implementations,
missing_copy_implementations,
@@ -9,18 +10,41 @@
unused_import_braces,
unused_qualifications
)]
-// #![allow(dead_code)]
//! general hex lib
extern crate ansi_term;
extern crate clap;
use clap::ArgMatches;
+use std::env;
+use std::error::Error;
use std::f64;
use std::fs;
-use std::fs::File;
use std::io::BufReader;
-use std::io::Read;
+use std::io::{self, BufRead, Read};
+
+/// arg cols
+pub const ARG_COL: &str = "cols";
+/// arg len
+pub const ARG_LEN: &str = "len";
+/// arg format
+pub const ARG_FMT: &str = "format";
+/// arg INPUTFILE
+pub const ARG_INP: &str = "INPUTFILE";
+/// arg color
+pub const ARG_CLR: &str = "color";
+/// arg array
+pub const ARG_ARR: &str = "array";
+/// arg func
+pub const ARG_FNC: &str = "func";
+/// arg places
+pub const ARG_PLC: &str = "places";
+
+const ARGS: [&str; 8] = [
+ ARG_COL, ARG_LEN, ARG_FMT, ARG_INP, ARG_CLR, ARG_ARR, ARG_FNC, ARG_PLC,
+];
+
+const DBG: u8 = 0x0;
/// nothing ⇒ Display
/// ? ⇒ Debug
@@ -180,29 +204,9 @@ pub fn print_byte(b: u8, format: Format, colorize: bool) {
}
}
-/// Function wave out.
-/// # Arguments
-///
-/// * `len` - Wave length.
-/// * `places` - Number of decimal places for function wave floats.
-pub fn func_out(len: u64, places: usize) {
- for y in 0..len {
- let y_float: f64 = y as f64;
- let len_float: f64 = len as f64;
- let x: f64 = (((y_float / len_float) * f64::consts::PI) / 2.0).sin();
- let formatted_number = format!("{:.*}", places, x);
- print!("{}", formatted_number);
- print!(",");
- if (y % 10) == 9 {
- println!();
- }
- }
- println!();
-}
-
/// In most hex editor applications, the data of the computer file is
-/// represented as hexadecimal values grouped in 4 groups of 4 bytes
-/// (or two groups of 8 bytes), followed by one group of 16 printable ASCII
+/// represented as hexadecimal values grouped in 4 groups of 4 bytes (or
+/// two groups of 8 bytes), followed by one group of 16 printable ASCII
/// characters which correspond to each pair of hex values (each byte).
/// Non-printable ASCII characters (e.g., Bell) and characters that would take
/// more than one character space (e.g., tab) are typically represented by a
@@ -211,30 +215,41 @@ pub fn func_out(len: u64, places: usize) {
/// # Arguments
///
/// * `matches` - Argument matches from command line.
-pub fn run(matches: ArgMatches) -> Result<(), Box<::std::error::Error>> {
+pub fn run(matches: ArgMatches) -> Result<(), Box<dyn Error>> {
let mut column_width: u64 = 10;
+ let mut truncate_len: u64 = 0x0;
if let Some(len) = matches.value_of("func") {
let mut p: usize = 4;
if let Some(places) = matches.value_of("places") {
p = places.parse::<usize>().unwrap();
}
- func_out(len.parse::<u64>().unwrap(), p);
- } else if let Some(file) = matches.value_of("INPUTFILE") {
- let f = File::open(file).unwrap();
- let mut buf_len = fs::metadata(file)?.len();
- let mut buf = BufReader::new(f);
+ output_function(len.parse::<u64>().unwrap(), p);
+ } else {
+ // cases:
+ // $ cat Cargo.toml | target/debug/hx
+ // $ cat Cargo.toml | target/debug/hx -a r
+ // $ target/debug/hx Cargo.toml
+ // $ target/debug/hx Cargo.toml -a r
+ let is_stdin = is_stdin(matches.clone());
+ let mut buf: Box<dyn BufRead> = if is_stdin.unwrap() {
+ Box::new(BufReader::new(io::stdin()))
+ } else {
+ Box::new(BufReader::new(
+ fs::File::open(matches.value_of(ARG_INP).unwrap()).unwrap(),
+ ))
+ };
let mut format_out = Format::LowerHex;
let mut colorize = true;
- if let Some(columns) = matches.value_of("cols") {
+ if let Some(columns) = matches.value_of(ARG_COL) {
column_width = columns.parse::<u64>().unwrap(); //turbofish
}
- if let Some(length) = matches.value_of("len") {
- buf_len = length.parse::<u64>().unwrap();
+ if let Some(length) = matches.value_of(ARG_LEN) {
+ truncate_len = length.parse::<u64>().unwrap();
}
- if let Some(format) = matches.value_of("format") {
+ if let Some(format) = matches.value_of(ARG_FMT) {
// o, x, X, p, b, e, E
match format {
"o" => format_out = Format::Octal,
@@ -248,7 +263,7 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<::std::error::Error>> {
}
}
- if let Some(color) = matches.value_of("color") {
+ if let Some(color) = matches.value_of(ARG_CLR) {
let color_v = color.parse::<u8>().unwrap();
if color_v == 1 {
colorize = true;
@@ -257,54 +272,21 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<::std::error::Error>> {
}
}
- match matches.occurrences_of("v") {
- 0 => print!(""),
- 1 => println!("verbose 1"),
- 2 => println!("verbose 2"),
- 3 | _ => println!("verbose max"),
- }
-
// array output mode is mutually exclusive
- if let Some(array) = matches.value_of("array") {
- let mut array_format = array;
- let mut page = buf_to_array(&mut buf, buf_len, column_width).unwrap();
- match array_format {
- "r" => println!("let ARRAY: [u8; {}] = [", page.bytes),
- "c" => println!("unsigned char ARRAY[{}] = {{", page.bytes),
- "g" => println!("a := [{}]byte{{", page.bytes),
- _ => println!("unknown array format"),
- }
-
- let mut i: u64 = 0x0;
- for line in page.body.iter() {
- print!(" ");
- for hex in line.hex_body.iter() {
- i += 1;
- if i == buf_len && array_format != "g" {
- print!("{}", hex_lower_hex(*hex));
- } else {
- print!("{}, ", hex_lower_hex(*hex));
- }
- }
- println!();
- }
- match array_format {
- "r" => println!("];"),
- "c" => println!("}};"),
- "g" => println!("}}"),
- _ => println!("unknown array format"),
- }
+ if let Some(array) = matches.value_of(ARG_ARR) {
+ output_array(array, buf, truncate_len, column_width);
} else {
// Transforms this Read instance to an Iterator over its bytes.
// The returned type implements Iterator where the Item is
// Result<u8, R::Err>. The yielded item is Ok if a byte was
- // successfully read and Err otherwise for I/O errors. EOF is mapped
- // to returning None from this iterator.
+ // successfully read and Err otherwise for I/O errors. EOF is
+ // mapped to returning None from this iterator.
// (https://doc.rust-lang.org/1.16.0/std/io/trait.Read.html#method.bytes)
let mut ascii_line: Line = Line::new();
let mut offset_counter: u64 = 0x0;
let mut byte_column: u64 = 0x0;
- let mut page = buf_to_array(&mut buf, buf_len, column_width).unwrap();
+ let page = buf_to_array(&mut buf, truncate_len, column_width).unwrap();
+
for line in page.body.iter() {
print_offset(offset_counter);
@@ -338,18 +320,114 @@ pub fn run(matches: ArgMatches) -> Result<(), Box<::std::error::Error>> {
Ok(())
}
+/// Detect stdin, file path and/or parameters.
+/// # Arguments
+///
+/// * `matches` - argument matches.
+pub fn is_stdin(matches: ArgMatches) -> Result<bool, Box<dyn Error>> {
+ let mut is_stdin = false;
+ if DBG > 0 {
+ dbg!(env::args().len(), matches.args.len());
+ dbg!(env::args().nth(0).unwrap());
+ }
+ if let Some(nth1) = env::args().nth(1) {
+ if DBG > 0 {
+ dbg!(nth1);
+ }
+ for arg in ARGS.iter() {
+ if let Some(index) = matches.index_of(arg) {
+ if let 2 = index {
+ is_stdin = true;
+ }
+ }
+ }
+ } else if matches.args.is_empty() {
+ is_stdin = true;
+ } else if let Some(file) = matches.value_of(ARG_INP) {
+ if DBG > 0 {
+ dbg!(file);
+ }
+ is_stdin = false;
+ }
+ if DBG > 0 {
+ dbg!(is_stdin);
+ }
+ Ok(is_stdin)
+}
+
+/// Output source code array format.
+/// # Arguments
+///
+/// * `array_format` - array format, rust (r), C (c), golang (g).
+/// * `buf` - BufRead.
+/// * `truncate_len` - truncate to length.
+/// * `column_width` - column width.
+pub fn output_array(
+ array_format: &str,
+ mut buf: Box<dyn BufRead>,
+ truncate_len: u64,
+ column_width: u64,
+) {
+ let page = buf_to_array(&mut buf, truncate_len, column_width).unwrap();
+ match array_format {
+ "r" => println!("let ARRAY: [u8; {}] = [", page.bytes),
+ "c" => println!("unsigned char ARRAY[{}] = {{", page.bytes),
+ "g" => println!("a := [{}]byte{{", page.bytes),
+ _ => println!("unknown array format"),
+ }
+ let mut i: u64 = 0x0;
+ for line in page.body.iter() {
+ print!(" ");
+ for hex in line.hex_body.iter() {
+ i += 1;
+ if i == page.bytes && array_format != "g" {
+ print!("{}", hex_lower_hex(*hex));
+ } else {
+ print!("{}, ", hex_lower_hex(*hex));
+ }
+ }
+ println!();
+ }
+ match array_format {
+ "r" => println!("];"),
+ "c" => println!("}};"),
+ "g" => println!("}}"),
+ _ => println!("unknown array format"),
+ }
+}
+
+/// Function wave out.
+/// # Arguments
+///
+/// * `len` - Wave length.
+/// * `places` - Number of decimal places for function wave floats.
+pub fn output_function(len: u64, places: usize) {
+ for y in 0..len {
+ let y_float: f64 = y as f64;
+ let len_float: f64 = len as f64;
+ let x: f64 = (((y_float / len_float) * f64::consts::PI) / 2.0).sin();
+ let formatted_number = format!("{:.*}", places, x);
+ print!("{}", formatted_number);
+ print!(",");
+ if (y % 10) == 9 {
+ println!();
+ }
+ }
+ println!();
+}
+
/// Buffer to array.
///
/// # Arguments
///
/// * `buf` - Buffer to be read.
-/// * `buf_len` - Buffer length.
+/// * `buf_len` - force buffer length.
/// * `column_width` - column width for output.
pub fn buf_to_array(
- buf: &mut Read,
+ buf: &mut dyn Read,
buf_len: u64,
column_width: u64,
-) -> Result<Page, Box<::std::error::Error>> {
+) -> Result<Page, Box<dyn ::std::error::Error>> {
let mut column_count: u64 = 0x0;
let max_array_size: u16 = <u16>::max_value(); // 2^16;
let mut page: Page = Page::new();
@@ -366,11 +444,12 @@ pub fn buf_to_array(
line = Line::new();
column_count = 0;
}
- if page.bytes == buf_len || u64::from(max_array_size) == buf_len {
- page.body.push(line);
+
+ if buf_len > 0 && (page.bytes == buf_len || u64::from(max_array_size) == buf_len) {
break;
}
}
+ page.body.push(line);
Ok(page)
}