From df32a863d654e215b3aa1f01cc38bb27b6644c64 Mon Sep 17 00:00:00 2001 From: "Christoph J. Scherr" Date: Fri, 6 Sep 2024 12:47:26 +0200 Subject: [PATCH] reafactor(numf_parser): add numf_parser_str and make numf_parser work with any data --- src/format.rs | 82 +++++++++++++++++++++++++++++++-------------------- src/main.rs | 20 +++++++++---- 2 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/format.rs b/src/format.rs index 9363eb3..6adc06b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -116,12 +116,12 @@ pub struct FormatOptions { #[arg(short = 'a', long)] /// format raw, no text raw: bool, - #[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser::)] + #[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser_str::)] /// output random numbers /// /// Add a user defined amount of cryptographically pseudorandom numbers to the number list. rand: NumberType, - #[arg(long, default_value_t = NumberType::MAX, value_parser=numf_parser::)] + #[arg(long, default_value_t = NumberType::MAX, value_parser=numf_parser_str::)] /// max for the random numbers /// /// Generated numbers will not be lower than this. Only has an effect with --rand set. @@ -129,7 +129,7 @@ pub struct FormatOptions { #[arg(short = 'z', long)] /// format to base32 base32: bool, - #[clap(value_parser=numf_parser::, required=false)] + #[clap(value_parser=numf_parser_str::, required=false)] /// numbers that should be formatted /// /// Any of the [Formats](Format::format) are supported, but the prefixes are needed for formats @@ -367,17 +367,17 @@ impl Format { /// /// ``` /// use clap::Parser; -/// use numf::format::numf_parser; +/// use numf::format::numf_parser_str; /// /// #[derive(Parser)] /// struct Args { -/// #[clap(short, long, value_parser=numf_parser::)] +/// #[clap(short, long, value_parser=numf_parser_str::)] /// address: u128, /// } /// let args = Args::parse_from(&["", "-a", "0x10"]); /// assert_eq!(args.address, 16); /// ``` -pub fn numf_parser(s: &str) -> anyhow::Result +pub fn numf_parser_str(s: &str) -> anyhow::Result where T: std::str::FromStr + std::convert::TryFrom, ::Err: std::fmt::Display, @@ -391,10 +391,29 @@ where >::Error: std::marker::Sync, >::Error: 'static, { - if s.starts_with(&Format::Dec.prefix_str()) || s.parse::().is_ok() { - let s = match s.strip_prefix(&Format::Dec.prefix_str()) { + numf_parser(s.as_bytes()) +} + +pub fn numf_parser(data: &[u8]) -> anyhow::Result +where + T: std::str::FromStr + std::convert::TryFrom, + ::Err: std::fmt::Display, + T: num::Num, + ::FromStrRadixErr: std::fmt::Display, + ::Err: std::fmt::Debug, + u128: std::convert::From, + ::Err: std::error::Error, + >::Error: std::error::Error, + >::Error: std::marker::Send, + >::Error: std::marker::Sync, + >::Error: 'static, +{ + let data_as_text = String::from_utf8_lossy(data).to_string(); + + if data_as_text.starts_with(&Format::Dec.prefix_str()) || data_as_text.parse::().is_ok() { + let s = match data_as_text.strip_prefix(&Format::Dec.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match s.parse() { Ok(r) => Ok(r), @@ -403,10 +422,10 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Hex.prefix_str()) { - let s = match s.strip_prefix(&Format::Hex.prefix_str()) { + } else if data_as_text.starts_with(&Format::Hex.prefix_str()) { + let s = match data_as_text.strip_prefix(&Format::Hex.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match T::from_str_radix(s, 16) { Ok(r) => Ok(r), @@ -415,10 +434,10 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Octal.prefix_str()) { - let s = match s.strip_prefix(&Format::Octal.prefix_str()) { + } else if data_as_text.starts_with(&Format::Octal.prefix_str()) { + let s = match data_as_text.strip_prefix(&Format::Octal.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match T::from_str_radix(s, 8) { Ok(r) => Ok(r), @@ -427,10 +446,10 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Bin.prefix_str()) { - let s = match s.strip_prefix(&Format::Bin.prefix_str()) { + } else if data_as_text.starts_with(&Format::Bin.prefix_str()) { + let s = match data_as_text.strip_prefix(&Format::Bin.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match T::from_str_radix(s, 2) { Ok(r) => Ok(r), @@ -439,10 +458,10 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Base64.prefix_str()) { - let s = match s.strip_prefix(&Format::Base64.prefix_str()) { + } else if data_as_text.starts_with(&Format::Base64.prefix_str()) { + let s = match data_as_text.strip_prefix(&Format::Base64.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match fast32::base64::RFC4648.decode_str(s) { Ok(r) => Ok(join::array_to_unsigned::(&r)?), @@ -451,10 +470,10 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Base32.prefix_str()) { - let s = match s.strip_prefix(&Format::Base32.prefix_str()) { + } else if data_as_text.starts_with(&Format::Base32.prefix_str()) { + let s = match data_as_text.strip_prefix(&Format::Base32.prefix_str()) { Some(sr) => sr, - None => s, + None => &data_as_text, }; match fast32::base32::RFC4648.decode_str(s) { Ok(r) => Ok(join::array_to_unsigned::(&r)?), @@ -463,14 +482,13 @@ where Err(anyhow!(e)) } } - } else if s.starts_with(&Format::Raw.prefix_str()) { - let s = match s.strip_prefix(&Format::Raw.prefix_str()) { - Some(sr) => sr, - None => s, - }; - Ok(join::array_to_unsigned(s.as_bytes())?) } else { - let e = "could not determine the format of the value".to_string(); - Err(anyhow!(e)) + // what could go wrong with interpreting everything else as raw number input + let s: Vec = if data.len() > 2 && data[0] == 0x00 { + data.iter().skip(1).map(ToOwned::to_owned).collect() + } else { + data.as_ref().to_vec() + }; + Ok(join::array_to_unsigned(&s)?) } } diff --git a/src/main.rs b/src/main.rs index 28790f2..c764f6f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::io::{IsTerminal, Read, Write}; use std::process::exit; use clap::{CommandFactory, Parser}; +use numf::format::numf_parser_str; mod format; use crate::format::{numf_parser, Format}; @@ -26,17 +27,24 @@ fn main() -> anyhow::Result<()> { if !stdin.is_terminal() { match stdin.lock().read_to_end(&mut stdin_nums) { Ok(_) => { - let whole: String = match String::from_utf8(stdin_nums) { + let whole: String = match String::from_utf8(stdin_nums.clone()) { Ok(r) => r, - Err(e) => { - eprintln!("{}", FormatOptions::command().render_usage()); - eprintln!("stdin for this program only accepts text: {e:#?}"); - exit(1); + Err(_) => { + let number = match numf_parser(&stdin_nums) { + Ok(n) => n, + Err(e) => { + eprintln!("{}", FormatOptions::command().render_usage()); + eprintln!("could not parse number from stdin: {e:#?}"); + exit(2); + } + }; + options.push_number(number); + String::new() } }; let split = whole.split_whitespace(); for s in split { - let number = match numf_parser(s) { + let number = match numf_parser_str(s) { Ok(n) => n, Err(e) => { eprintln!("{}", FormatOptions::command().render_usage());