use std::path::Path;
use serde::de::DeserializeOwned;
use crate::error::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Format {
Json,
Yaml,
Toml,
}
impl Format {
pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
match path.extension().and_then(|ext| ext.to_str()) {
Some(ext) if ext.eq_ignore_ascii_case("json") => Ok(Self::Json),
Some(ext) if ext.eq_ignore_ascii_case("yaml") || ext.eq_ignore_ascii_case("yml") => {
Ok(Self::Yaml)
}
Some(ext) if ext.eq_ignore_ascii_case("toml") => Ok(Self::Toml),
_ => Err(Error::UnknownFormat {
path: path.to_path_buf(),
}),
}
}
pub const fn name(self) -> &'static str {
match self {
Self::Json => "json",
Self::Yaml => "yaml",
Self::Toml => "toml",
}
}
pub(crate) fn parse<T>(self, path: &Path, content: &str) -> Result<T>
where
T: DeserializeOwned,
{
match self {
Self::Json => serde_json::from_str(content).map_err(|source| Error::Parse {
path: path.to_path_buf(),
format: self.name(),
source: Box::new(source),
}),
Self::Yaml => serde_yaml::from_str(content).map_err(|source| Error::Parse {
path: path.to_path_buf(),
format: self.name(),
source: Box::new(source),
}),
Self::Toml => toml::from_str(content).map_err(|source| Error::Parse {
path: path.to_path_buf(),
format: self.name(),
source: Box::new(source),
}),
}
}
}
impl std::fmt::Display for Format {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(self.name())
}
}