Browse Source

WIP: refactor

develop-refactor
chodak166 4 months ago
parent
commit
a1d5d6977a
  1. 14
      app/src/app.rs
  2. 46
      app/src/commands.rs
  3. 8
      app/src/commands/decode.rs
  4. 8
      app/src/commands/encode.rs
  5. 8
      app/src/commands/import_dict.rs
  6. 4
      app/src/config.rs

14
app/src/app.rs

@ -1,4 +1,4 @@
use crate::commands::{CliArgs, Command, resolve_command};
use crate::commands::{AppCommand, CliArgs};
use crate::config::AppConfig;
use crate::container::Container;
use anyhow::Result;
@ -8,17 +8,16 @@ use tracing::debug;
pub struct Application {
config: AppConfig,
container: Container,
command: Command,
command: Box<dyn AppCommand>,
}
impl Application {
pub async fn build() -> Result<Self> {
let args = CliArgs::parse();
// Resolve the command once to get the trait object for configuration
let handler = resolve_command(&args.command);
let app_cmd = args.command.into_app_command();
let config = AppConfig::build(&args.global, handler)?;
let config = AppConfig::build(&args.global, app_cmd.as_ref())?;
tracing_subscriber::fmt()
.compact()
@ -33,12 +32,11 @@ impl Application {
Ok(Self {
config,
container,
command: args.command,
command: app_cmd,
})
}
pub async fn run(self) -> Result<()> {
let handler = resolve_command(&self.command);
handler.execute(&self.config, &self.container).await
self.command.execute(&self.config, &self.container).await
}
}

46
app/src/commands.rs

@ -15,23 +15,41 @@ use std::path::PathBuf;
#[derive(Subcommand, Debug, Clone)]
pub enum Command {
/// Decode a word using given system
Decode(decode::DecodeArgs),
Decode(decode::DecodeCmd),
/// Encode a number using given system
Encode(encode::EncodeArgs),
Encode(encode::EncodeCmd),
/// Import dictionary
ImportDict(import_dict::ImportDictArgs),
ImportDict(import_dict::ImportDictCmd),
}
pub fn resolve_command(command: &Command) -> &dyn AppCommand {
match command {
Command::Decode(args) => args,
Command::Encode(args) => args,
Command::ImportDict(args) => args,
impl Command {
pub fn into_app_command(self) -> Box<dyn AppCommand> {
match self {
Command::Decode(cmd) => Box::new(cmd),
Command::Encode(cmd) => Box::new(cmd),
Command::ImportDict(cmd) => Box::new(cmd),
}
}
}
// pub fn resolve_command(command: &Command) -> &dyn AppCommand {
// match command {
// Command::Decode(app_cmd) => app_cmd,
// Command::Encode(app_cmd) => app_cmd,
// Command::ImportDict(app_cmd) => app_cmd,
// }
// }
// pub fn resolve_command_box(command: Command) -> Box<dyn AppCommand> {
// match command {
// Command::Decode(cmd) => Box::new(cmd),
// Command::Encode(cmd) => Box::new(cmd),
// Command::ImportDict(cmd) => Box::new(cmd),
// }
// }
#[derive(Parser, Debug)]
#[command(author, version, about)]
pub struct CliArgs {
@ -52,7 +70,7 @@ pub struct GlobalArgs {
pub log_level: Option<String>,
}
pub trait ConfigurableCommand {
pub trait Configurable {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
@ -64,15 +82,15 @@ pub trait ConfigurableCommand {
}
#[async_trait]
pub trait CommandExecutor {
pub trait Executable {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()>;
}
// AppCommand must be dyn-compatible. ConfigurableCommand is already dyn-compatible.
// CommandExecutor is dyn-compatible because of #[async_trait].
pub trait AppCommand: ConfigurableCommand + CommandExecutor {}
// AppCommand must be dyn-compatible. Configurable is already dyn-compatible.
// Executable is dyn-compatible because of #[async_trait].
pub trait AppCommand: Configurable + Executable {}
impl<T: ConfigurableCommand + CommandExecutor> AppCommand for T {}
impl<T: Configurable + Executable> AppCommand for T {}
mod defaults {
use const_format::formatcp;

8
app/src/commands/decode.rs

@ -1,4 +1,4 @@
use crate::commands::{ClapArgs, CommandExecutor, ConfigurableCommand};
use crate::commands::{ClapArgs, Configurable, Executable};
use crate::config::AppConfig;
use crate::config::System;
use crate::container::Container;
@ -16,7 +16,7 @@ pub struct Config {
}
#[derive(ClapArgs, Debug, Clone)]
pub struct DecodeArgs {
pub struct DecodeCmd {
#[arg(short, long, help = defaults::HELP_DEC_SYSTEM)]
pub system: Option<String>,
@ -24,7 +24,7 @@ pub struct DecodeArgs {
pub input: String,
}
impl ConfigurableCommand for DecodeArgs {
impl Configurable for DecodeCmd {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
@ -50,7 +50,7 @@ impl ConfigurableCommand for DecodeArgs {
}
#[async_trait]
impl CommandExecutor for DecodeArgs {
impl Executable for DecodeCmd {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()> {
let config = config
.decode

8
app/src/commands/encode.rs

@ -1,6 +1,6 @@
use serde::Deserialize;
use crate::commands::{ClapArgs, CommandExecutor, ConfigurableCommand};
use crate::commands::{ClapArgs, Configurable, Executable};
use crate::config::{AppConfig, System};
use crate::container::Container;
@ -17,7 +17,7 @@ pub struct Config {
}
#[derive(ClapArgs, Debug, Clone)]
pub struct EncodeArgs {
pub struct EncodeCmd {
#[arg(short, long, help = defaults::HELP_ENC_SYSTEM)]
pub system: Option<String>,
@ -28,7 +28,7 @@ pub struct EncodeArgs {
pub input: String,
}
impl ConfigurableCommand for EncodeArgs {
impl Configurable for EncodeCmd {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
@ -58,7 +58,7 @@ impl ConfigurableCommand for EncodeArgs {
}
#[async_trait]
impl CommandExecutor for EncodeArgs {
impl Executable for EncodeCmd {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()> {
let config = config
.encode

8
app/src/commands/import_dict.rs

@ -1,4 +1,4 @@
use crate::commands::{ClapArgs, CommandExecutor, ConfigurableCommand};
use crate::commands::{ClapArgs, Configurable, Executable};
use crate::config::AppConfig;
use crate::container::Container;
use anyhow::Result;
@ -14,7 +14,7 @@ pub struct Config {
}
#[derive(ClapArgs, Debug, Clone)]
pub struct ImportDictArgs {
pub struct ImportDictCmd {
#[arg(long, help = defaults::HELP_IMPORT_DICT_NAME)]
pub name: String,
@ -22,7 +22,7 @@ pub struct ImportDictArgs {
pub path: String,
}
impl ConfigurableCommand for ImportDictArgs {
impl Configurable for ImportDictCmd {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
@ -45,7 +45,7 @@ impl ConfigurableCommand for ImportDictArgs {
}
#[async_trait]
impl CommandExecutor for ImportDictArgs {
impl Executable for ImportDictCmd {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()> {
let config = config
.import_dict

4
app/src/config.rs

@ -1,5 +1,5 @@
use crate::commands::*;
// use crate::commands::{ConfigurableCommand, GlobalArgs};
// use crate::commands::{Configurable, GlobalArgs};
use anyhow::{Context, Result};
use config::{Config, Environment, File};
use serde::Deserialize;
@ -16,7 +16,7 @@ pub struct AppConfig {
}
impl AppConfig {
pub fn build(args: &GlobalArgs, handler: &dyn ConfigurableCommand) -> Result<Self> {
pub fn build(args: &GlobalArgs, handler: &dyn Configurable) -> Result<Self> {
let mut builder = Config::builder();
// Command-specific defaults via Trait

Loading…
Cancel
Save