1#![allow(
16 clippy::if_same_then_else,
17 clippy::needless_bool,
18 clippy::needless_pass_by_value,
19 clippy::ptr_arg
20)]
21
22#[cfg(all(test, feature = "benchmarks"))]
23extern crate test;
24
25use super::Sample;
26use serde_json;
27use std::io::{Error as IOError, ErrorKind as IOErrorKind, Read, Write};
28
29#[derive(Debug)]
30pub enum Error {
31 Io(IOError),
32 Json(serde_json::Error),
33 DecodingFormat(String),
34}
35
36impl From<IOError> for Error {
37 fn from(e: IOError) -> Error {
38 Error::Io(e)
39 }
40}
41
42impl From<serde_json::Error> for Error {
43 fn from(e: serde_json::Error) -> Error {
44 Error::Json(e)
45 }
46}
47
48impl From<String> for Error {
49 fn from(e: String) -> Error {
50 Error::DecodingFormat(e)
51 }
52}
53
54impl Error {
55 pub fn already_exists() -> Error {
56 Error::Io(IOError::from(IOErrorKind::AlreadyExists))
57 }
58}
59
60#[derive(Clone, Debug, Deserialize)]
61#[serde(untagged)]
62enum ChromeTraceArrayEntries {
63 Array(Vec<Sample>),
64}
65
66pub fn serialize<W>(samples: &Vec<Sample>, output: W) -> Result<(), Error>
86where
87 W: Write,
88{
89 serde_json::to_writer(output, samples).map_err(Error::Json)
90}
91
92pub fn to_value(samples: &Vec<Sample>) -> Result<serde_json::Value, Error> {
93 serde_json::to_value(samples).map_err(Error::Json)
94}
95
96pub fn decode(samples: serde_json::Value) -> Result<Vec<Sample>, Error> {
97 serde_json::from_value(samples).map_err(Error::Json)
98}
99
100pub fn deserialize<R>(input: R) -> Result<Vec<Sample>, Error>
101where
102 R: Read,
103{
104 serde_json::from_reader(input).map_err(Error::Json)
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 #[cfg(feature = "json_payload")]
111 use crate::TracePayloadT;
112 #[cfg(feature = "benchmarks")]
113 use test::Bencher;
114
115 #[cfg(not(feature = "json_payload"))]
116 fn to_payload(value: &'static str) -> &'static str {
117 value
118 }
119
120 #[cfg(feature = "json_payload")]
121 fn to_payload(value: &'static str) -> TracePayloadT {
122 json!({ "test": value })
123 }
124
125 #[cfg(feature = "chrome_trace_event")]
126 #[test]
127 fn test_chrome_trace_serialization() {
128 use super::super::*;
129
130 let trace = Trace::enabled(Config::with_limit_count(10));
131 trace.instant("sample1", &["test", "chrome"]);
132 trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
133 trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
134 trace.closure_payload(
135 "sample4",
136 &["test", "chrome"],
137 || {
138 let _guard = trace.block("sample5", &["test,chrome"]);
139 },
140 to_payload("payload 4"),
141 );
142
143 let samples = trace.samples_cloned_unsorted();
144
145 let mut serialized = Vec::<u8>::new();
146
147 let result = serialize(&samples, &mut serialized);
148 assert!(result.is_ok(), "{:?}", result);
149
150 let decoded_result: Vec<serde_json::Value> = serde_json::from_slice(&serialized).unwrap();
151 assert_eq!(decoded_result.len(), 8);
152 assert_eq!(decoded_result[0]["name"].as_str().unwrap(), "process_name");
153 assert_eq!(decoded_result[1]["name"].as_str().unwrap(), "thread_name");
154 for i in 2..5 {
155 assert_eq!(decoded_result[i]["name"].as_str().unwrap(), samples[i].name);
156 assert_eq!(decoded_result[i]["cat"].as_str().unwrap(), "test,chrome");
157 assert_eq!(decoded_result[i]["ph"].as_str().unwrap(), "i");
158 assert_eq!(decoded_result[i]["ts"], samples[i].timestamp_us);
159 let nth_sample = &samples[i];
160 let nth_args = nth_sample.args.as_ref().unwrap();
161 assert_eq!(decoded_result[i]["args"]["xi_payload"], json!(nth_args.payload.as_ref()));
162 }
163 assert_eq!(decoded_result[5]["ph"], "B");
164 assert_eq!(decoded_result[6]["ph"], "E");
165 assert_eq!(decoded_result[7]["ph"], "X");
166 }
167
168 #[cfg(feature = "chrome_trace_event")]
169 #[test]
170 fn test_chrome_trace_deserialization() {
171 use super::super::*;
172
173 let trace = Trace::enabled(Config::with_limit_count(10));
174 trace.instant("sample1", &["test", "chrome"]);
175 trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
176 trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
177 trace.closure_payload("sample4", &["test", "chrome"], || (), to_payload("payload 4"));
178
179 let samples = trace.samples_cloned_unsorted();
180
181 let mut serialized = Vec::<u8>::new();
182 let result = serialize(&samples, &mut serialized);
183 assert!(result.is_ok(), "{:?}", result);
184
185 let deserialized_samples = deserialize(serialized.as_slice()).unwrap();
186 assert_eq!(deserialized_samples, samples);
187 }
188
189 #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
190 #[bench]
191 fn bench_chrome_trace_serialization_one_element(b: &mut Bencher) {
192 use super::*;
193
194 let mut serialized = Vec::<u8>::new();
195 let samples = vec![super::Sample::new_instant("trace1", &["benchmark", "test"], None)];
196 b.iter(|| {
197 serialized.clear();
198 serialize(&samples, &mut serialized).unwrap();
199 });
200 }
201
202 #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
203 #[bench]
204 fn bench_chrome_trace_serialization_multiple_elements(b: &mut Bencher) {
205 use super::super::*;
206 use super::*;
207
208 let mut serialized = Vec::<u8>::new();
209 let samples = vec![
210 Sample::new_instant("trace1", &["benchmark", "test"], None),
211 Sample::new_instant("trace2", &["benchmark"], None),
212 Sample::new_duration("trace3", &["benchmark"], Some(to_payload("some payload")), 0, 0),
213 Sample::new_instant("trace4", &["benchmark"], None),
214 ];
215
216 b.iter(|| {
217 serialized.clear();
218 serialize(&samples, &mut serialized).unwrap();
219 });
220 }
221}