summaryrefslogtreecommitdiff
path: root/systems/_config
diff options
context:
space:
mode:
Diffstat (limited to 'systems/_config')
-rw-r--r--systems/_config/Cargo.toml4
-rw-r--r--systems/_config/src/error.rs19
-rw-r--r--systems/_config/src/lib.rs2
-rw-r--r--systems/_config/src/main.rs3
-rw-r--r--systems/_config/src/rw.rs66
5 files changed, 91 insertions, 3 deletions
diff --git a/systems/_config/Cargo.toml b/systems/_config/Cargo.toml
index afc1d81..11e08f3 100644
--- a/systems/_config/Cargo.toml
+++ b/systems/_config/Cargo.toml
@@ -5,3 +5,7 @@ version.workspace = true
[dependencies]
serde.workspace = true
+serde_json.workspace = true
+serde_yaml.workspace = true
+thiserror.workspace = true
+toml.workspace = true
diff --git a/systems/_config/src/error.rs b/systems/_config/src/error.rs
new file mode 100644
index 0000000..791aab2
--- /dev/null
+++ b/systems/_config/src/error.rs
@@ -0,0 +1,19 @@
+use std::path::PathBuf;
+
+#[derive(thiserror::Error, Debug)]
+pub enum ConfigError {
+ #[error("Failed to read config file: {0}")]
+ ConfigReadFailed(#[source] std::io::Error),
+
+ #[error("Failed to write config file: {0}")]
+ ConfigWriteFailed(#[source] std::io::Error),
+
+ #[error("Config file not found: {0}")]
+ FileNotFound(PathBuf),
+
+ #[error("IO error: {0}")]
+ Io(#[source] std::io::Error),
+
+ #[error("Other error: {0}")]
+ Other(String),
+}
diff --git a/systems/_config/src/lib.rs b/systems/_config/src/lib.rs
new file mode 100644
index 0000000..26fe31a
--- /dev/null
+++ b/systems/_config/src/lib.rs
@@ -0,0 +1,2 @@
+pub mod error;
+pub mod rw;
diff --git a/systems/_config/src/main.rs b/systems/_config/src/main.rs
deleted file mode 100644
index e7a11a9..0000000
--- a/systems/_config/src/main.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
- println!("Hello, world!");
-}
diff --git a/systems/_config/src/rw.rs b/systems/_config/src/rw.rs
new file mode 100644
index 0000000..36ea00c
--- /dev/null
+++ b/systems/_config/src/rw.rs
@@ -0,0 +1,66 @@
+use crate::error::ConfigError;
+use serde::{Deserialize, Serialize};
+use std::path::Path;
+
+pub async fn read_config<C>(path: impl AsRef<Path>) -> Result<C, ConfigError>
+where
+ C: for<'a> Deserialize<'a>,
+{
+ let path_ref = path.as_ref();
+ let ext = path_ref
+ .extension()
+ .and_then(|ext| ext.to_str())
+ .unwrap_or("json");
+ let format = ext_fmt(&ext.to_lowercase());
+
+ let content = std::fs::read_to_string(path_ref).map_err(ConfigError::ConfigReadFailed)?;
+
+ match format {
+ Format::Yaml => {
+ serde_yaml::from_str(&content).map_err(|e| ConfigError::Other(e.to_string()))
+ }
+ Format::Toml => toml::from_str(&content).map_err(|e| ConfigError::Other(e.to_string())),
+ Format::Json => {
+ serde_json::from_str(&content).map_err(|e| ConfigError::Other(e.to_string()))
+ }
+ }
+}
+
+pub async fn write_config<C>(path: impl AsRef<Path>, config: &C) -> Result<(), ConfigError>
+where
+ C: Serialize,
+{
+ let path_ref = path.as_ref();
+ let ext = path_ref
+ .extension()
+ .and_then(|ext| ext.to_str())
+ .unwrap_or("json");
+ let format = ext_fmt(&ext.to_lowercase());
+
+ let content = match format {
+ Format::Yaml => {
+ serde_yaml::to_string(config).map_err(|e| ConfigError::Other(e.to_string()))?
+ }
+ Format::Toml => toml::to_string(config).map_err(|e| ConfigError::Other(e.to_string()))?,
+ Format::Json => {
+ serde_json::to_string_pretty(config).map_err(|e| ConfigError::Other(e.to_string()))?
+ }
+ };
+
+ std::fs::write(path_ref, content).map_err(ConfigError::ConfigWriteFailed)
+}
+
+enum Format {
+ Yaml,
+ Toml,
+ Json,
+}
+
+fn ext_fmt(ext: &str) -> Format {
+ match ext {
+ "yaml" | "yml" => Format::Yaml,
+ "toml" | "tml" => Format::Toml,
+ "json" => Format::Json,
+ _ => Format::Json,
+ }
+}