add cli for usage and benchmarking
This commit is contained in:
parent
a9d81f015e
commit
3101c03211
4 changed files with 422 additions and 30 deletions
165
src/cli.rs
Normal file
165
src/cli.rs
Normal file
|
@ -0,0 +1,165 @@
|
|||
// this is a separate feature for *optional* dependencies to ensure clap doesn't get compiled if you're just using the library
|
||||
use cat2text::{self, anybase, core};
|
||||
use clap::{CommandFactory, Parser, Subcommand};
|
||||
use clap_complete::aot::{generate, Bash, Fish, PowerShell, Zsh};
|
||||
use std::{
|
||||
io::stdout,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub(crate) struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub(crate) enum Commands {
|
||||
///Generate bash completions
|
||||
GenerateBashCompletions,
|
||||
///Generate zsh completions
|
||||
GenerateZshCompletions,
|
||||
///Generate fish completions
|
||||
GenerateFishCompletions,
|
||||
///Generate PowerShell completions,
|
||||
GeneratePowershellCompletions,
|
||||
///Encodes text/data to mrow~
|
||||
///
|
||||
///The default is base 4 text encoding, to match the original program, but it can encode either text or binary data in up to base 16 meows :3
|
||||
Encode {
|
||||
///What base to encode using - up to base 16
|
||||
#[arg(short, long, default_value_t = 4)]
|
||||
base: u8,
|
||||
#[arg(long, default_value_t = false)]
|
||||
///Whether to use byte encoding or English text encoding; text encoding can only handle a-z (lowercase)
|
||||
bytes: bool,
|
||||
text: String,
|
||||
},
|
||||
///Decodes mrow~ to text/data
|
||||
///
|
||||
///The default is base 4 text encoding, to match the original program, but it can decode either text or binary data in up to base 16 meows :3
|
||||
Decode {
|
||||
///What base to decode using - up to base 16
|
||||
#[arg(short, long, default_value_t = 4)]
|
||||
base: u8,
|
||||
#[arg(long, default_value_t = false)]
|
||||
///Whether the input is using byte encoding or English text encoding
|
||||
bytes: bool,
|
||||
text: String,
|
||||
},
|
||||
Benchmark {
|
||||
///What base to benchmark using - up to base 16
|
||||
#[arg(short, long, default_value_t = 4)]
|
||||
base: u8,
|
||||
///Whether to use byte encoding or English text encoding; text encoding can only handle a-z (lowercase)
|
||||
#[arg(long, default_value_t = false)]
|
||||
bytes: bool,
|
||||
///How many iterations to run each benchmark for
|
||||
#[arg(short, long, default_value_t = 1000)]
|
||||
iterations: u128,
|
||||
text: String,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) fn run() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Commands::GenerateBashCompletions => {
|
||||
generate(
|
||||
Bash,
|
||||
&mut Cli::command(),
|
||||
clap::crate_name!(),
|
||||
&mut stdout(),
|
||||
);
|
||||
}
|
||||
Commands::GenerateZshCompletions => {
|
||||
generate(Zsh, &mut Cli::command(), clap::crate_name!(), &mut stdout());
|
||||
}
|
||||
Commands::GenerateFishCompletions => {
|
||||
generate(
|
||||
Fish,
|
||||
&mut Cli::command(),
|
||||
clap::crate_name!(),
|
||||
&mut stdout(),
|
||||
);
|
||||
}
|
||||
Commands::GeneratePowershellCompletions => {
|
||||
generate(
|
||||
PowerShell,
|
||||
&mut Cli::command(),
|
||||
clap::crate_name!(),
|
||||
&mut stdout(),
|
||||
);
|
||||
}
|
||||
Commands::Encode { base, text, bytes } => {
|
||||
println!("{}", encode(base, text, bytes))
|
||||
}
|
||||
Commands::Decode { base, text, bytes } => {
|
||||
println!("{}", decode(base, text, bytes))
|
||||
}
|
||||
Commands::Benchmark {
|
||||
base,
|
||||
text,
|
||||
bytes,
|
||||
iterations,
|
||||
} => {
|
||||
let mut start = Instant::now();
|
||||
for _ in 0..iterations {
|
||||
let _ = encode(base, text.clone(), bytes);
|
||||
}
|
||||
let encode_time = start.elapsed();
|
||||
println!("Encode time: {}", encode_time.as_millis());
|
||||
|
||||
start = Instant::now();
|
||||
for _ in 0..iterations {
|
||||
let _ = decode(base, text.clone(), bytes);
|
||||
}
|
||||
let decode_time = start.elapsed();
|
||||
|
||||
println!("Decode time: {}", decode_time.as_millis());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn encode(base: u8, text: String, bytes: bool) -> String {
|
||||
match bytes {
|
||||
true => {
|
||||
return format!(
|
||||
"{}",
|
||||
anybase::bytes::encode(
|
||||
text.as_bytes(), // make the string into a Vec<u8>
|
||||
base as u32,
|
||||
core::bytes::char_length(base as u32)
|
||||
)
|
||||
);
|
||||
}
|
||||
false => {
|
||||
return format!(
|
||||
"{}",
|
||||
anybase::encode(text, base as u32, core::char_length(base as u32))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decode(base: u8, text: String, bytes: bool) -> String {
|
||||
match bytes {
|
||||
true => {
|
||||
return anybase::bytes::decode(
|
||||
text,
|
||||
base as u32,
|
||||
core::bytes::char_length(base as u32),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|item| item.to_string() + " ")
|
||||
.collect::<String>()
|
||||
.trim()
|
||||
.to_string();
|
||||
}
|
||||
false => {
|
||||
return anybase::decode(text, base as u32, core::char_length(base as u32));
|
||||
}
|
||||
}
|
||||
}
|
35
src/main.rs
35
src/main.rs
|
@ -1,32 +1,7 @@
|
|||
extern crate cat2text;
|
||||
use cat2text::base4;
|
||||
use std::io::{self, stdout, Write};
|
||||
#[cfg(feature = "bin")]
|
||||
mod cli;
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
let mut input;
|
||||
|
||||
loop {
|
||||
println!("Pick your translation:");
|
||||
println!("1) cat to text");
|
||||
println!("2) text to cat");
|
||||
input = "".to_string();
|
||||
stdin.read_line(&mut input).unwrap();
|
||||
print!("~> ");
|
||||
stdout().flush().unwrap();
|
||||
let trimmed = input.trim();
|
||||
if trimmed == "1".to_string() {
|
||||
input = "".to_string();
|
||||
stdin.read_line(&mut input).unwrap();
|
||||
println!("{}", base4::decode(input.trim().to_string()));
|
||||
} else if trimmed == "2".to_string() {
|
||||
input = "".to_string();
|
||||
stdin.read_line(&mut input).unwrap();
|
||||
println!("{}", base4::encode(input.trim().to_string()));
|
||||
} else {
|
||||
println!("Invalid input, exiting...");
|
||||
break;
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "bin")]
|
||||
cli::run()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue