use serde_json::Value;
use crate::{json::JSON, lang::SError, Format, IntoNodeRef, SDoc, SGraph};
#[cfg(test)]
mod tests;
pub struct YAML;
impl YAML {
pub fn parse_new(yaml: &str) -> Result<SDoc, SError> {
Ok(SDoc::new(Self::parse(yaml)?))
}
pub fn parse(yaml: &str) -> Result<SGraph, SError> {
let res = serde_yaml::from_str::<Value>(yaml);
match res {
Ok(value) => {
Ok(JSON::from_value(value))
},
Err(error) => {
Err(SError::empty_fmt("yaml", &error.to_string()))
}
}
}
pub fn stringify(pid: &str, doc: &SDoc) -> Result<String, SError> {
if let Ok(value) = JSON::to_value(pid, doc) {
let res = serde_yaml::to_string(&value);
return match res {
Ok(value) => {
Ok(value)
},
Err(error) => {
Err(SError::fmt(pid, doc, "yaml", &error.to_string()))
}
};
}
Err(SError::fmt(pid, doc, "yaml", "could not stringify document"))
}
pub fn stringify_node(pid: &str, doc: &SDoc, node: impl IntoNodeRef) -> Result<String, SError> {
let res = serde_yaml::to_string(&JSON::to_node_value(&doc.graph, node));
match res {
Ok(value) => {
Ok(value)
},
Err(error) => {
Err(SError::fmt(pid, doc, "yaml", &error.to_string()))
}
}
}
}
impl Format for YAML {
fn format(&self) -> String {
"yaml".to_string()
}
fn content_type(&self) -> String {
"application/yaml".to_string()
}
fn header_import(&self, pid: &str, doc: &mut crate::SDoc, _content_type: &str, bytes: &mut bytes::Bytes, as_name: &str) -> Result<(), SError> {
let res = std::str::from_utf8(bytes.as_ref());
match res {
Ok(str) => {
self.string_import(pid, doc, str, as_name)
},
Err(error) => {
Err(SError::fmt(pid, &doc, "yaml", &error.to_string()))
}
}
}
fn string_import(&self, pid: &str, doc: &mut crate::SDoc, src: &str, as_name: &str) -> Result<(), SError> {
let mut graph = YAML::parse(src)?;
if as_name.len() > 0 && as_name != "root" {
let mut path = as_name.replace(".", "/");
if as_name.starts_with("self") || as_name.starts_with("super") {
if let Some(ptr) = doc.self_ptr(pid) {
path = format!("{}/{}", ptr.path(&doc.graph), path);
}
}
let mut loc_graph = SGraph::default();
let loc = loc_graph.ensure_nodes(&path, '/', true, None);
if let Some(main) = graph.main_root() {
if let Some(main) = main.node(&graph) {
loc_graph.absorb_external_node(&graph, main, &loc);
}
}
graph = loc_graph;
}
doc.graph.default_absorb_merge(graph)
}
fn file_import(&self, pid: &str, doc: &mut crate::SDoc, _format: &str, full_path: &str, _extension: &str, as_name: &str) -> Result<(), SError> {
let src = doc.fs_read_string(pid, full_path)?;
self.string_import(pid, doc, &src, as_name)
}
fn export_string(&self, pid: &str, doc: &crate::SDoc, node: Option<&crate::SNodeRef>) -> Result<String, SError> {
if node.is_some() {
YAML::stringify_node(pid, &doc, node)
} else {
YAML::stringify(pid, &doc)
}
}
}