1pub mod import;
18use import::parse_object_value;
19
20pub mod export;
21use export::toml_value_from_node;
22use toml::{Table, Value};
23
24use crate::{lang::SError, Format, IntoNodeRef, SDoc, SGraph};
25
26
27pub struct TOML;
29impl TOML {
30 pub fn parse_new(toml: &str) -> Result<SDoc, SError> {
32 Ok(SDoc::new(Self::parse(toml)?))
33 }
34
35 pub fn parse(toml: &str) -> Result<SGraph, SError> {
37 if let Ok(value) = toml.parse::<Table>() {
38 let mut graph = SGraph::default();
39 let root = graph.insert_root("root");
40 parse_object_value(&mut graph, &root, Table::from(value));
41 Ok(graph)
42 } else {
43 Err(SError::empty_fmt("toml", "unable to parse TOML string into a table"))
44 }
45 }
46
47 pub fn stringify(pid: &str, doc: &SDoc) -> Result<String, SError> {
50 if let Some(main) = doc.graph.main_root() {
51 let value = toml_value_from_node(&doc.graph, &main);
52 if let Ok(toml) = toml::to_string(&Value::Table(value)) {
53 return Ok(toml);
54 }
55 return Err(SError::fmt(pid, doc, "toml", "could not parse toml::Value into a toml string"));
56 }
57 Err(SError::fmt(pid, doc, "toml", "did not find a main root to stringify"))
58 }
59
60 pub fn stringify_node(pid: &str, doc: &SDoc, node: impl IntoNodeRef) -> Result<String, SError> {
62 let value = toml_value_from_node(&doc.graph, &node.node_ref());
63 if let Ok(toml) = toml::to_string(&Value::Table(value)) {
64 return Ok(toml);
65 }
66 Err(SError::fmt(pid, doc, "toml", "could not parse toml::Value into a toml string"))
67 }
68}
69
70impl Format for TOML {
71 fn format(&self) -> String {
73 "toml".to_string()
74 }
75
76 fn content_type(&self) -> String {
78 "text/toml".to_string()
79 }
80
81 fn header_import(&self, pid: &str, doc: &mut crate::SDoc, _content_type: &str, bytes: &mut bytes::Bytes, as_name: &str) -> Result<(), SError> {
83 let res = std::str::from_utf8(bytes.as_ref());
84 match res {
85 Ok(str) => {
86 self.string_import(pid, doc, str, as_name)
87 },
88 Err(error) => {
89 Err(SError::fmt(pid, &doc, "toml", &error.to_string()))
90 }
91 }
92 }
93
94 fn string_import(&self, pid: &str, doc: &mut crate::SDoc, src: &str, as_name: &str) -> Result<(), SError> {
96 let mut graph = TOML::parse(src)?;
97 if as_name.len() > 0 && as_name != "root" {
98 let mut path = as_name.replace(".", "/");
99 if as_name.starts_with("self") || as_name.starts_with("super") {
100 if let Some(ptr) = doc.self_ptr(pid) {
101 path = format!("{}/{}", ptr.path(&doc.graph), path);
102 }
103 }
104
105 let mut loc_graph = SGraph::default();
107 let loc = loc_graph.ensure_nodes(&path, '/', true, None);
108 if let Some(main) = graph.main_root() {
109 if let Some(main) = main.node(&graph) {
110 loc_graph.absorb_external_node(&graph, main, &loc);
111 }
112 }
113 graph = loc_graph;
114 }
115 doc.graph.default_absorb_merge(graph)
116 }
117
118 fn file_import(&self, pid: &str, doc: &mut crate::SDoc, _format: &str, full_path: &str, _extension: &str, as_name: &str) -> Result<(), SError> {
120 let src = doc.fs_read_string(pid, full_path)?;
121 self.string_import(pid, doc, &src, as_name)
122 }
123
124 fn export_string(&self, pid: &str, doc: &crate::SDoc, node: Option<&crate::SNodeRef>) -> Result<String, SError> {
126 if node.is_some() {
127 TOML::stringify_node(pid, &doc, node)
128 } else {
129 TOML::stringify(pid, &doc)
130 }
131 }
132}