fmt_derive/lib.rs
1#![cfg_attr(not(test), no_std)] // we build the tests with `std` so that we can use `std::format!` and friends
2
3//! More robust and versatile implementation of `derive(Debug)` and `derive(Display)`. Unlike the version of
4//! `derive(Debug)` in the standard library, these macros will always successfully generate an implementation - even if
5//! a member does not implement `Debug`/`Display`. In that case, the generated implementation will print a replacement
6//! string of the form `<TypeName>`.
7//!
8//! # More Robust
9//! These derive macros always work, even when `derive(std::fmt::Debug)` fails.
10//!
11//! ```rust
12//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
13//! // a type that implements neither `Debug` nor `Display`
14//! struct Unprintable;
15//!
16//! #[derive(fmt_derive::Debug, fmt_derive::Display)]
17//! struct Printable(Unprintable);
18//!
19//! fn main() {
20//! // error[E0277]: `Unprintable` doesn't implement `Debug`
21//! // println!("{:?}", Unprintable);
22//!
23//! assert_eq!(format!("{:?}", Printable(Unprintable)), "Printable(<Unprintable>)");
24//!
25//! // deriving display is often more useful with a custom format expression, but will silently fall back to the same
26//! // behavior as `Debug`
27//! assert_eq!(format!("{}", Printable(Unprintable)), "Printable(<Unprintable>)");
28//! }
29//! ```
30//!
31//! # Drop in Usage
32//! Anything that derives [`std::fmt::Debug`] or [`core::fmt::Debug`] can derive [`fmt_derive::Debug`](`Debug`) instead
33//! without any changes required.
34//!
35//! However, both cannot be `use`d at the same time, as their names clash:
36//!
37//! ```rust,compile_fail
38//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
39//! # fn main() {}
40//! // error[E0252]: the name `Debug` is defined multiple times
41//! use fmt_derive::Debug;
42//! use core::fmt::Debug;
43//! ```
44//!
45//! The same problem exists for `Display`:
46//! ```rust,compile_fail
47//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
48//! # fn main() {}
49//! // error[E0252]: the name `Display` is defined multiple times
50//! use fmt_derive::Display;
51//! use core::fmt::Display;
52//! ```
53//!
54//! If you encounter this problem, there is a simple solution: `use fmt_derive::Debug;` also pulls in the
55//! [`std::fmt::Debug`]/[`core::fmt::Debug`] trait, there is no need to `use` the standard library `Debug`.
56//!
57//! ```rust
58//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
59//! use fmt_derive::Debug; // replace `use std::fmt::Debug;` and `use core::fmt::Debug;`
60//!
61//! struct Unprintable;
62//!
63//! #[derive(Debug)]
64//! struct Printable(Unprintable);
65//!
66//! fn main() {
67//! // error[E0277]: `Unprintable` doesn't implement `Debug`
68//! // println!("{:?}", Unprintable);
69//!
70//! assert_eq!(format!("{:?}", &Printable(Unprintable) as &dyn Debug), "Printable(<Unprintable>)");
71//! }
72//! ```
73//!
74//! # More Versatile
75//! The derived implementation can be easily customized using additional attributes.
76//!
77//! ## Custom Format Expressions
78//! A custom representation can be quickly derived using a format expression for the whole structure, enumeration, or
79//! untagged unions. This is the expected case when deriving `Display` or when a member needs to be formatted in a
80//! special manner:
81//!
82//! ```rust
83//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
84//! use fmt_derive::{Debug, Display};
85//!
86//! #[derive(Display, Debug)]
87//! #[debug("T<0x{:X}>", self.0)]
88//! #[display("A thing that sits on the number {}", self.0)]
89//! struct Thing(u32);
90//!
91//! fn main() {
92//! assert_eq!(format!("{:?}", Thing(0xF7A)), "T<0xF7A>");
93//! assert_eq!(format!("{}", Thing(42)), "A thing that sits on the number 42");
94//! }
95//! ```
96//!
97//! ## Custom Format Expressions for Enumeration Variants
98//! For enumerations, variants can also be customized:
99//!
100//! ```rust
101//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
102//! use fmt_derive::Debug;
103//!
104//! #[derive(Debug)]
105//! enum Thing{
106//! // tuple members are exposed as `_0`, `_1`, and so forth
107//! #[debug("Thing::VariantA(0x{:X}, {})", _0, _1)]
108//! VariantA(u32, u32),
109//! // struct members are exposed under their name
110//! #[debug("Thing::VariantB({})", x)]
111//! VariantB{
112//! x: u32,
113//! unused: u32,
114//! }
115//! }
116//!
117//! fn main() {
118//! assert_eq!(format!("{:?}", Thing::VariantA(0xF7A, 42)), "Thing::VariantA(0xF7A, 42)");
119//! assert_eq!(format!("{:?}", Thing::VariantB{x: 42, unused: 0}), "Thing::VariantB(42)");
120//! }
121//! ```
122//!
123//! ## Custom Format Expressions for Individual Fields
124//! Or by customizing an individual field:
125//!
126//! ```rust
127//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
128//! use fmt_derive::Debug;
129//!
130//! #[derive(Debug)]
131//! struct Thing(#[debug("0x{:X}", self.0)] u32);
132//!
133//! fn main() {
134//! assert_eq!(format!("{:?}", Thing(0xF7A)), "Thing(0xF7A)");
135//! }
136//! ```
137//!
138//! ## Ignoring a Field
139//! Although it is possible to derive a debug message for any field, it is sometimes preferable to not print a field at
140//! all:
141//!
142//! ```rust
143//! # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
144//! use fmt_derive::Debug;
145//!
146//! #[derive(Debug)]
147//! struct Function(#[debug(ignore)] fn());
148//!
149//! fn main() {
150//! assert_eq!(format!("{:?}", Function(main)), "Function");
151//! }
152//! ```
153
154/// Derive implementations of `Debug` for arbitrary `struct`s and `enum`s (`union`s are supported only with a
155/// top-level format directive). `use`ing [`fmt_derive::Debug`](crate::Debug), will also pull in the
156/// [`core::fmt::Debug`]/[`std::fmt::Debug`] trait (but the macro of the same name will be replaced with this one).
157pub use fmt_derive_proc::Debug;
158/// Derive implementations of `Display` for arbitrary `struct`s and `enum`s (`union`s are supported only with a
159/// top-level format directive).. `use`ing [`fmt_derive::Display`](crate::Display), will also pull in the
160/// [`core::fmt::Display`]/[`std::fmt::Display`] trait (but the macro of the same name will be replaced with this
161/// one).
162pub use fmt_derive_proc::Display;
163
164pub mod _rt;
165
166mod test;
167
168/// Glob-exporting this module reexports original [`core::fmt::Debug`] *trait*, while shadowing the macro of the same
169/// name (due to the specific reexport of [`fmt_derive_proc::Debug`]). This enables the following use case:
170///
171/// ```
172/// # use fmt_derive::_rt; // required for doctests in the `fmt_derive` crate only
173/// use fmt_derive::Debug;
174///
175/// #[derive(Debug)]
176/// struct Derived;
177///
178/// struct Custom;
179///
180/// // [`fmt_derive::Debug`] is also reexport of the [`core::fmt::Debug`] trait
181/// impl Debug for Custom {
182/// fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
183/// write!(f, "Custom!")
184/// }
185/// }
186///
187/// // All ways of naming this trait are equivalent
188/// fn as_debug(_: &dyn Debug) { }
189/// fn as_core_debug(_: &dyn core::fmt::Debug) { }
190/// fn as_fmt_derive_debug(_: &dyn fmt_derive::Debug) { }
191///
192/// fn main() {
193/// assert_eq!(format!("{:?}", Derived), "Derived");
194/// assert_eq!(format!("{:?}", Custom), "Custom!");
195///
196/// as_debug(&Derived);
197/// as_debug(&Custom);
198/// as_debug(&"");
199///
200/// as_core_debug(&Derived);
201/// as_core_debug(&Custom);
202/// as_core_debug(&"");
203///
204/// as_fmt_derive_debug(&Derived);
205/// as_fmt_derive_debug(&Custom);
206/// as_fmt_derive_debug(&"");
207/// }
208/// ```
209mod shadowed_reexport_trick {
210 /// The trait and macro from the standard library. Only the trait is actually exposed by this crate.
211 pub use core::fmt::Debug;
212 /// The trait and macro from the standard library. Only the trait is actually exposed by this crate.
213 pub use core::fmt::Display;
214}
215pub use shadowed_reexport_trick::*;