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