use serde::de::value::Error as ValueError;
use serde::Serialize;
use crate::content::{json, yaml, Content, ContentSerializer};
use crate::settings::Settings;
pub enum SerializationFormat {
#[cfg(feature = "csv")]
Csv,
#[cfg(feature = "ron")]
Ron,
#[cfg(feature = "toml")]
Toml,
Yaml,
Json,
JsonCompact,
}
pub enum SnapshotLocation {
Inline,
File,
}
pub fn serialize_content(
mut content: Content,
format: SerializationFormat,
location: SnapshotLocation,
) -> String {
content = Settings::with(|settings| {
if settings.sort_maps() {
content.sort_maps();
}
#[cfg(feature = "redactions")]
{
for (selector, redaction) in settings.iter_redactions() {
content = selector.redact(content, redaction);
}
}
content
});
match format {
SerializationFormat::Yaml => {
let serialized = yaml::to_string(&content);
match location {
SnapshotLocation::Inline => serialized,
SnapshotLocation::File => serialized[4..].to_string(),
}
}
SerializationFormat::Json => json::to_string_pretty(&content),
SerializationFormat::JsonCompact => json::to_string_compact(&content),
#[cfg(feature = "csv")]
SerializationFormat::Csv => {
let mut buf = Vec::with_capacity(128);
{
let mut writer = dep_csv::Writer::from_writer(&mut buf);
if let Some(content_slice) = content.as_slice() {
for content in content_slice {
writer.serialize(content).unwrap();
}
} else {
writer.serialize(&content).unwrap();
}
writer.flush().unwrap();
}
if buf.ends_with(b"\n") {
buf.truncate(buf.len() - 1);
}
String::from_utf8(buf).unwrap()
}
#[cfg(feature = "ron")]
SerializationFormat::Ron => {
let mut buf = Vec::new();
let mut config = dep_ron::ser::PrettyConfig::new();
config.new_line = "\n".to_string();
config.indentor = " ".to_string();
config.struct_names = true;
let mut serializer = dep_ron::ser::Serializer::with_options(
&mut buf,
Some(config),
dep_ron::options::Options::default(),
)
.unwrap();
content.serialize(&mut serializer).unwrap();
String::from_utf8(buf).unwrap()
}
#[cfg(feature = "toml")]
SerializationFormat::Toml => {
let mut rv = dep_toml::to_string_pretty(&content).unwrap();
if rv.ends_with('\n') {
rv.truncate(rv.len() - 1);
}
rv
}
}
}
pub fn serialize_value<S: Serialize>(
s: &S,
format: SerializationFormat,
location: SnapshotLocation,
) -> String {
let serializer = ContentSerializer::<ValueError>::new();
let content = Serialize::serialize(s, serializer).unwrap();
serialize_content(content, format, location)
}
#[cfg(feature = "redactions")]
pub fn serialize_value_redacted<S: Serialize>(
s: &S,
redactions: &[(crate::redaction::Selector, crate::redaction::Redaction)],
format: SerializationFormat,
location: SnapshotLocation,
) -> String {
let serializer = ContentSerializer::<ValueError>::new();
let mut content = Serialize::serialize(s, serializer).unwrap();
for (selector, redaction) in redactions {
content = selector.redact(content, redaction);
}
serialize_content(content, format, location)
}
#[test]
fn test_yaml_serialization() {
let yaml = serialize_content(
Content::Map(vec![
(
Content::from("env"),
Content::Seq(vec![
Content::from("ENVIRONMENT"),
Content::from("production"),
]),
),
(
Content::from("cmdline"),
Content::Seq(vec![Content::from("my-tool"), Content::from("run")]),
),
]),
SerializationFormat::Yaml,
SnapshotLocation::File,
);
crate::assert_snapshot!(&yaml, @r###"
env:
- ENVIRONMENT
- production
cmdline:
- my-tool
- run
"###);
let inline_yaml = serialize_content(
Content::Map(vec![
(
Content::from("env"),
Content::Seq(vec![
Content::from("ENVIRONMENT"),
Content::from("production"),
]),
),
(
Content::from("cmdline"),
Content::Seq(vec![Content::from("my-tool"), Content::from("run")]),
),
]),
SerializationFormat::Yaml,
SnapshotLocation::Inline,
);
crate::assert_snapshot!(&inline_yaml, @r###"
---
env:
- ENVIRONMENT
- production
cmdline:
- my-tool
- run
"###);
}