use std::path::Path;
use serde::de::DeserializeOwned;
use crate::config::Config;
use crate::error::ConfigError;
impl<C> Config<C>
where
C: DeserializeOwned + serde::Serialize + schemars::JsonSchema + Send + Sync + 'static,
{
#[must_use]
pub fn schema() -> serde_json::Value {
let mut generator = schemars::SchemaGenerator::default();
let schema = generator.root_schema_for::<C>();
serde_json::to_value(schema).unwrap_or(serde_json::Value::Null)
}
pub fn write(&self, path: &Path) -> Result<(), ConfigError> {
let value = self.get();
let format = WriteFormat::from_path(path);
let serialised = match format {
WriteFormat::Yaml => serde_yaml::to_string(&*value)
.map_err(|e| ConfigError::Write(format!("yaml: {e}")))?,
WriteFormat::Toml => toml::to_string_pretty(&*value)
.map_err(|e| ConfigError::Write(format!("toml: {e}")))?,
WriteFormat::Json => serde_json::to_string_pretty(&*value)
.map_err(|e| ConfigError::Write(format!("json: {e}")))?,
};
if let Some(parent) = path.parent() {
if !parent.as_os_str().is_empty() {
std::fs::create_dir_all(parent).map_err(|e| {
ConfigError::Write(format!("create parent {}: {e}", parent.display()))
})?;
}
}
std::fs::write(path, serialised)
.map_err(|e| ConfigError::Write(format!("{}: {e}", path.display())))?;
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum WriteFormat {
Yaml,
Toml,
Json,
}
impl WriteFormat {
fn from_path(path: &Path) -> Self {
match path.extension().and_then(|e| e.to_str()) {
Some("toml") => Self::Toml,
Some("json") => Self::Json,
_ => Self::Yaml,
}
}
}
#[cfg(test)]
mod format_tests {
use std::path::Path;
use super::WriteFormat;
#[test]
fn extension_picks_format() {
assert_eq!(WriteFormat::from_path(Path::new("c.yaml")), WriteFormat::Yaml);
assert_eq!(WriteFormat::from_path(Path::new("c.yml")), WriteFormat::Yaml);
assert_eq!(WriteFormat::from_path(Path::new("c.toml")), WriteFormat::Toml);
assert_eq!(WriteFormat::from_path(Path::new("c.json")), WriteFormat::Json);
assert_eq!(WriteFormat::from_path(Path::new("c")), WriteFormat::Yaml);
assert_eq!(WriteFormat::from_path(Path::new("c.txt")), WriteFormat::Yaml);
}
}