1 use serde::de::value::Error as ValueError;
2 use serde::Serialize;
3
4 use crate::content::{Content, ContentSerializer};
5 use crate::settings::Settings;
6
7 pub enum SerializationFormat {
8 #[cfg(feature = "csv")]
9 Csv,
10 #[cfg(feature = "ron")]
11 Ron,
12 #[cfg(feature = "toml")]
13 Toml,
14 Yaml,
15 Json,
16 }
17
18 pub enum SnapshotLocation {
19 Inline,
20 File,
21 }
22
serialize_content( mut content: Content, format: SerializationFormat, location: SnapshotLocation, ) -> String23 pub fn serialize_content(
24 mut content: Content,
25 format: SerializationFormat,
26 location: SnapshotLocation,
27 ) -> String {
28 content = Settings::with(|settings| {
29 if settings.sort_maps() {
30 content.sort_maps();
31 }
32 #[cfg(feature = "redactions")]
33 {
34 for (selector, redaction) in settings.iter_redactions() {
35 content = selector.redact(content, redaction);
36 }
37 }
38 content
39 });
40
41 match format {
42 SerializationFormat::Yaml => {
43 let serialized = serde_yaml::to_string(&content).unwrap();
44 match location {
45 SnapshotLocation::Inline => serialized,
46 SnapshotLocation::File => serialized[4..].to_string(),
47 }
48 }
49 SerializationFormat::Json => serde_json::to_string_pretty(&content).unwrap(),
50 #[cfg(feature = "csv")]
51 SerializationFormat::Csv => {
52 let mut buf = Vec::with_capacity(128);
53 {
54 let mut writer = csv::Writer::from_writer(&mut buf);
55 // if the top-level content we're serializing is a vector we
56 // want to serialize it multiple times once for each item.
57 if let Some(content_slice) = content.as_slice() {
58 for content in content_slice {
59 writer.serialize(content).unwrap();
60 }
61 } else {
62 writer.serialize(&content).unwrap();
63 }
64 writer.flush().unwrap();
65 }
66 if buf.ends_with(b"\n") {
67 buf.truncate(buf.len() - 1);
68 }
69 String::from_utf8(buf).unwrap()
70 }
71 #[cfg(feature = "ron")]
72 SerializationFormat::Ron => {
73 let mut buf = Vec::new();
74 let mut config = ron::ser::PrettyConfig::new();
75 config.new_line = "\n".to_string();
76 config.indentor = " ".to_string();
77 let mut serializer = ron::ser::Serializer::new(&mut buf, Some(config), true).unwrap();
78 content.serialize(&mut serializer).unwrap();
79 String::from_utf8(buf).unwrap()
80 }
81 #[cfg(feature = "toml")]
82 SerializationFormat::Toml => {
83 let mut rv = toml::to_string_pretty(&content).unwrap();
84 if rv.ends_with('\n') {
85 rv.truncate(rv.len() - 1);
86 }
87 rv
88 }
89 }
90 }
91
serialize_value<S: Serialize>( s: &S, format: SerializationFormat, location: SnapshotLocation, ) -> String92 pub fn serialize_value<S: Serialize>(
93 s: &S,
94 format: SerializationFormat,
95 location: SnapshotLocation,
96 ) -> String {
97 let serializer = ContentSerializer::<ValueError>::new();
98 let content = Serialize::serialize(s, serializer).unwrap();
99 serialize_content(content, format, location)
100 }
101
102 #[cfg(feature = "redactions")]
serialize_value_redacted<S: Serialize>( s: &S, redactions: &[(crate::redaction::Selector, crate::redaction::Redaction)], format: SerializationFormat, location: SnapshotLocation, ) -> String103 pub fn serialize_value_redacted<S: Serialize>(
104 s: &S,
105 redactions: &[(crate::redaction::Selector, crate::redaction::Redaction)],
106 format: SerializationFormat,
107 location: SnapshotLocation,
108 ) -> String {
109 let serializer = ContentSerializer::<ValueError>::new();
110 let mut content = Serialize::serialize(s, serializer).unwrap();
111 for (selector, redaction) in redactions {
112 content = selector.redact(content, &redaction);
113 }
114 serialize_content(content, format, location)
115 }
116