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