1#![cfg(feature = "serde")]
2
3use serde::de::{
4 Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess,
5 Visitor,
6};
7use serde::ser::{Serialize, Serializer};
8
9use crate::{Level, LevelFilter, LOG_LEVEL_NAMES};
10
11use std::fmt;
12use std::str::{self, FromStr};
13
14impl Serialize for Level {
17 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
18 where
19 S: Serializer,
20 {
21 match *self {
22 Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
23 Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
24 Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
25 Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
26 Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
27 }
28 }
29}
30
31impl<'de> Deserialize<'de> for Level {
32 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33 where
34 D: Deserializer<'de>,
35 {
36 struct LevelIdentifier;
37
38 impl<'de> Visitor<'de> for LevelIdentifier {
39 type Value = Level;
40
41 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
42 formatter.write_str("log level")
43 }
44
45 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
46 where
47 E: Error,
48 {
49 let variant = LOG_LEVEL_NAMES[1..]
50 .get(v as usize)
51 .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
52
53 self.visit_str(variant)
54 }
55
56 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
57 where
58 E: Error,
59 {
60 FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
62 }
63
64 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
65 where
66 E: Error,
67 {
68 let variant = str::from_utf8(value)
69 .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
70
71 self.visit_str(variant)
72 }
73 }
74
75 impl<'de> DeserializeSeed<'de> for LevelIdentifier {
76 type Value = Level;
77
78 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
79 where
80 D: Deserializer<'de>,
81 {
82 deserializer.deserialize_identifier(LevelIdentifier)
83 }
84 }
85
86 struct LevelEnum;
87
88 impl<'de> Visitor<'de> for LevelEnum {
89 type Value = Level;
90
91 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
92 formatter.write_str("log level")
93 }
94
95 fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
96 where
97 A: EnumAccess<'de>,
98 {
99 let (level, variant) = value.variant_seed(LevelIdentifier)?;
100 variant.unit_variant()?;
102 Ok(level)
103 }
104 }
105
106 deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
107 }
108}
109
110impl Serialize for LevelFilter {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: Serializer,
114 {
115 match *self {
116 LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
117 LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
118 LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
119 LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
120 LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
121 LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
122 }
123 }
124}
125
126impl<'de> Deserialize<'de> for LevelFilter {
127 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
128 where
129 D: Deserializer<'de>,
130 {
131 struct LevelFilterIdentifier;
132
133 impl<'de> Visitor<'de> for LevelFilterIdentifier {
134 type Value = LevelFilter;
135
136 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
137 formatter.write_str("log level filter")
138 }
139
140 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
141 where
142 E: Error,
143 {
144 let variant = LOG_LEVEL_NAMES
145 .get(v as usize)
146 .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
147
148 self.visit_str(variant)
149 }
150
151 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
152 where
153 E: Error,
154 {
155 FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
157 }
158
159 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
160 where
161 E: Error,
162 {
163 let variant = str::from_utf8(value)
164 .map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
165
166 self.visit_str(variant)
167 }
168 }
169
170 impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
171 type Value = LevelFilter;
172
173 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
174 where
175 D: Deserializer<'de>,
176 {
177 deserializer.deserialize_identifier(LevelFilterIdentifier)
178 }
179 }
180
181 struct LevelFilterEnum;
182
183 impl<'de> Visitor<'de> for LevelFilterEnum {
184 type Value = LevelFilter;
185
186 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
187 formatter.write_str("log level filter")
188 }
189
190 fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
191 where
192 A: EnumAccess<'de>,
193 {
194 let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
195 variant.unit_variant()?;
197 Ok(level_filter)
198 }
199 }
200
201 deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use crate::{Level, LevelFilter};
208 use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
209
210 fn level_token(variant: &'static str) -> Token {
211 Token::UnitVariant {
212 name: "Level",
213 variant,
214 }
215 }
216
217 fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
218 [
219 Token::Enum { name: "Level" },
220 Token::Bytes(variant),
221 Token::Unit,
222 ]
223 }
224
225 fn level_variant_tokens(variant: u32) -> [Token; 3] {
226 [
227 Token::Enum { name: "Level" },
228 Token::U32(variant),
229 Token::Unit,
230 ]
231 }
232
233 fn level_filter_token(variant: &'static str) -> Token {
234 Token::UnitVariant {
235 name: "LevelFilter",
236 variant,
237 }
238 }
239
240 fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
241 [
242 Token::Enum {
243 name: "LevelFilter",
244 },
245 Token::Bytes(variant),
246 Token::Unit,
247 ]
248 }
249
250 fn level_filter_variant_tokens(variant: u32) -> [Token; 3] {
251 [
252 Token::Enum {
253 name: "LevelFilter",
254 },
255 Token::U32(variant),
256 Token::Unit,
257 ]
258 }
259
260 #[test]
261 fn test_level_ser_de() {
262 let cases = &[
263 (Level::Error, [level_token("ERROR")]),
264 (Level::Warn, [level_token("WARN")]),
265 (Level::Info, [level_token("INFO")]),
266 (Level::Debug, [level_token("DEBUG")]),
267 (Level::Trace, [level_token("TRACE")]),
268 ];
269
270 for (s, expected) in cases {
271 assert_tokens(s, expected);
272 }
273 }
274
275 #[test]
276 fn test_level_case_insensitive() {
277 let cases = &[
278 (Level::Error, [level_token("error")]),
279 (Level::Warn, [level_token("warn")]),
280 (Level::Info, [level_token("info")]),
281 (Level::Debug, [level_token("debug")]),
282 (Level::Trace, [level_token("trace")]),
283 ];
284
285 for (s, expected) in cases {
286 assert_de_tokens(s, expected);
287 }
288 }
289
290 #[test]
291 fn test_level_de_bytes() {
292 let cases = &[
293 (Level::Error, level_bytes_tokens(b"ERROR")),
294 (Level::Warn, level_bytes_tokens(b"WARN")),
295 (Level::Info, level_bytes_tokens(b"INFO")),
296 (Level::Debug, level_bytes_tokens(b"DEBUG")),
297 (Level::Trace, level_bytes_tokens(b"TRACE")),
298 ];
299
300 for (value, tokens) in cases {
301 assert_de_tokens(value, tokens);
302 }
303 }
304
305 #[test]
306 fn test_level_de_variant_index() {
307 let cases = &[
308 (Level::Error, level_variant_tokens(0)),
309 (Level::Warn, level_variant_tokens(1)),
310 (Level::Info, level_variant_tokens(2)),
311 (Level::Debug, level_variant_tokens(3)),
312 (Level::Trace, level_variant_tokens(4)),
313 ];
314
315 for (value, tokens) in cases {
316 assert_de_tokens(value, tokens);
317 }
318 }
319
320 #[test]
321 fn test_level_de_error() {
322 let msg = "unknown variant `errorx`, expected one of \
323 `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
324 assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
325 }
326
327 #[test]
328 fn test_level_filter_ser_de() {
329 let cases = &[
330 (LevelFilter::Off, [level_filter_token("OFF")]),
331 (LevelFilter::Error, [level_filter_token("ERROR")]),
332 (LevelFilter::Warn, [level_filter_token("WARN")]),
333 (LevelFilter::Info, [level_filter_token("INFO")]),
334 (LevelFilter::Debug, [level_filter_token("DEBUG")]),
335 (LevelFilter::Trace, [level_filter_token("TRACE")]),
336 ];
337
338 for (s, expected) in cases {
339 assert_tokens(s, expected);
340 }
341 }
342
343 #[test]
344 fn test_level_filter_case_insensitive() {
345 let cases = &[
346 (LevelFilter::Off, [level_filter_token("off")]),
347 (LevelFilter::Error, [level_filter_token("error")]),
348 (LevelFilter::Warn, [level_filter_token("warn")]),
349 (LevelFilter::Info, [level_filter_token("info")]),
350 (LevelFilter::Debug, [level_filter_token("debug")]),
351 (LevelFilter::Trace, [level_filter_token("trace")]),
352 ];
353
354 for (s, expected) in cases {
355 assert_de_tokens(s, expected);
356 }
357 }
358
359 #[test]
360 fn test_level_filter_de_bytes() {
361 let cases = &[
362 (LevelFilter::Off, level_filter_bytes_tokens(b"OFF")),
363 (LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")),
364 (LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")),
365 (LevelFilter::Info, level_filter_bytes_tokens(b"INFO")),
366 (LevelFilter::Debug, level_filter_bytes_tokens(b"DEBUG")),
367 (LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")),
368 ];
369
370 for (value, tokens) in cases {
371 assert_de_tokens(value, tokens);
372 }
373 }
374
375 #[test]
376 fn test_level_filter_de_variant_index() {
377 let cases = &[
378 (LevelFilter::Off, level_filter_variant_tokens(0)),
379 (LevelFilter::Error, level_filter_variant_tokens(1)),
380 (LevelFilter::Warn, level_filter_variant_tokens(2)),
381 (LevelFilter::Info, level_filter_variant_tokens(3)),
382 (LevelFilter::Debug, level_filter_variant_tokens(4)),
383 (LevelFilter::Trace, level_filter_variant_tokens(5)),
384 ];
385
386 for (value, tokens) in cases {
387 assert_de_tokens(value, tokens);
388 }
389 }
390
391 #[test]
392 fn test_level_filter_de_error() {
393 let msg = "unknown variant `errorx`, expected one of \
394 `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
395 assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
396 }
397}