config parsing

This commit is contained in:
s1idewhist1e 2023-05-04 00:58:15 -07:00
parent c8b7584fee
commit 993befbd9c
No known key found for this signature in database
GPG key ID: 9CC756BB9B325062
11 changed files with 657 additions and 5505 deletions

View file

@ -2,13 +2,134 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backend"
version = "0.0.0"
dependencies = [
"once_cell",
"serde",
"serde_yaml",
"server",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "proc-macro2"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "queue"
version = "0.1.0"
[[package]]
name = "quote"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "serde"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.160"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yaml"
version = "0.9.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "server"
version = "0.1.0"
[[package]]
name = "syn"
version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "unsafe-libyaml"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"

View file

@ -11,6 +11,9 @@ members = ["crates/*"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
once_cell = "1.17.1"
serde = { version = "1.0.160", features = [ "derive" ] }
serde_yaml = "0.9.21"
server = { path = "crates/server" }
[dev-dependencies]

View file

@ -0,0 +1,8 @@
[package]
name = "queue"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -0,0 +1,14 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

View file

@ -1,15 +1,15 @@
pub fn add(left: usize, right: usize) -> usize {
todo!();
left + right
todo!();
left + right
}
#[cfg(test)]
mod tests {
use super::*;
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

View file

@ -1 +0,0 @@
tab_spaces = 2

View file

@ -1,4 +1,3 @@
fn main() {
todo!();
todo!();
}

View file

@ -0,0 +1,131 @@
use std::fmt::Display;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;
use once_cell::sync::OnceCell;
mod cfg;
pub use cfg::*;
// Config Errors
#[derive(Debug)]
pub enum Error {
Uninitialized,
Deserialize(serde_yaml::Error),
FileError(io::Error),
}
macro_rules! generate_error_impl {
($t:ident, $o:ty) => {
impl From<$o> for Error {
fn from(value: $o) -> Self {
Self::$t(value)
}
}
};
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Error::*;
f.write_str(&{
match self {
Uninitialized => {
format!("The configuration has not been initialized yet: {:?}", self)
}
Deserialize(e) => format!("Error when parsing config file: {}", e),
FileError(e) => format!("Error when reading config file: {}", e),
}
})
}
}
generate_error_impl!(FileError, io::Error);
generate_error_impl!(Deserialize, serde_yaml::Error);
impl std::error::Error for Error {}
// Functions
fn fetch_config(path: &Path) -> Result<Config, Error> {
let mut buf = String::new();
File::open(path)?.read_to_string(&mut buf)?;
Ok(serde_yaml::from_str(&buf)?)
}
static CONFIG: OnceCell<Config> = OnceCell::new();
pub fn init_config(cfg_path: &Path) -> Result<(), Error> {
let config = fetch_config(cfg_path)?;
CONFIG.get_or_init(move || config);
Ok(())
}
pub fn get_config() -> Result<&'static Config, Error> {
CONFIG.get().ok_or(Error::Uninitialized)
}
#[cfg(test)]
mod tests {
use std::{
fs::{remove_file, File},
io::Write,
path::PathBuf,
};
struct Guard(PathBuf);
impl Drop for Guard {
fn drop(&mut self) {
println!("removing temp file...");
match remove_file(&self.0) {
Ok(_) => println!("Successfully removed file"),
Err(e) => println!("Could not remove file: {}", e),
}
}
}
use super::*;
#[test]
fn errors_on_invalid_path() {
assert!(init_config(Path::new("./invalid/path/does/not/exist")).is_err());
}
#[test]
fn parses_test_config() {
// setup test temp config
let mut temp_file = std::env::temp_dir();
temp_file.push(Path::new("calckey.test.config"));
let err = File::create(&temp_file).unwrap().write_all(br"");
let _g = Guard(temp_file.clone());
err.unwrap();
let config = fetch_config(temp_file.as_path()).unwrap();
assert_eq!(
config,
Config {
url: String::from("https://example.tld/"),
port: 3000,
db: db::DbConfig {
host: String::from("localhost"),
port: 5432,
db: String::from("calckey"),
user: String::from("example-calckey-user"),
pass: String::from("example-calckey-pass"),
disable_cache: true,
extra: db::Extra { extra: true }
}
}
);
remove_file(&temp_file).unwrap();
}
}

View file

@ -0,0 +1,35 @@
use serde::Deserialize;
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename = "camelCase")]
pub struct Config {
pub url: String,
pub port: u16,
pub db: db::DbConfig,
}
pub mod db {
use super::*;
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename = "camelCase")]
pub struct DbConfig {
pub host: String,
pub port: u16,
pub db: String,
pub user: String,
pub pass: String,
#[serde(default = "true_fn")]
pub disable_cache: bool,
pub extra: Extra,
}
#[derive(Debug, PartialEq, Deserialize)]
pub struct Extra {
#[serde(default = "true_fn")]
pub extra: bool,
}
}
fn true_fn() -> bool {
true
}

View file

@ -1,5 +1,9 @@
mod config;
fn main() {
// bootstrap
// ENV
// get config
}

File diff suppressed because it is too large Load diff