Simplify arg parsing

This commit is contained in:
Garen Tyler 2024-12-05 16:54:24 -07:00
parent 28f1656c81
commit e9e35c0dbe
Signed by: garentyler
SSH Key Fingerprint: SHA256:G4ke7blZMdpWPbkescyZ7IQYE4JAtwpI85YoJdq+S7U
7 changed files with 100 additions and 36 deletions

27
Cargo.lock generated
View File

@ -175,6 +175,7 @@ dependencies = [
"async-trait",
"base64",
"clap",
"const_format",
"nom",
"once_cell",
"serde",
@ -188,6 +189,26 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "const_format"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.13"
@ -782,6 +803,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "utf8parse"
version = "0.2.2"

View File

@ -35,3 +35,4 @@ tracing = { version = "0.1.37", features = ["log"] }
tracing-subscriber = { version = "0.3.17", features = ["tracing-log"] }
tracing-appender = "0.2.2"
nom = "7.1.3"
const_format = "0.2.33"

View File

@ -1,7 +1,6 @@
use clap::Arg;
use once_cell::sync::{Lazy, OnceCell};
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
use std::io::{Read, Write};
use std::{fs::File, path::Path, path::PathBuf};
use tracing::{error, trace, warn};
@ -18,7 +17,8 @@ pub static CONFIG: OnceCell<Config> = OnceCell::new();
/// The globablly-accessible static instance of Args.
/// On program startup, Args::load() should be called to initialize it.
pub static ARGS: OnceCell<Args> = OnceCell::new();
static DEFAULT_ARGS: Lazy<Args> = Lazy::new(Args::default);
const DEFAULT_CONFIG_FILE: &str = "composition.toml";
const DEFAULT_LOG_DIR: &str = "logs";
/// Helper function to read a file from a `Path`
/// and return its bytes as a `Vec<u8>`.
@ -140,8 +140,8 @@ impl Default for GlobalConfig {
fn default() -> Self {
GlobalConfig {
version: Config::get_formatted_version(Subcommand::None),
protocol_version: 762,
game_version: "1.19.4".to_owned(),
protocol_version: crate::PROTOCOL_VERSION,
game_version: crate::GAME_VERSION.to_owned(),
threads: None,
}
}
@ -179,9 +179,9 @@ pub struct Args {
impl Default for Args {
fn default() -> Self {
Args {
config_file: PathBuf::from("composition.toml"),
config_file: PathBuf::from(DEFAULT_CONFIG_FILE),
log_level: None,
log_dir: PathBuf::from("logs"),
log_dir: PathBuf::from(DEFAULT_LOG_DIR),
subcommand: Subcommand::None,
#[cfg(feature = "server")]
server: None,
@ -229,7 +229,7 @@ impl Args {
.help("Configuration file path")
.global(true)
.value_hint(clap::ValueHint::FilePath)
.default_value(OsStr::new(&DEFAULT_ARGS.config_file)),
.default_value(DEFAULT_CONFIG_FILE),
)
.arg(
Arg::new("log-level")
@ -248,7 +248,7 @@ impl Args {
.global(true)
.value_name("dir")
.value_hint(clap::ValueHint::DirPath)
.default_value(OsStr::new(&DEFAULT_ARGS.log_dir)),
.default_value(DEFAULT_LOG_DIR),
);
#[cfg(feature = "server")]
{

View File

@ -16,6 +16,9 @@ use config::Subcommand;
use once_cell::sync::OnceCell;
use std::time::Instant;
pub const PROTOCOL_VERSION: i32 = 762;
pub const GAME_VERSION: &str = "1.19.4";
/// A globally accessible instant of the composition's start time.
///
/// This should be set immediately on startup.

View File

@ -1,10 +1,10 @@
use crate::config::{Args, Config};
use clap::Arg;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
pub static DEFAULT_PROXY_ARGS: Lazy<ProxyArgs> = Lazy::new(ProxyArgs::default);
const DEFAULT_PORT: u16 = 25566;
const DEFAULT_UPSTREAM_HOST: &str = "127.0.0.1";
const DEFAULT_UPSTREAM_PORT: u16 = 25565;
/// The main server configuration struct.
#[derive(Debug, Deserialize, Serialize)]
@ -14,14 +14,16 @@ pub struct ProxyConfig {
#[serde(rename = "version-string")]
pub version: String,
pub port: u16,
pub upstream: String,
pub upstream_host: String,
pub upstream_port: u16,
}
impl Default for ProxyConfig {
fn default() -> Self {
ProxyConfig {
version: Config::get_formatted_version(crate::config::Subcommand::Proxy),
port: 25565,
upstream: String::new(),
port: DEFAULT_PORT,
upstream_host: DEFAULT_UPSTREAM_HOST.to_owned(),
upstream_port: DEFAULT_UPSTREAM_PORT,
}
}
}
@ -30,16 +32,27 @@ impl ProxyConfig {
&Config::instance().proxy
}
pub fn load_args(&mut self) {
self.upstream = ProxyArgs::instance()
self.upstream_host = ProxyArgs::instance()
.as_ref()
.map(|p| p.upstream.clone())
.unwrap_or(DEFAULT_PROXY_ARGS.upstream.clone());
.map(|p| p.upstream_host.clone())
.unwrap_or(DEFAULT_UPSTREAM_HOST.to_owned());
}
}
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct ProxyArgs {
upstream: String,
port: u16,
upstream_host: String,
upstream_port: u16,
}
impl Default for ProxyArgs {
fn default() -> Self {
ProxyArgs {
port: DEFAULT_PORT,
upstream_host: DEFAULT_UPSTREAM_HOST.to_owned(),
upstream_port: DEFAULT_UPSTREAM_PORT,
}
}
}
impl ProxyArgs {
pub fn instance() -> Option<&'static Self> {
@ -49,20 +62,40 @@ impl ProxyArgs {
clap::Command::new("proxy")
.about("Run composition in proxy mode")
.arg(
Arg::new("upstream")
.short('u')
.long("upstream")
Arg::new("port")
.short('p')
.long("port")
.help("Proxy listening port")
.value_hint(clap::ValueHint::Other)
.default_value(const_format::formatcp!("{}", DEFAULT_PORT)),
)
.arg(
Arg::new("upstream-host")
.short('U')
.long("upstream-host")
.help("Upstream server address")
.value_hint(clap::ValueHint::Hostname)
.default_value(OsStr::new(&DEFAULT_PROXY_ARGS.upstream)),
.default_value(const_format::formatcp!("{}", DEFAULT_UPSTREAM_HOST)),
)
.arg(
Arg::new("upstream-port")
.short('P')
.long("upstream-port")
.help("Upstream server port")
.value_hint(clap::ValueHint::Other)
.default_value(const_format::formatcp!("{}", DEFAULT_UPSTREAM_PORT)),
)
}
pub fn parse(m: clap::ArgMatches) -> Self {
let mut proxy_args = ProxyArgs::default();
proxy_args.upstream = m
.get_one::<String>("upstream")
.unwrap_or(&proxy_args.upstream)
proxy_args.port = *m.get_one::<u16>("port").unwrap_or(&proxy_args.port);
proxy_args.upstream_host = m
.get_one::<String>("upstream-host")
.unwrap_or(&proxy_args.upstream_host)
.clone();
proxy_args.upstream_port = *m
.get_one::<u16>("upstream-port")
.unwrap_or(&proxy_args.upstream_port);
proxy_args
}
}

View File

@ -23,7 +23,10 @@ impl Proxy {
"Done! Start took {:?}",
crate::START_TIME.get().unwrap().elapsed()
);
info!("Upstream server: {}", config.proxy.upstream);
info!(
"Upstream server: {}:{}",
config.proxy.upstream_host, config.proxy.upstream_port
);
// Spawn the ctrl-c task.
let r = running.clone();

View File

@ -1,13 +1,11 @@
use crate::config::{read_file, Args, Config};
use clap::Arg;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::ffi::OsStr;
use std::io::Write;
use std::{fs::File, path::Path, path::PathBuf};
use tracing::{error, trace, warn};
pub static DEFAULT_SERVER_ARGS: Lazy<ServerArgs> = Lazy::new(ServerArgs::default);
const DEFAULT_SERVER_ICON: &str = "server-icon.png";
/// The main server configuration struct.
#[derive(Debug, Deserialize, Serialize)]
@ -30,7 +28,7 @@ impl Default for ServerConfig {
port: 25565,
max_players: 20,
motd: "Hello world!".to_owned(),
server_icon: PathBuf::from("server-icon.png"),
server_icon: PathBuf::from(DEFAULT_SERVER_ICON),
server_icon_bytes: include_bytes!("../server-icon.png").to_vec(),
}
}
@ -43,7 +41,7 @@ impl ServerConfig {
self.server_icon = ServerArgs::instance()
.as_ref()
.map(|s| s.server_icon.clone())
.unwrap_or(DEFAULT_SERVER_ARGS.server_icon.clone());
.unwrap_or(PathBuf::from(DEFAULT_SERVER_ICON));
self.load_icon();
}
/// Load the server icon.
@ -87,9 +85,8 @@ pub struct ServerArgs {
}
impl Default for ServerArgs {
fn default() -> Self {
let config = Config::default();
ServerArgs {
server_icon: config.server.server_icon,
server_icon: PathBuf::from(DEFAULT_SERVER_ICON),
}
}
}
@ -105,7 +102,7 @@ impl ServerArgs {
.long("server-icon")
.help("Server icon file path")
.value_hint(clap::ValueHint::FilePath)
.default_value(OsStr::new(&DEFAULT_SERVER_ARGS.server_icon)),
.default_value(DEFAULT_SERVER_ICON),
)
}
pub fn parse(m: clap::ArgMatches) -> Self {