use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataFormat {
Json,
Yaml,
Toml,
Xml,
}
impl FromStr for DataFormat {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"json" => Ok(DataFormat::Json),
"yaml" | "yml" => Ok(DataFormat::Yaml),
"toml" => Ok(DataFormat::Toml),
"xml" => Ok(DataFormat::Xml),
_ => Err(format!("Unsupported format: {}", s)),
}
}
}
pub fn convert(input: &str, from: DataFormat, to: DataFormat) -> Result<String, String> {
let value: serde_json::Value = match from {
DataFormat::Json => {
serde_json::from_str(input).map_err(|e| format!("JSON Parse Error: {}", e))?
}
DataFormat::Yaml => {
serde_yml::from_str(input).map_err(|e| format!("YAML Parse Error: {}", e))?
}
DataFormat::Toml => {
toml::from_str(input).map_err(|e| format!("TOML Parse Error: {}", e))?
}
DataFormat::Xml => {
quick_xml::de::from_str(input).map_err(|e| format!("XML Parse Error: {}", e))?
}
};
match to {
DataFormat::Json => {
let raw_json = serde_json::to_string(&value)
.map_err(|e| format!("JSON Serialize Error: {}", e))?;
match crate::parse(&raw_json) {
Ok(node) => Ok(crate::format(&node)),
Err(_) => Ok(raw_json), }
}
DataFormat::Yaml => {
serde_yml::to_string(&value).map_err(|e| format!("YAML Serialize Error: {}", e))
}
DataFormat::Toml => {
let toml_value = if value.is_array() {
let mut map = serde_json::Map::new();
map.insert("data".to_string(), value.clone());
serde_json::Value::Object(map)
} else {
value.clone()
};
toml::to_string_pretty(&toml_value).map_err(|e| format!("TOML Serialize Error: {}", e))
}
DataFormat::Xml => {
#[derive(serde::Serialize)]
struct XmlRoot<'a> {
#[serde(rename = "$value")]
value: &'a serde_json::Value,
}
quick_xml::se::to_string_with_root("root", &value)
.or_else(|_| quick_xml::se::to_string(&XmlRoot { value: &value }))
.map_err(|e| format!("XML Serialize Error: {}", e))
}
}
}