mirror of
https://github.com/sergi0g/cup.git
synced 2025-11-17 01:23:39 -05:00
Switch to serde for config parsing
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -357,6 +357,8 @@ dependencies = [
|
|||||||
"reqwest-middleware",
|
"reqwest-middleware",
|
||||||
"reqwest-retry",
|
"reqwest-retry",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"termsize",
|
"termsize",
|
||||||
"tokio",
|
"tokio",
|
||||||
"xitca-web",
|
"xitca-web",
|
||||||
@@ -1172,9 +1174,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -1473,18 +1475,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.210"
|
version = "1.0.215"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.210"
|
version = "1.0.215"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1493,9 +1495,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.128"
|
version = "1.0.133"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -1623,9 +1625,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.68"
|
version = "2.0.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ reqwest-middleware = "0.3.3"
|
|||||||
rustc-hash = "2.0.0"
|
rustc-hash = "2.0.0"
|
||||||
http-link = "1.0.1"
|
http-link = "1.0.1"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
|
serde_json = "1.0.133"
|
||||||
|
serde = "1.0.215"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["server", "cli"]
|
default = ["server", "cli"]
|
||||||
|
|||||||
106
src/config.rs
106
src/config.rs
@@ -1,23 +1,35 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
const VALID_KEYS: [&str; 4] = ["authentication", "theme", "insecure_registries", "socket"];
|
#[derive(Clone, Deserialize)]
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
|
#[serde(rename = "default")]
|
||||||
Default,
|
Default,
|
||||||
|
#[serde(rename = "blue")]
|
||||||
Blue,
|
Blue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(default = "FxHashMap::default")]
|
||||||
pub authentication: FxHashMap<String, String>,
|
pub authentication: FxHashMap<String, String>,
|
||||||
|
#[serde(default = "Theme::default")]
|
||||||
pub theme: Theme,
|
pub theme: Theme,
|
||||||
|
#[serde(default = "Vec::default")]
|
||||||
pub insecure_registries: Vec<String>,
|
pub insecure_registries: Vec<String>,
|
||||||
pub socket: Option<String>,
|
pub socket: Option<String>,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +49,7 @@ impl Config {
|
|||||||
pub fn load(&self, path: Option<PathBuf>) -> Self {
|
pub fn load(&self, path: Option<PathBuf>) -> Self {
|
||||||
let raw_config = match &path {
|
let raw_config = match &path {
|
||||||
Some(path) => std::fs::read_to_string(path),
|
Some(path) => std::fs::read_to_string(path),
|
||||||
None => Ok(String::from("{}")), // Empty config
|
None => return Self::new(), // Empty config
|
||||||
};
|
};
|
||||||
if raw_config.is_err() {
|
if raw_config.is_err() {
|
||||||
error!(
|
error!(
|
||||||
@@ -47,87 +59,11 @@ impl Config {
|
|||||||
};
|
};
|
||||||
self.parse(&raw_config.unwrap()) // We can safely unwrap here
|
self.parse(&raw_config.unwrap()) // We can safely unwrap here
|
||||||
}
|
}
|
||||||
/// Parses and validates the config. The process is quite manual and I would rather use a library, but I don't want to grow the dependency tree, for a config as simple as this one.
|
/// Parses and validates the config.
|
||||||
/// Many of these checks are stupid, but we either validate the config properly, or we don't at all, so... this is the result. I _am not_ proud of this code.
|
|
||||||
pub fn parse(&self, raw_config: &str) -> Self {
|
pub fn parse(&self, raw_config: &str) -> Self {
|
||||||
let json = match json::parse(raw_config) {
|
match serde_json::from_str(raw_config) {
|
||||||
Ok(v) => v,
|
Ok(config) => config,
|
||||||
Err(e) => error!("Failed to parse config!\n{}", e),
|
Err(e) => error!("Unexpected error occured while parsing config: {}", e),
|
||||||
};
|
|
||||||
// In the code, raw_<key> means the JsonValue from the parsed config, before it's validated.
|
|
||||||
|
|
||||||
// Authentication
|
|
||||||
let raw_authentication = &json["authentication"];
|
|
||||||
if !raw_authentication.is_null() && !raw_authentication.is_object() {
|
|
||||||
error!("Config key `authentication` must be an object!");
|
|
||||||
}
|
|
||||||
let mut authentication: FxHashMap<String, String> = FxHashMap::default();
|
|
||||||
raw_authentication.entries().for_each(|(registry, key)| {
|
|
||||||
if !key.is_string() {
|
|
||||||
error!("Config key `authentication.{}` must be a string!", registry);
|
|
||||||
}
|
|
||||||
authentication.insert(registry.to_string(), key.to_string());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Theme
|
|
||||||
let raw_theme = &json["theme"];
|
|
||||||
if !raw_theme.is_null() && !raw_theme.is_string() {
|
|
||||||
error!("Config key `theme` must be a string!");
|
|
||||||
}
|
|
||||||
let theme: Theme = {
|
|
||||||
if raw_theme.is_null() {
|
|
||||||
Theme::Default
|
|
||||||
} else {
|
|
||||||
match raw_theme.as_str().unwrap() {
|
|
||||||
"default" => Theme::Default,
|
|
||||||
"blue" => Theme::Blue,
|
|
||||||
_ => {
|
|
||||||
error!("Config key `theme` must be one of: `default`, `blue`!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insecure registries
|
|
||||||
let raw_insecure_registries = &json["insecure_registries"];
|
|
||||||
if !raw_insecure_registries.is_null() && !raw_insecure_registries.is_array() {
|
|
||||||
error!("Config key `insecure_registries` must be an array!");
|
|
||||||
}
|
|
||||||
let insecure_registries: Vec<String> = raw_insecure_registries
|
|
||||||
.members()
|
|
||||||
.map(|registry| {
|
|
||||||
if !registry.is_string() {
|
|
||||||
error!("Config key `insecure_registries` must only consist of strings!");
|
|
||||||
} else {
|
|
||||||
registry.as_str().unwrap().to_owned()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Socket
|
|
||||||
let raw_socket = &json["socket"];
|
|
||||||
if !raw_socket.is_null() && !raw_socket.is_string() {
|
|
||||||
error!("Config key `socket` must be a string!");
|
|
||||||
}
|
|
||||||
let socket: Option<String> = if raw_socket.is_null() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(raw_socket.to_string())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for extra keys
|
|
||||||
json.entries().for_each(|(key, _)| {
|
|
||||||
if !VALID_KEYS.contains(&key) {
|
|
||||||
error!("Invalid key `{}`", key)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
|
||||||
authentication,
|
|
||||||
theme,
|
|
||||||
insecure_registries,
|
|
||||||
socket,
|
|
||||||
debug: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user