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

46
app/src/commands.rs

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

8
app/src/commands/encode.rs

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

4
app/src/config.rs

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

Loading…
Cancel
Save