From f206de5d49eda1900552a4b19f01c8c6985b7903 Mon Sep 17 00:00:00 2001 From: "Adam T. Carpenter" Date: Wed, 28 Apr 2021 19:58:27 -0400 Subject: finally committed to structopt arg parsing --- Cargo.toml | 8 +++--- src/config.rs | 48 +++++++++++++++++++++++++++++++++++ src/error.rs | 4 +++ src/main.rs | 72 +++++++++------------------------------------------- src/repo/mod.rs | 27 +++++++------------- src/routes/mod.rs | 4 +-- src/templates/mod.rs | 29 +++++++++++---------- 7 files changed, 95 insertions(+), 97 deletions(-) create mode 100644 src/config.rs diff --git a/Cargo.toml b/Cargo.toml index 13b4535..b625320 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,17 +2,19 @@ name = "twinh" version = "0.1.0" authors = ["Adam T. Carpenter "] +description = "Twin H-Power: A classic car parts catalog and cross-reference tool" edition = "2018" [dependencies] bincode = "1" env_logger = "0.8" handlebars = "3" -hyper = { version = "0.14", default-features = false, features = ["full"] } +hyper = { version = "0.14", default-features = false, features = ["server", "client", "http1", "http2"] } hyper-rustls = "0.22" log = "0.4" -once_cell = "1" +lazy_static = "1.4" serde = { version = "1", features = ["derive"]} serde_urlencoded = "0.7" sled = "0.34" -tokio = { version = "1", default-features = false, features = ["full"] } +structopt = { version = "0.3", default-features = false } +tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "macros", "signal"] } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..4dd4433 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,48 @@ +use std::{net::SocketAddrV4, path::PathBuf}; +use structopt::StructOpt; + +lazy_static! { + pub static ref INSTANCE: Config = Config::from_args(); +} + +#[derive(Debug, StructOpt)] +#[structopt(author, about)] +pub struct Config { + #[structopt( + name = "DIR", + required = true, + parse(from_str), + help = "The path to your data directory" + )] + pub data_dir: PathBuf, + + #[structopt( + name = "ADDR", + long = "bind-addr", + required = false, + default_value = "127.0.0.1:5353", + help = "Sets the IP address and port to bind to" + )] + pub bind_addr: SocketAddrV4, + + #[structopt( + long, + short, + multiple = true, + parse(from_occurrences), + help = "Increases log level" + )] + pub verbose: u8, + + #[structopt( + long, + help = "Creates a fresh data directory at DIR and exits; Fails if DIR exists" + )] + pub create_dir: bool, + + #[structopt(long, help = "Imports CSV car data into the data directory")] + pub import_cars: bool, + + #[structopt(long, help = "Imports CSV parts data into the data directory")] + pub import_parts: bool, +} diff --git a/src/error.rs b/src/error.rs index ef0ef1d..f987d66 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,6 +8,10 @@ use std::num::ParseIntError; #[derive(Debug)] pub struct TwinHError(pub String); +impl TwinHError { + fn bail(self) {} +} + impl std::error::Error for TwinHError {} impl std::fmt::Display for TwinHError { diff --git a/src/main.rs b/src/main.rs index 0c7766a..c6a1110 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,13 @@ use hyper::{ service::{make_service_fn, service_fn}, Server, }; -use std::{env, net::IpAddr, net::Ipv4Addr, net::SocketAddr}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use structopt::StructOpt; +#[macro_use] +extern crate lazy_static; + +mod config; mod error; mod import; mod models; @@ -14,57 +19,19 @@ mod templates; #[tokio::main] async fn main() -> Result<(), TwinHError> { - // print help if there are no arguments - let mut args = env::args().skip(1).peekable(); - if args.peek().is_none() { - print_help(); - return Ok(()); - } - - // set default bind addr - let mut bind_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 5353); - - // handle arguments and options - while let Some(arg) = args.next() { - match arg.as_str() { - "--create-db" => { - // create a fresh database and quit - repo::create_new_db()?; - return Ok(()); - } - "--import" => { - // import CSV data into database - let _source = args - .next() - .ok_or_else(|| TwinHError(String::from("import source not provided")))?; - todo!(); - } - "--addr" => { - bind_addr.set_ip(args.next().unwrap_or_default().parse()?); - } - "--port" => { - bind_addr.set_port(args.next().unwrap_or_default().parse()?); - } - _ => { - // if not the last argument (the database) then it's unknown - if args.peek().is_some() { - print_help(); - return Ok(()); - } - } - }; - } + //env_logger::try_init_from_env; - // create primary listener + // create HTTP listener let make_svc = make_service_fn(move |_conn| async { Ok::<_, TwinHError>(service_fn(routes::router)) }); - // bind server - let server = Server::bind(&bind_addr).serve(make_svc); + // bind server with signal + let server = Server::bind(&config::INSTANCE.bind_addr.into()).serve(make_svc); let graceful = server.with_graceful_shutdown(shutdown_signal()); - // start and run until signal + // start and run graceful.await?; + Ok(()) } @@ -74,18 +41,3 @@ async fn shutdown_signal() { .await .expect("failed to install CTRL+C signal handler"); } - -fn print_help() { - print!( - "twinh: a home-grown classic car parts catalog\n\ - \nUsage: twinh [options] \n\ - your database directory (e.g. /var/db/twinh)\n\ - \nOptions:\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; cannot exist yet\n\ - --import-cars imports CSV car data into the database\n\ - --import-parts imports CSV parts data into the database\n\ - " - ); -} diff --git a/src/repo/mod.rs b/src/repo/mod.rs index c7992c9..80b2814 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -1,32 +1,23 @@ +use crate::config; use crate::error::TwinHError; use crate::models::Car; use crate::models::Part; use bincode::deserialize; use constants::*; -use once_cell::sync::Lazy; use sled::{Config, Db}; -use std::env; mod constants; -pub static DB_PATH_INSTANCE: Lazy = Lazy::new(|| { - env::args() - .skip(1) - .last() - .expect("database directory not provided") -}); - -static REPO_INSTANCE: Lazy = - Lazy::new( - || match Config::default().path(DB_PATH_INSTANCE.as_str()).open() { - Err(e) => panic!("failed to open database: {}", e), - Ok(db) => db, - }, - ); +lazy_static! { + static ref REPO_INSTANCE: Db = match Config::default().path(&config::INSTANCE.data_dir).open() { + Err(e) => panic!("failed to open database: {}", e), + Ok(db) => db, + }; +} pub fn create_demo_db() -> Result<(), TwinHError> { let db = sled::Config::default() - .path(DB_PATH_INSTANCE.as_str()) + .path(&config::INSTANCE.data_dir) .create_new(true) .open()?; let cars_tree = db.open_tree(CARS_TREE)?; @@ -35,7 +26,7 @@ pub fn create_demo_db() -> Result<(), TwinHError> { pub fn create_new_db() -> Result<(), TwinHError> { sled::Config::default() - .path(DB_PATH_INSTANCE.as_str()) + .path(&config::INSTANCE.data_dir) .create_new(true) .open()?; Ok(()) diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 1866e49..be07aa0 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,5 +1,5 @@ use crate::error::TwinHError; -use crate::repo; +//use crate::repo; use crate::templates; use hyper::body::HttpBody as _; use hyper::Method; @@ -124,7 +124,7 @@ pub struct AccessToken { } async fn cars(req: Request) -> Result, TwinHError> { - let cars = repo::get_all_cars().unwrap(); + //let cars = repo::get_all_cars().unwrap(); todo!() } diff --git a/src/templates/mod.rs b/src/templates/mod.rs index 534ada0..8b8f156 100644 --- a/src/templates/mod.rs +++ b/src/templates/mod.rs @@ -1,16 +1,17 @@ use handlebars::Handlebars; -use once_cell::sync::Lazy; -pub static REGISTRY: Lazy = Lazy::new(|| { - let mut handlebars = Handlebars::new(); - handlebars - .register_template_string("index", include_str!("index.hbs")) - .unwrap(); - handlebars - .register_template_string("login", include_str!("login.hbs")) - .unwrap(); - handlebars - .register_template_string("base", include_str!("base.hbs")) - .unwrap(); - handlebars -}); +lazy_static! { + pub static ref REGISTRY: Handlebars<'static> = { + let mut handlebars = Handlebars::new(); + handlebars + .register_template_string("index", include_str!("index.hbs")) + .unwrap(); + handlebars + .register_template_string("login", include_str!("login.hbs")) + .unwrap(); + handlebars + .register_template_string("base", include_str!("base.hbs")) + .unwrap(); + handlebars + }; +} -- cgit v1.2.3