summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.rs56
-rw-r--r--src/error.rs15
-rw-r--r--src/import/mod.rs1
-rw-r--r--src/main.rs48
-rw-r--r--src/repo/mod.rs6
5 files changed, 100 insertions, 26 deletions
diff --git a/src/config.rs b/src/config.rs
index b3c9715..da65385 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,22 +1,54 @@
+use crate::TwinHError;
use once_cell::sync::Lazy;
-use std::{env::var, error::Error, net::SocketAddr};
+use std::{env, error::Error, net::IpAddr, net::Ipv4Addr, net::SocketAddr};
-pub static CONFIG_INSTANCE: Lazy<AppConfig> =
- Lazy::new(|| AppConfig::from_env().expect("Error loading config"));
+pub static CONFIG_INSTANCE: Lazy<Config> = Lazy::new(|| match Config::new() {
+ Ok(c) => c,
+ Err(e) => panic!("twinh: config error: {}", e),
+});
#[derive(Clone, Debug)]
-pub struct AppConfig {
- pub addr: SocketAddr,
- pub db_uri: String,
+pub struct Config {
+ pub bind_addr: SocketAddr,
+ pub db_path: String,
}
-impl AppConfig {
- pub fn from_env() -> Result<Self, Box<dyn Error>> {
- let new = Self {
- addr: var("TWINH_ADDR")?.parse()?,
- db_uri: var("TWINH_DB_URI")?,
+impl Default for Config {
+ fn default() -> Self {
+ Self {
+ bind_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 5353),
+ db_path: String::from("/var/db/twinh"),
+ }
+ }
+}
+
+impl Config {
+ fn new() -> Result<Self, Box<dyn Error>> {
+ let mut args = env::args().skip(1);
+
+ let db_path = args
+ .next()
+ .ok_or_else(|| TwinHError(String::from("database directory not provided")))?;
+
+ let mut config = Config {
+ bind_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 5353),
+ db_path,
};
- Ok(new)
+ while let Some(arg) = args.next() {
+ match arg.as_str() {
+ "--addr" => {
+ let addr = args.next().unwrap_or_default().parse()?;
+ config.bind_addr.set_ip(addr);
+ }
+ "--port" => {
+ let port = args.next().unwrap_or_default().parse()?;
+ config.bind_addr.set_port(port);
+ }
+ _ => {}
+ };
+ }
+
+ Ok(config)
}
}
diff --git a/src/error.rs b/src/error.rs
index 06d7d1e..943c3ec 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,25 +1,26 @@
use bincode::Error as bincode_e;
use sled::Error as sled_e;
+use std::fmt;
#[derive(Debug)]
-pub struct TwinHError;
+pub struct TwinHError(pub String);
impl std::error::Error for TwinHError {}
impl std::fmt::Display for TwinHError {
- fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
- todo!()
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ write!(f, "Twin H-Power: {}", self.0)
}
}
impl From<sled_e> for TwinHError {
- fn from(_: sled_e) -> Self {
- todo!()
+ fn from(e: sled_e) -> Self {
+ Self(format!("database error: {}", e))
}
}
impl From<bincode_e> for TwinHError {
- fn from(_: bincode_e) -> Self {
- todo!()
+ fn from(e: bincode_e) -> Self {
+ Self(format!("(de)serialization error: {}", e))
}
}
diff --git a/src/import/mod.rs b/src/import/mod.rs
new file mode 100644
index 0000000..bac9966
--- /dev/null
+++ b/src/import/mod.rs
@@ -0,0 +1 @@
+const test: i32 = 4;
diff --git a/src/main.rs b/src/main.rs
index 4a5a8b1..02fdc2e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,13 @@
-use crate::config::CONFIG_INSTANCE;
-use crate::error::TwinHError;
+use crate::{config::CONFIG_INSTANCE, error::TwinHError};
use hyper::{
service::{make_service_fn, service_fn},
Server,
};
+use std::env;
mod config;
mod error;
+mod import;
mod models;
mod repo;
mod routes;
@@ -14,14 +15,53 @@ mod templates;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
- let addr = CONFIG_INSTANCE.addr;
+ // handle non-config args
+ for arg in env::args().skip(1) {
+ match arg.as_str() {
+ "--create-db" => {
+ // create a fresh database and quit
+ repo::create_new_db()?;
+ return Ok(());
+ }
+ "--import" => {
+ // import CSV data into database
+ todo!();
+ }
+ "--help" | "-h" => {
+ // print help
+ print!(
+ "twinh: a home-grown classic car parts catalog\n\
+ \nUsage: twinh <dir> [options]\n\
+ <dir> your database directory (e.g. /var/db/twinh)\n\
+ \nOptions:\n\
+ --help | -h prints this message and exits\n\
+ --addr an ip address to bind to (e.g. 127.0.0.1)\n\
+ --port a port to bind to (e.g. 5353)\n\
+ --create-db creates a fresh empty database; <dir> cannot exist yet\n\
+ --import-cars imports CSV car data into the database\n\
+ --import-parts imports CSV parts data into the database\n\
+ "
+ );
+ return Ok(());
+ }
+ unknown => {
+ panic!("unknown option: {}", unknown);
+ }
+ };
+ }
+
+ // gather config
+ let bind_addr = CONFIG_INSTANCE.bind_addr;
+ // create primary listener
let make_svc =
make_service_fn(move |_conn| async { Ok::<_, TwinHError>(service_fn(routes::router)) });
- let server = Server::bind(&addr).serve(make_svc);
+ // bind server
+ let server = Server::bind(&bind_addr).serve(make_svc);
let graceful = server.with_graceful_shutdown(shutdown_signal());
+ // start and run until signal
if let Err(e) = graceful.await {
eprintln!("server error: {}", e);
}
diff --git a/src/repo/mod.rs b/src/repo/mod.rs
index f0bb95c..45e9ce3 100644
--- a/src/repo/mod.rs
+++ b/src/repo/mod.rs
@@ -11,7 +11,7 @@ mod constants;
static REPO_INSTANCE: Lazy<Db> = Lazy::new(|| {
Config::default()
- .path(&CONFIG_INSTANCE.db_uri)
+ .path(&CONFIG_INSTANCE.db_path)
.temporary(true)
.open()
.expect("Couldn't open DB!")
@@ -19,7 +19,7 @@ static REPO_INSTANCE: Lazy<Db> = Lazy::new(|| {
pub fn create_demo_db() -> Result<(), TwinHError> {
let db = sled::Config::default()
- .path(&CONFIG_INSTANCE.db_uri)
+ .path(&CONFIG_INSTANCE.db_path)
.create_new(true)
.open()?;
let cars_tree = db.open_tree(CARS_TREE)?;
@@ -28,7 +28,7 @@ pub fn create_demo_db() -> Result<(), TwinHError> {
pub fn create_new_db() -> Result<(), TwinHError> {
sled::Config::default()
- .path(&CONFIG_INSTANCE.db_uri)
+ .path(&CONFIG_INSTANCE.db_path)
.create_new(true)
.open()?;
Ok(())