initial project setup

This commit is contained in:
D. Scott Boggs 2023-06-06 10:27:02 -04:00
commit 75b57539d9
9 changed files with 2366 additions and 0 deletions

60
src/db/mod.rs Normal file
View file

@ -0,0 +1,60 @@
use std::{
default::default,
env,
ffi::{OsStr, OsString},
fs::File,
io::Read,
};
// from https://doc.rust-lang.org/std/ffi/struct.OsString.html
fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
ret.push(a); // This will not allocate further
ret.push(b); // This will not allocate further
ret
}
/// Check for an environment variable named for the given key with _FILE
/// appended to the end. If that exists, return the contents of the file, or
/// panic if it doesn't exist. If the `"${key}_FILE"` environment variable is
/// not set, return the value of the environment variable set by the given key,
/// or `None` if it's not set.
///
/// Panics:
/// - if the given file variable doesn't exist
/// - if there's an error reading the specified file
/// - if the environment variable string contains invalid unicode.
fn get_env_var_or_file<A: AsRef<OsStr>>(key: A) -> Option<String> {
let key = key.as_ref();
let file_key = concat_os_strings(key, "_FILE".as_ref());
if let Some(path) = env::var_os(file_key) {
// open the file and read it
let mut file = File::open(&path).unwrap_or_else(|_| panic!("no such file at {path:?}"));
let mut val: String = default();
file.read_to_string(&mut val)
.unwrap_or_else(|_| panic!("reading file at {path:?}"));
Some(val)
} else {
env::var_os(key).map(|val| {
val.to_str()
.expect(&format!("value for ${key:?} contains invalid unicode"))
.to_string()
})
}
}
/// Connect to the database using environment variables for configuration.
/// Panics on any failure.
pub(crate) fn connection_url() -> String {
let user = get_env_var_or_file("POSTGRES_USER").expect("$POSTGRES_USER");
let password = get_env_var_or_file("POSTGRES_PASSWORD").expect("$POSTGRES_PASSWORD");
let db = get_env_var_or_file("POSTGRES_DB").expect("$POSTGRES_DB");
let host = get_env_var_or_file("POSTGRES_HOST").unwrap_or_else(|| "localhost".into());
let port = get_env_var_or_file("POSTGRES_PORT")
.map(|port| {
port.parse::<u16>()
.expect("$POSTGRES_PORT is not a valid port number")
})
.unwrap_or(5432_u16);
format!("postgres://{user}:{password}@{host}:{port}/{db}")
}

11
src/error.rs Normal file
View file

@ -0,0 +1,11 @@
use derive_builder::UninitializedFieldError;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Builder(#[from] UninitializedFieldError),
#[error(transparent)]
SeaOrm(#[from] sea_orm::DbErr),
}
pub type Result<T> = std::result::Result<T, Error>;

11
src/main.rs Normal file
View file

@ -0,0 +1,11 @@
#![feature(default_free_fn)]
mod db;
mod error;
use error::Result;
use sea_orm::Database;
#[tokio::main]
async fn main() -> Result<()> {
let db = Database::connect(db::connection_url()).await?;
Ok(println!("Hello, world! {db:?}"))
}