diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f61d2d4..885c49d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -6,7 +6,13 @@ edition = "2024" [dependencies] tokio = { version = "*", features = ["full"] } serde = { version = "*", features = ["derive"] } +either = { version = "*", features = ["serde"] } + thiserror = "*" -clap = { version = "*", features = ["derive"] } +anyhow = "*" tracing = "*" tracing-subscriber = "*" + +clap = { version = "*", features = ["derive"] } +figment = { version = "*", features = ["toml", "env", "json"] } + diff --git a/rust/src/config.rs b/rust/src/config.rs index a70fa34..81800cc 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -1,4 +1,27 @@ +use either::{Either, Either::Left}; use serde::Deserialize; -#[derive(Deserialize)] -struct CommandConfig {} +#[derive(Deserialize, Clone, Debug)] +pub struct CommandConfig { + /// The port(s) to listen on. + /// + /// If you are using Docker, don't change this, you'll need to map an + /// external port to this. + /// + /// To listen on multiple ports, specify a vector e.g. [8080, 8448] + /// + /// default: 8008 + #[serde(default = "default_port")] + pub port: ListeningPort, +} + +#[derive(Deserialize, Clone, Debug)] +#[serde(transparent)] +pub struct ListeningPort { + #[serde(with = "either::serde_untagged")] + pub ports: Either>, +} + +fn default_port() -> ListeningPort { + ListeningPort { ports: Left(8008) } +} diff --git a/rust/src/error.rs b/rust/src/error.rs new file mode 100644 index 0000000..611ce1d --- /dev/null +++ b/rust/src/error.rs @@ -0,0 +1,21 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum CommandError { + #[error("the configuration is invalid")] + InvalidConfig(#[from] Box), + + #[error(transparent)] + Unknown(#[from] anyhow::Error), + // examples + // #[error("the data for key `{0}` is not available")] + // Redaction(String), + // #[error("invalid header (expected {expected:?}, found {found:?})")] + // InvalidHeader { expected: String, found: String }, +} + +impl From for CommandError { + fn from(error: figment::Error) -> Self { + CommandError::InvalidConfig(Box::new(error)) + } +} diff --git a/rust/src/main.rs b/rust/src/main.rs index e98ed26..1f7e9ec 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,4 +1,8 @@ use clap::Parser; +use figment::{ + Figment, + providers::{Env, Format, Json, Toml}, +}; use tracing::{Level, event}; mod args; @@ -6,10 +10,19 @@ use args::{ActionType, CommandArgs}; mod config; +mod error; +use error::CommandError; + #[tokio::main] -async fn main() { +async fn main() -> Result<(), CommandError> { let args = CommandArgs::parse(); + let config: config::CommandConfig = Figment::new() + .admerge(Json::file("config.json")) + .admerge(Toml::file("config.toml")) + .admerge(Env::prefixed("APP_")) + .extract()?; + match &args.action { ActionType::Serve(serve_args) => { tracing_subscriber::fmt() @@ -24,7 +37,11 @@ async fn main() { println!("{:#?}", args); - // println!("{:#?}", config); + println!("{:#?}", config); + + println!("{:#?}", config.port.ports); } } + + Ok(()) }