diff --git a/Cargo.lock b/Cargo.lock index a4a6be1..be88e86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -621,6 +621,18 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1201,6 +1213,7 @@ dependencies = [ "colored", "csv", "ed25519-dalek", + "enum_dispatch", "rand", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 26e93eb..318211c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ clap = { version = "4.5.4", features = ["derive"] } colored = "2.1.0" csv = "1.3.0" ed25519-dalek = { version = "2.1.1", features = ["rand_core"] } +enum_dispatch = "0.3.13" rand = "0.8.5" serde = { version = "1.0.198", features = ["derive"] } serde_json = "1.0.116" diff --git a/src/cli/base64.rs b/src/cli/base64.rs index 76d5f6a..e725f13 100644 --- a/src/cli/base64.rs +++ b/src/cli/base64.rs @@ -1,4 +1,5 @@ use clap::{Parser, ValueEnum}; +use enum_dispatch::enum_dispatch; use crate::{ process::{process_decode, process_encode}, @@ -8,6 +9,7 @@ use crate::{ use super::verify_file; #[derive(Debug, Parser)] +#[enum_dispatch(CmdExector)] pub enum Base64SubCommand { #[command(name = "encode", about = "Encode a string to base64")] Encode(Base64EncodeOpts), @@ -47,15 +49,6 @@ pub enum Base64Format { Urlsafe, } -impl CmdExector for Base64SubCommand { - async fn execute(self) -> anyhow::Result<()> { - match self { - Base64SubCommand::Decode(opts) => opts.execute().await, - Base64SubCommand::Encode(opts) => opts.execute().await, - } - } -} - impl CmdExector for Base64DecodeOpts { async fn execute(self) -> anyhow::Result<()> { let encoded = process_decode(&self.input, self.format, self.no_padding)?; diff --git a/src/cli/http.rs b/src/cli/http.rs index 223cda7..8d801ce 100644 --- a/src/cli/http.rs +++ b/src/cli/http.rs @@ -1,8 +1,10 @@ use crate::{cli::verify_dir, process::process_http_serve, CmdExector}; use clap::Parser; +use enum_dispatch::enum_dispatch; use std::path::PathBuf; #[derive(Debug, Parser)] +#[enum_dispatch(CmdExector)] pub enum HttpSubCommand { #[command(about = "Serve a directory over HTTP")] Serve(HttpServeOpts), @@ -16,14 +18,6 @@ pub struct HttpServeOpts { pub port: u16, } -impl CmdExector for HttpSubCommand { - async fn execute(self) -> anyhow::Result<()> { - match self { - HttpSubCommand::Serve(opts) => opts.execute().await, - } - } -} - impl CmdExector for HttpServeOpts { async fn execute(self) -> anyhow::Result<()> { process_http_serve(self.dir, self.port).await?; diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 0699ea4..6047c6b 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -5,16 +5,17 @@ pub mod http; pub mod text; pub mod time; -use std::path::{Path, PathBuf}; - -use self::http::HttpSubCommand; -use self::time::TimeOpts; use clap::{Parser, Subcommand}; +use enum_dispatch::enum_dispatch; + +use std::path::{Path, PathBuf}; -pub use self::base64::Base64SubCommand; -pub use self::csv::{CsvOpts, OutputFormat}; -pub use self::gen_pass::GenPassOpts; -pub use self::text::{TextSignFormat, TextSignOpts, TextSubCommand, TextVerifyOpts}; +pub use self::base64::*; +pub use self::csv::*; +pub use self::gen_pass::*; +pub use self::http::*; +pub use self::text::*; +pub use self::time::*; #[derive(Debug, Parser)] #[command(version, about, long_about = None)] @@ -25,6 +26,7 @@ pub struct Opts { /// rcli csv -i input.csv -o output.json --header -d ',' #[derive(Debug, Subcommand)] +#[enum_dispatch(CmdExector)] pub enum SubCommand { #[command(name = "csv", about = "Show CSV, or convert CSV to other formats")] Csv(CsvOpts), diff --git a/src/cli/text.rs b/src/cli/text.rs index 80eeac0..3d337be 100644 --- a/src/cli/text.rs +++ b/src/cli/text.rs @@ -3,6 +3,7 @@ use std::{fs, path::PathBuf}; use anyhow::Ok; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use clap::{Parser, ValueEnum}; +use enum_dispatch::enum_dispatch; use crate::{ cli::{verify_dir, verify_file}, @@ -11,6 +12,7 @@ use crate::{ }; #[derive(Debug, Parser)] +#[enum_dispatch(CmdExector)] pub enum TextSubCommand { #[command(about = "Sign a message with a private key")] Sign(TextSignOpts), @@ -63,16 +65,6 @@ pub struct GenKeyOpts { pub output: PathBuf, } -impl CmdExector for TextSubCommand { - async fn execute(self) -> anyhow::Result<()> { - match self { - TextSubCommand::GenKey(opts) => opts.execute().await, - TextSubCommand::Sign(opts) => opts.execute().await, - TextSubCommand::Verify(opts) => opts.execute().await, - } - } -} - impl CmdExector for TextSignOpts { async fn execute(self) -> anyhow::Result<()> { let sig = process_text_sign(&self.input, &self.key, self.format)?; diff --git a/src/lib.rs b/src/lib.rs index 0269285..342df5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,11 @@ pub mod cli; pub mod process; pub mod utils; -pub use cli::TextSignFormat; +pub use cli::*; +use enum_dispatch::enum_dispatch; #[allow(async_fn_in_trait)] +#[enum_dispatch] pub trait CmdExector { async fn execute(self) -> anyhow::Result<()>; } diff --git a/src/main.rs b/src/main.rs index f90762a..8f46462 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,13 +5,6 @@ use rcli::{cli, CmdExector}; async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); let opts = cli::Opts::parse(); - match opts.cmd { - cli::SubCommand::Csv(opts) => opts.execute().await?, - cli::SubCommand::GenPass(opts) => opts.execute().await?, - cli::SubCommand::Base64(cmd) => cmd.execute().await?, - cli::SubCommand::Time(opts) => opts.execute().await?, - cli::SubCommand::Text(cmd) => cmd.execute().await?, - cli::SubCommand::Http(cmd) => cmd.execute().await?, - } + opts.cmd.execute().await?; Ok(()) }