log/
serde.rs

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
14// The Deserialize impls are handwritten to be case-insensitive using FromStr.
15
16impl 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                // Case-insensitive.
61                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                // Every variant is a unit variant.
101                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                // Case-insensitive.
156                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                // Every variant is a unit variant.
196                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}