use crate::document::Document;
use crate::helper::string::DisplayOnlyForDebugging;
use crate::Metadata;
use crate::{DataResult, DataSet};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::io;
const DEFAULT_SUBTYPE: &str = "toml";
const DEFAULT_TERMINATOR: &str = "---";
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
#[serde(default, deny_unknown_fields)]
pub struct Toml {
#[serde(rename = "metadata")]
#[serde(alias = "meta")]
pub metadata: Metadata,
}
impl Default for Toml {
fn default() -> Self {
let metadata = Metadata {
terminator: Some(DEFAULT_TERMINATOR.to_string()),
mime_type: Some(mime::APPLICATION.to_string()),
mime_subtype: Some(DEFAULT_SUBTYPE.to_string()),
charset: Some(mime::UTF_8.to_string()),
..Default::default()
};
Toml { metadata }
}
}
impl Document for Toml {
fn set_metadata(&mut self, metadata: Metadata) {
self.metadata = metadata.clone();
}
fn metadata(&self) -> Metadata {
Toml::default().metadata.merge(&self.metadata)
}
#[instrument(skip(buffer), name = "toml::read")]
fn read(&self, buffer: &[u8]) -> io::Result<DataSet> {
let str_buffer = std::str::from_utf8(buffer)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let record: Value = toml::from_str(str_buffer)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(match record {
Value::Array(records) => records
.into_iter()
.map(|record| {
trace!(
record = record.display_only_for_debugging(),
"Record deserialized"
);
DataResult::Ok(record)
})
.collect(),
record => {
trace!(
record = record.display_only_for_debugging(),
"Record deserialized"
);
vec![DataResult::Ok(record)]
}
})
}
#[instrument(skip(dataset), name = "toml::write")]
fn write(&self, dataset: &DataSet) -> io::Result<Vec<u8>> {
let mut buffer = Vec::default();
for data in dataset {
let record = data.to_value();
let toml = toml::to_string(&record)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
trace!(
record = record.display_only_for_debugging(),
"Record serialized"
);
buffer.append(&mut toml.as_bytes().to_vec());
}
Ok(buffer)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read() {
let document = Toml::default();
let buffer = r#"[Title]
key_1 = "value_1"
key_2 = "value_2"
"#
.as_bytes()
.to_vec();
let mut dataset = document.read(&buffer).unwrap().into_iter();
let data = dataset.next().unwrap().to_value();
let expected_data: Value =
serde_json::from_str(r#"{"Title":{"key_1":"value_1","key_2":"value_2"}}"#).unwrap();
assert_eq!(expected_data, data);
}
#[test]
fn write() {
let document = Toml::default();
let dataset = vec![DataResult::Ok(
serde_json::from_str(r#"{"column_1":"line_1"}"#).unwrap(),
)];
let buffer = document.write(&dataset).unwrap();
assert_eq!(
r#"column_1 = "line_1"
"#
.as_bytes()
.to_vec(),
buffer
);
let dataset = vec![DataResult::Ok(
serde_json::from_str(r#"{"column_1":"line_2"}"#).unwrap(),
)];
let buffer = document.write(&dataset).unwrap();
assert_eq!(
r#"column_1 = "line_2"
"#
.as_bytes()
.to_vec(),
buffer
);
}
}