insta/
serialization.rs
1use serde::de::value::Error as ValueError;
2use serde::Serialize;
3
4use crate::content::{json, yaml, Content, ContentSerializer};
5use crate::settings::Settings;
6
7pub 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 JsonCompact,
17}
18
19#[derive(Debug)]
20pub enum SnapshotLocation {
21 Inline,
22 File,
23}
24
25pub fn serialize_content(mut content: Content, format: SerializationFormat) -> String {
26 content = Settings::with(|settings| {
27 if settings.sort_maps() {
28 content.sort_maps();
29 }
30 #[cfg(feature = "redactions")]
31 {
32 for (selector, redaction) in settings.iter_redactions() {
33 content = selector.redact(content, redaction);
34 }
35 }
36 content
37 });
38
39 match format {
40 SerializationFormat::Yaml => yaml::to_string(&content)[4..].to_string(),
41 SerializationFormat::Json => json::to_string_pretty(&content),
42 SerializationFormat::JsonCompact => json::to_string_compact(&content),
43 #[cfg(feature = "csv")]
44 SerializationFormat::Csv => {
45 let mut buf = Vec::with_capacity(128);
46 {
47 let mut writer = csv::Writer::from_writer(&mut buf);
48 if let Some(content_slice) = content.as_slice() {
51 for content in content_slice {
52 writer.serialize(content).unwrap();
53 }
54 } else {
55 writer.serialize(&content).unwrap();
56 }
57 writer.flush().unwrap();
58 }
59 if buf.ends_with(b"\n") {
60 buf.truncate(buf.len() - 1);
61 }
62 String::from_utf8(buf).unwrap()
63 }
64 #[cfg(feature = "ron")]
65 SerializationFormat::Ron => {
66 let mut buf = Vec::new();
67 let mut config = ron::ser::PrettyConfig::new();
68 config.new_line = "\n".to_string();
69 config.indentor = " ".to_string();
70 config.struct_names = true;
71 let mut serializer = ron::ser::Serializer::with_options(
72 &mut buf,
73 Some(config),
74 ron::options::Options::default(),
75 )
76 .unwrap();
77 content.serialize(&mut serializer).unwrap();
78 String::from_utf8(buf).unwrap()
79 }
80 #[cfg(feature = "toml")]
81 SerializationFormat::Toml => {
82 let mut rv = toml::to_string_pretty(&content).unwrap();
83 if rv.ends_with('\n') {
84 rv.truncate(rv.len() - 1);
85 }
86 rv
87 }
88 }
89}
90
91pub fn serialize_value<S: Serialize>(s: &S, format: SerializationFormat) -> String {
92 let serializer = ContentSerializer::<ValueError>::new();
93 let content = Serialize::serialize(s, serializer).unwrap();
94 serialize_content(content, format)
95}
96
97#[cfg(feature = "redactions")]
98pub fn serialize_value_redacted<S: Serialize>(
99 s: &S,
100 redactions: &[(crate::redaction::Selector, crate::redaction::Redaction)],
101 format: SerializationFormat,
102) -> String {
103 let serializer = ContentSerializer::<ValueError>::new();
104 let mut content = Serialize::serialize(s, serializer).unwrap();
105 for (selector, redaction) in redactions {
106 content = selector.redact(content, redaction);
107 }
108 serialize_content(content, format)
109}
110
111#[test]
112fn test_yaml_serialization() {
113 let yaml = serialize_content(
114 Content::Map(vec![
115 (
116 Content::from("env"),
117 Content::Seq(vec![
118 Content::from("ENVIRONMENT"),
119 Content::from("production"),
120 ]),
121 ),
122 (
123 Content::from("cmdline"),
124 Content::Seq(vec![Content::from("my-tool"), Content::from("run")]),
125 ),
126 ]),
127 SerializationFormat::Yaml,
128 );
129 crate::assert_snapshot!(&yaml, @r###"
130 env:
131 - ENVIRONMENT
132 - production
133 cmdline:
134 - my-tool
135 - run
136 "###);
137
138 let inline_yaml = serialize_content(
139 Content::Map(vec![
140 (
141 Content::from("env"),
142 Content::Seq(vec![
143 Content::from("ENVIRONMENT"),
144 Content::from("production"),
145 ]),
146 ),
147 (
148 Content::from("cmdline"),
149 Content::Seq(vec![Content::from("my-tool"), Content::from("run")]),
150 ),
151 ]),
152 SerializationFormat::Yaml,
153 );
154 crate::assert_snapshot!(&inline_yaml, @r###"
155 env:
156 - ENVIRONMENT
157 - production
158 cmdline:
159 - my-tool
160 - run
161 "###);
162}