generated from PlexSheep/rs-base
reafactor(numf_parser): add numf_parser_str and make numf_parser work with any data
cargo devel CI / cargo CI (push) Successful in 1m38s
Details
cargo devel CI / cargo CI (push) Successful in 1m38s
Details
This commit is contained in:
parent
45409c4ff3
commit
df32a863d6
|
@ -116,12 +116,12 @@ pub struct FormatOptions {
|
||||||
#[arg(short = 'a', long)]
|
#[arg(short = 'a', long)]
|
||||||
/// format raw, no text
|
/// format raw, no text
|
||||||
raw: bool,
|
raw: bool,
|
||||||
#[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser::<NumberType>)]
|
#[arg(short = 'r', long, default_value_t = 0, value_parser=numf_parser_str::<NumberType>)]
|
||||||
/// output random numbers
|
/// output random numbers
|
||||||
///
|
///
|
||||||
/// Add a user defined amount of cryptographically pseudorandom numbers to the number list.
|
/// Add a user defined amount of cryptographically pseudorandom numbers to the number list.
|
||||||
rand: NumberType,
|
rand: NumberType,
|
||||||
#[arg(long, default_value_t = NumberType::MAX, value_parser=numf_parser::<NumberType>)]
|
#[arg(long, default_value_t = NumberType::MAX, value_parser=numf_parser_str::<NumberType>)]
|
||||||
/// max for the random numbers
|
/// max for the random numbers
|
||||||
///
|
///
|
||||||
/// Generated numbers will not be lower than this. Only has an effect with --rand set.
|
/// 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)]
|
#[arg(short = 'z', long)]
|
||||||
/// format to base32
|
/// format to base32
|
||||||
base32: bool,
|
base32: bool,
|
||||||
#[clap(value_parser=numf_parser::<NumberType>, required=false)]
|
#[clap(value_parser=numf_parser_str::<NumberType>, required=false)]
|
||||||
/// numbers that should be formatted
|
/// numbers that should be formatted
|
||||||
///
|
///
|
||||||
/// Any of the [Formats](Format::format) are supported, but the prefixes are needed for formats
|
/// 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 clap::Parser;
|
||||||
/// use numf::format::numf_parser;
|
/// use numf::format::numf_parser_str;
|
||||||
///
|
///
|
||||||
/// #[derive(Parser)]
|
/// #[derive(Parser)]
|
||||||
/// struct Args {
|
/// struct Args {
|
||||||
/// #[clap(short, long, value_parser=numf_parser::<u128>)]
|
/// #[clap(short, long, value_parser=numf_parser_str::<u128>)]
|
||||||
/// address: u128,
|
/// address: u128,
|
||||||
/// }
|
/// }
|
||||||
/// let args = Args::parse_from(&["", "-a", "0x10"]);
|
/// let args = Args::parse_from(&["", "-a", "0x10"]);
|
||||||
/// assert_eq!(args.address, 16);
|
/// assert_eq!(args.address, 16);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn numf_parser<T>(s: &str) -> anyhow::Result<T>
|
pub fn numf_parser_str<T>(s: &str) -> anyhow::Result<T>
|
||||||
where
|
where
|
||||||
T: std::str::FromStr + std::convert::TryFrom<u128>,
|
T: std::str::FromStr + std::convert::TryFrom<u128>,
|
||||||
<T as std::str::FromStr>::Err: std::fmt::Display,
|
<T as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
@ -391,10 +391,29 @@ where
|
||||||
<T as std::convert::TryFrom<u128>>::Error: std::marker::Sync,
|
<T as std::convert::TryFrom<u128>>::Error: std::marker::Sync,
|
||||||
<T as std::convert::TryFrom<u128>>::Error: 'static,
|
<T as std::convert::TryFrom<u128>>::Error: 'static,
|
||||||
{
|
{
|
||||||
if s.starts_with(&Format::Dec.prefix_str()) || s.parse::<T>().is_ok() {
|
numf_parser(s.as_bytes())
|
||||||
let s = match s.strip_prefix(&Format::Dec.prefix_str()) {
|
}
|
||||||
|
|
||||||
|
pub fn numf_parser<T>(data: &[u8]) -> anyhow::Result<T>
|
||||||
|
where
|
||||||
|
T: std::str::FromStr + std::convert::TryFrom<u128>,
|
||||||
|
<T as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
T: num::Num,
|
||||||
|
<T as num::Num>::FromStrRadixErr: std::fmt::Display,
|
||||||
|
<T as std::str::FromStr>::Err: std::fmt::Debug,
|
||||||
|
u128: std::convert::From<T>,
|
||||||
|
<T as std::str::FromStr>::Err: std::error::Error,
|
||||||
|
<T as std::convert::TryFrom<u128>>::Error: std::error::Error,
|
||||||
|
<T as std::convert::TryFrom<u128>>::Error: std::marker::Send,
|
||||||
|
<T as std::convert::TryFrom<u128>>::Error: std::marker::Sync,
|
||||||
|
<T as std::convert::TryFrom<u128>>::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::<T>().is_ok() {
|
||||||
|
let s = match data_as_text.strip_prefix(&Format::Dec.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match s.parse() {
|
match s.parse() {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
|
@ -403,10 +422,10 @@ where
|
||||||
Err(anyhow!(e))
|
Err(anyhow!(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.starts_with(&Format::Hex.prefix_str()) {
|
} else if data_as_text.starts_with(&Format::Hex.prefix_str()) {
|
||||||
let s = match s.strip_prefix(&Format::Hex.prefix_str()) {
|
let s = match data_as_text.strip_prefix(&Format::Hex.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match T::from_str_radix(s, 16) {
|
match T::from_str_radix(s, 16) {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
|
@ -415,10 +434,10 @@ where
|
||||||
Err(anyhow!(e))
|
Err(anyhow!(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.starts_with(&Format::Octal.prefix_str()) {
|
} else if data_as_text.starts_with(&Format::Octal.prefix_str()) {
|
||||||
let s = match s.strip_prefix(&Format::Octal.prefix_str()) {
|
let s = match data_as_text.strip_prefix(&Format::Octal.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match T::from_str_radix(s, 8) {
|
match T::from_str_radix(s, 8) {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
|
@ -427,10 +446,10 @@ where
|
||||||
Err(anyhow!(e))
|
Err(anyhow!(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.starts_with(&Format::Bin.prefix_str()) {
|
} else if data_as_text.starts_with(&Format::Bin.prefix_str()) {
|
||||||
let s = match s.strip_prefix(&Format::Bin.prefix_str()) {
|
let s = match data_as_text.strip_prefix(&Format::Bin.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match T::from_str_radix(s, 2) {
|
match T::from_str_radix(s, 2) {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
|
@ -439,10 +458,10 @@ where
|
||||||
Err(anyhow!(e))
|
Err(anyhow!(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.starts_with(&Format::Base64.prefix_str()) {
|
} else if data_as_text.starts_with(&Format::Base64.prefix_str()) {
|
||||||
let s = match s.strip_prefix(&Format::Base64.prefix_str()) {
|
let s = match data_as_text.strip_prefix(&Format::Base64.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match fast32::base64::RFC4648.decode_str(s) {
|
match fast32::base64::RFC4648.decode_str(s) {
|
||||||
Ok(r) => Ok(join::array_to_unsigned::<T>(&r)?),
|
Ok(r) => Ok(join::array_to_unsigned::<T>(&r)?),
|
||||||
|
@ -451,10 +470,10 @@ where
|
||||||
Err(anyhow!(e))
|
Err(anyhow!(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.starts_with(&Format::Base32.prefix_str()) {
|
} else if data_as_text.starts_with(&Format::Base32.prefix_str()) {
|
||||||
let s = match s.strip_prefix(&Format::Base32.prefix_str()) {
|
let s = match data_as_text.strip_prefix(&Format::Base32.prefix_str()) {
|
||||||
Some(sr) => sr,
|
Some(sr) => sr,
|
||||||
None => s,
|
None => &data_as_text,
|
||||||
};
|
};
|
||||||
match fast32::base32::RFC4648.decode_str(s) {
|
match fast32::base32::RFC4648.decode_str(s) {
|
||||||
Ok(r) => Ok(join::array_to_unsigned::<T>(&r)?),
|
Ok(r) => Ok(join::array_to_unsigned::<T>(&r)?),
|
||||||
|
@ -463,14 +482,13 @@ where
|
||||||
Err(anyhow!(e))
|
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 {
|
} else {
|
||||||
let e = "could not determine the format of the value".to_string();
|
// what could go wrong with interpreting everything else as raw number input
|
||||||
Err(anyhow!(e))
|
let s: Vec<u8> = 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)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/main.rs
20
src/main.rs
|
@ -2,6 +2,7 @@ use std::io::{IsTerminal, Read, Write};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
|
use numf::format::numf_parser_str;
|
||||||
|
|
||||||
mod format;
|
mod format;
|
||||||
use crate::format::{numf_parser, Format};
|
use crate::format::{numf_parser, Format};
|
||||||
|
@ -26,17 +27,24 @@ fn main() -> anyhow::Result<()> {
|
||||||
if !stdin.is_terminal() {
|
if !stdin.is_terminal() {
|
||||||
match stdin.lock().read_to_end(&mut stdin_nums) {
|
match stdin.lock().read_to_end(&mut stdin_nums) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let whole: String = match String::from_utf8(stdin_nums) {
|
let whole: String = match String::from_utf8(stdin_nums.clone()) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(_) => {
|
||||||
eprintln!("{}", FormatOptions::command().render_usage());
|
let number = match numf_parser(&stdin_nums) {
|
||||||
eprintln!("stdin for this program only accepts text: {e:#?}");
|
Ok(n) => n,
|
||||||
exit(1);
|
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();
|
let split = whole.split_whitespace();
|
||||||
for s in split {
|
for s in split {
|
||||||
let number = match numf_parser(s) {
|
let number = match numf_parser_str(s) {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}", FormatOptions::command().render_usage());
|
eprintln!("{}", FormatOptions::command().render_usage());
|
||||||
|
|
Reference in New Issue