serde_fmt/
lib.rs

1/*!
2# `serde` -> `std::fmt`
3
4This library lets you take any `Serialize` and format it as if it's `Debug`.
5The format produced is the same as if the type derived `Debug`, and any
6formatting flags will be preserved.
7
8# Getting started
9
10Add `serde_fmt` to your `Cargo.toml`:
11
12```toml,ignore
13[dependencies.serde_fmt]
14version = "1.0.3"
15```
16
17By default, this library doesn't depend on the standard library.
18You can enable support with the `std` Cargo feature:
19
20```toml,ignore
21[dependencies.serde_fmt]
22version = "1.0.3"
23features = ["std"]
24```
25
26# Formatting a `Serialize`
27
28Use the [`to_debug`] function to treat a [`serde::Serialize`] like a [`std::fmt::Debug`]:
29
30```rust
31# use serde::Serialize;
32fn takes_serialize(v: impl Serialize) {
33    // You can dump any `Serialize` using the
34    // standard `dbg!` macro
35    dbg!(serde_fmt::to_debug(&v));
36
37    // do something with `v`
38}
39```
40*/
41
42#![doc(html_root_url = "https://docs.rs/serde_fmt/1.0.3")]
43#![cfg_attr(not(test), no_std)]
44
45#[cfg(all(not(test), not(feature = "std")))]
46extern crate core as std;
47
48#[cfg(any(test, feature = "std"))]
49extern crate std;
50
51use crate::std::fmt::{self, Debug, Display};
52
53use serde::ser::{
54    self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
55    SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer,
56};
57
58/**
59Format a [`serde::Serialize`] into a [`std::fmt::Write`].
60*/
61pub fn to_writer(v: impl Serialize, mut w: impl fmt::Write) -> fmt::Result {
62    w.write_fmt(format_args!("{:?}", to_debug(v)))
63}
64
65/**
66Treat a type implementing [`serde::Serialize`] like a type implementing [`std::fmt::Debug`].
67*/
68pub fn to_debug<T>(v: T) -> ToDebug<T>
69where
70    T: Serialize,
71{
72    ToDebug(v)
73}
74
75/**
76The result of calling [`to_debug`] .
77*/
78#[derive(Clone, Copy)]
79pub struct ToDebug<T>(T);
80
81impl<T> Debug for ToDebug<T>
82where
83    T: Serialize,
84{
85    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86        fmt::Display::fmt(self, f)
87    }
88}
89
90// Even though it's not specified, since we treat `fmt::Debug`
91// as the canonical format for `ToDebug` we can also think of
92// it as the human-readable `Display`able format in the same
93// way that `fmt::Arguments` does.
94impl<T> Display for ToDebug<T>
95where
96    T: Serialize,
97{
98    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99        // If the `Serialize` impl fails then swallow the error rather than
100        // propagate it; Traits like `ToString` expect formatting to be
101        // infallible unless the writer itself fails
102        match self.0.serialize(Formatter::new(f)) {
103            Ok(()) => Ok(()),
104            Err(e) => write!(f, "<{}>", e),
105        }
106    }
107}
108
109// Surface the original `Serialize` implementation.
110impl<T> Serialize for ToDebug<T>
111where
112    T: Serialize,
113{
114    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
115    where
116        S: Serializer,
117    {
118        self.0.serialize(serializer)
119    }
120}
121
122struct Formatter<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);
123
124impl<'a, 'b: 'a> Formatter<'a, 'b> {
125    fn new(fmt: &'a mut fmt::Formatter<'b>) -> Self {
126        Formatter(fmt)
127    }
128
129    fn fmt(self, v: impl Debug) -> Result<(), Error> {
130        v.fmt(self.0).map_err(Into::into)
131    }
132}
133
134impl<'a, 'b: 'a> Serializer for Formatter<'a, 'b> {
135    type Ok = ();
136    type Error = Error;
137
138    type SerializeSeq = DebugSeq<'a, 'b>;
139    type SerializeTuple = DebugTuple<'a, 'b>;
140    type SerializeTupleStruct = DebugTupleStruct<'a, 'b>;
141    type SerializeTupleVariant = DebugTupleVariant<'a, 'b>;
142    type SerializeMap = DebugMap<'a, 'b>;
143    type SerializeStruct = DebugStruct<'a, 'b>;
144    type SerializeStructVariant = DebugStructVariant<'a, 'b>;
145
146    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
147        self.fmt(v)
148    }
149
150    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
151        self.fmt(v)
152    }
153
154    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
155        self.fmt(v)
156    }
157
158    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
159        self.fmt(v)
160    }
161
162    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
163        self.fmt(v)
164    }
165
166    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
167        self.fmt(v)
168    }
169
170    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
171        self.fmt(v)
172    }
173
174    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
175        self.fmt(v)
176    }
177
178    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
179        self.fmt(v)
180    }
181
182    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
183        self.fmt(v)
184    }
185
186    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
187        self.fmt(v)
188    }
189
190    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
191        self.fmt(v)
192    }
193
194    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
195        self.fmt(v)
196    }
197
198    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
199        self.fmt(v)
200    }
201
202    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
203        self.fmt(v)
204    }
205
206    fn collect_str<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error>
207    where
208        T: Display,
209    {
210        self.fmt(format_args!("{}", v))
211    }
212
213    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
214        self.fmt(v)
215    }
216
217    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
218        write!(self.0, "None")?;
219        Ok(())
220    }
221
222    fn serialize_some<T>(self, v: &T) -> Result<Self::Ok, Self::Error>
223    where
224        T: ?Sized + Serialize,
225    {
226        self.serialize_newtype_struct("Some", v)
227    }
228
229    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
230        write!(self.0, "()")?;
231        Ok(())
232    }
233
234    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
235        self.serialize_tuple_struct(name, 0)?.end()
236    }
237
238    fn serialize_unit_variant(
239        self,
240        _name: &'static str,
241        _variant_index: u32,
242        variant: &'static str,
243    ) -> Result<Self::Ok, Self::Error> {
244        self.serialize_tuple_struct(variant, 0)?.end()
245    }
246
247    fn serialize_newtype_struct<T>(self, name: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
248    where
249        T: ?Sized + Serialize,
250    {
251        let mut tuple = self.serialize_tuple_struct(name, 1)?;
252        tuple.serialize_field(v)?;
253        tuple.end()
254    }
255
256    fn serialize_newtype_variant<T>(
257        self,
258        _name: &'static str,
259        _variant_index: u32,
260        variant: &'static str,
261        v: &T,
262    ) -> Result<Self::Ok, Self::Error>
263    where
264        T: ?Sized + Serialize,
265    {
266        let mut tuple = self.serialize_tuple_struct(variant, 1)?;
267        tuple.serialize_field(v)?;
268        tuple.end()
269    }
270
271    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
272        Ok(DebugSeq(self.0.debug_list()))
273    }
274
275    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
276        Ok(DebugTuple(self.0.debug_tuple("")))
277    }
278
279    fn serialize_tuple_struct(
280        self,
281        name: &'static str,
282        _len: usize,
283    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
284        Ok(DebugTupleStruct(self.0.debug_tuple(name)))
285    }
286
287    fn serialize_tuple_variant(
288        self,
289        _name: &'static str,
290        _variant_index: u32,
291        variant: &'static str,
292        _len: usize,
293    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
294        Ok(DebugTupleVariant(self.0.debug_tuple(variant)))
295    }
296
297    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
298        Ok(DebugMap(self.0.debug_map()))
299    }
300
301    fn serialize_struct(
302        self,
303        name: &'static str,
304        _len: usize,
305    ) -> Result<Self::SerializeStruct, Self::Error> {
306        Ok(DebugStruct(self.0.debug_struct(name)))
307    }
308
309    fn serialize_struct_variant(
310        self,
311        _name: &'static str,
312        _variant_index: u32,
313        variant: &'static str,
314        _len: usize,
315    ) -> Result<Self::SerializeStructVariant, Self::Error> {
316        Ok(DebugStructVariant(self.0.debug_struct(variant)))
317    }
318}
319
320struct DebugSeq<'a, 'b: 'a>(fmt::DebugList<'a, 'b>);
321
322impl<'a, 'b: 'a> SerializeSeq for DebugSeq<'a, 'b> {
323    type Ok = ();
324    type Error = Error;
325
326    fn serialize_element<T>(&mut self, v: &T) -> Result<Self::Ok, Self::Error>
327    where
328        T: ?Sized + Serialize,
329    {
330        self.0.entry(&to_debug(v));
331        Ok(())
332    }
333
334    fn end(mut self) -> Result<Self::Ok, Self::Error> {
335        self.0.finish().map_err(Into::into)
336    }
337}
338
339struct DebugTuple<'a, 'b: 'a>(fmt::DebugTuple<'a, 'b>);
340
341impl<'a, 'b: 'a> SerializeTuple for DebugTuple<'a, 'b> {
342    type Ok = ();
343    type Error = Error;
344
345    fn serialize_element<T>(&mut self, v: &T) -> Result<Self::Ok, Self::Error>
346    where
347        T: ?Sized + Serialize,
348    {
349        self.0.field(&to_debug(v));
350        Ok(())
351    }
352
353    fn end(mut self) -> Result<Self::Ok, Self::Error> {
354        self.0.finish().map_err(Into::into)
355    }
356}
357
358struct DebugTupleStruct<'a, 'b: 'a>(fmt::DebugTuple<'a, 'b>);
359
360impl<'a, 'b: 'a> SerializeTupleStruct for DebugTupleStruct<'a, 'b> {
361    type Ok = ();
362    type Error = Error;
363
364    fn serialize_field<T>(&mut self, v: &T) -> Result<Self::Ok, Self::Error>
365    where
366        T: ?Sized + Serialize,
367    {
368        self.0.field(&to_debug(v));
369        Ok(())
370    }
371
372    fn end(mut self) -> Result<Self::Ok, Self::Error> {
373        self.0.finish().map_err(Into::into)
374    }
375}
376
377struct DebugTupleVariant<'a, 'b: 'a>(fmt::DebugTuple<'a, 'b>);
378
379impl<'a, 'b: 'a> SerializeTupleVariant for DebugTupleVariant<'a, 'b> {
380    type Ok = ();
381    type Error = Error;
382
383    fn serialize_field<T>(&mut self, v: &T) -> Result<Self::Ok, Self::Error>
384    where
385        T: ?Sized + Serialize,
386    {
387        self.0.field(&to_debug(v));
388        Ok(())
389    }
390
391    fn end(mut self) -> Result<Self::Ok, Self::Error> {
392        self.0.finish().map_err(Into::into)
393    }
394}
395
396struct DebugStruct<'a, 'b: 'a>(fmt::DebugStruct<'a, 'b>);
397
398impl<'a, 'b: 'a> SerializeStruct for DebugStruct<'a, 'b> {
399    type Ok = ();
400    type Error = Error;
401
402    fn serialize_field<T>(&mut self, k: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
403    where
404        T: ?Sized + Serialize,
405    {
406        self.0.field(k, &to_debug(v));
407        Ok(())
408    }
409
410    fn end(mut self) -> Result<Self::Ok, Self::Error> {
411        self.0.finish().map_err(Into::into)
412    }
413}
414
415struct DebugStructVariant<'a, 'b: 'a>(fmt::DebugStruct<'a, 'b>);
416
417impl<'a, 'b: 'a> SerializeStructVariant for DebugStructVariant<'a, 'b> {
418    type Ok = ();
419    type Error = Error;
420
421    fn serialize_field<T>(&mut self, k: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
422    where
423        T: ?Sized + Serialize,
424    {
425        self.0.field(k, &to_debug(v));
426        Ok(())
427    }
428
429    fn end(mut self) -> Result<Self::Ok, Self::Error> {
430        self.0.finish().map_err(Into::into)
431    }
432}
433
434struct DebugMap<'a, 'b: 'a>(fmt::DebugMap<'a, 'b>);
435
436impl<'a, 'b: 'a> SerializeMap for DebugMap<'a, 'b> {
437    type Ok = ();
438    type Error = Error;
439
440    fn serialize_entry<K, V>(&mut self, k: &K, v: &V) -> Result<Self::Ok, Self::Error>
441    where
442        K: ?Sized + Serialize,
443        V: ?Sized + Serialize,
444    {
445        self.0.entry(&to_debug(k), &to_debug(v));
446        Ok(())
447    }
448
449    fn serialize_key<T>(&mut self, k: &T) -> Result<Self::Ok, Self::Error>
450    where
451        T: ?Sized + Serialize,
452    {
453        self.0.key(&to_debug(k));
454        Ok(())
455    }
456
457    fn serialize_value<T>(&mut self, v: &T) -> Result<Self::Ok, Self::Error>
458    where
459        T: ?Sized + Serialize,
460    {
461        self.0.value(&to_debug(v));
462        Ok(())
463    }
464
465    fn end(mut self) -> Result<Self::Ok, Self::Error> {
466        self.0.finish().map_err(Into::into)
467    }
468}
469
470#[derive(Debug)]
471struct Error;
472
473impl Display for Error {
474    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475        write!(f, "failed to serialize to a standard formatter")
476    }
477}
478
479impl From<Error> for fmt::Error {
480    fn from(_: Error) -> fmt::Error {
481        fmt::Error
482    }
483}
484
485impl From<fmt::Error> for Error {
486    fn from(_: fmt::Error) -> Error {
487        Error
488    }
489}
490
491impl ser::StdError for Error {}
492
493impl ser::Error for Error {
494    fn custom<T>(_: T) -> Self
495    where
496        T: Display,
497    {
498        Error
499    }
500}
501
502#[cfg(test)]
503extern crate serde_derive;
504
505#[cfg(test)]
506mod tests {
507    use super::*;
508    use serde::ser::Error as _;
509    use serde_derive::*;
510
511    fn check_fmt(v: (impl fmt::Debug + Serialize)) {
512        assert_eq!(format!("{:?}", v), format!("{:?}", to_debug(v)));
513    }
514
515    #[test]
516    fn failing_serialize_does_not_panic_to_string() {
517        struct Kaboom;
518
519        impl Serialize for Kaboom {
520            fn serialize<S: Serializer>(&self, _: S) -> Result<S::Ok, S::Error> {
521                Err(S::Error::custom("kaboom!"))
522            }
523        }
524
525        #[derive(Serialize)]
526        struct NestedKaboom {
527            a: i32,
528            b: Kaboom,
529            c: i32,
530        }
531
532        assert_eq!("<failed to serialize to a standard formatter>", to_debug(Kaboom).to_string());
533        assert_eq!("NestedKaboom { a: 1, b: <failed to serialize to a standard formatter>, c: 2 }", to_debug(NestedKaboom { a: 1, b: Kaboom, c: 2 }).to_string());
534    }
535
536    #[test]
537    fn struct_fmt_is_consitent() {
538        #[derive(Serialize, Debug)]
539        struct Struct {
540            a: Signed,
541            b: Unsigned,
542            c: char,
543            d: &'static str,
544            e: &'static [u8],
545            f: (),
546        }
547
548        #[derive(Serialize, Debug)]
549        struct Signed {
550            a: i8,
551            b: i16,
552            c: i32,
553            d: i64,
554        }
555
556        #[derive(Serialize, Debug)]
557        struct Unsigned {
558            a: u8,
559            b: u16,
560            c: u32,
561            d: u64,
562        }
563
564        check_fmt(Struct {
565            a: Signed {
566                a: -1,
567                b: 42,
568                c: -42,
569                d: 42,
570            },
571            b: Unsigned {
572                a: 1,
573                b: 42,
574                c: 1,
575                d: 42,
576            },
577            c: 'a',
578            d: "a string",
579            e: &[1, 2, 3],
580            f: (),
581        });
582    }
583
584    #[test]
585    fn fmt_flags_are_consistent() {
586        use crate::std::format;
587
588        #[derive(Serialize, Debug)]
589        struct Struct {
590            a: i32,
591            b: i32,
592        }
593
594        assert_eq!(format!("{:03?}", 42), format!("{:03?}", to_debug(42)));
595        assert_eq!(format!("{:x?}", 42), format!("{:x?}", to_debug(42)));
596        assert_eq!(format!("{:X?}", 42), format!("{:X?}", to_debug(42)));
597        assert_eq!(
598            format!("{:#?}", Struct { a: 42, b: 17 }),
599            format!("{:#?}", to_debug(Struct { a: 42, b: 17 }))
600        );
601    }
602
603    #[test]
604    fn option_fmt_is_consistent() {
605        check_fmt(Option::Some::<i32>(42));
606        check_fmt(Option::None::<i32>);
607    }
608
609    #[test]
610    fn result_fmt_is_consistent() {
611        check_fmt(Result::Ok::<i32, i32>(42));
612        check_fmt(Result::Err::<i32, i32>(42));
613    }
614
615    #[test]
616    fn tuple_fmt_is_consistent() {
617        check_fmt((42, 17));
618    }
619
620    #[test]
621    fn tagged_fmt_is_consistent() {
622        #[derive(Serialize, Debug)]
623        enum Tagged {
624            Unit,
625            NewType(i32),
626            Tuple(i32, i32),
627            Struct { a: i32, b: i32 },
628        }
629
630        check_fmt(Tagged::Unit);
631        check_fmt(Tagged::NewType(42));
632        check_fmt(Tagged::Tuple(42, 17));
633        check_fmt(Tagged::Struct { a: 42, b: 17 });
634    }
635}