Crate fmt_derive

Source
Expand description

More robust and versatile implementation of derive(Debug) and derive(Display). Unlike the version of derive(Debug) in the standard library, these macros will always successfully generate an implementation - even if a member does not implement Debug/Display. In that case, the generated implementation will print a replacement string of the form <TypeName>.

§More Robust

These derive macros always work, even when derive(std::fmt::Debug) fails.

// a type that implements neither `Debug` nor `Display`
struct Unprintable;

#[derive(fmt_derive::Debug, fmt_derive::Display)]
struct Printable(Unprintable);

fn main() {
  // error[E0277]: `Unprintable` doesn't implement `Debug`
  // println!("{:?}", Unprintable);

  assert_eq!(format!("{:?}", Printable(Unprintable)), "Printable(<Unprintable>)");

  // deriving display is often more useful with a custom format expression, but will silently fall back to the same
  // behavior as `Debug`
  assert_eq!(format!("{}", Printable(Unprintable)), "Printable(<Unprintable>)");
}

§Drop in Usage

Anything that derives [std::fmt::Debug] or core::fmt::Debug can derive fmt_derive::Debug instead without any changes required.

However, both cannot be used at the same time, as their names clash:

// error[E0252]: the name `Debug` is defined multiple times
use fmt_derive::Debug;
use core::fmt::Debug;

The same problem exists for Display:

// error[E0252]: the name `Display` is defined multiple times
use fmt_derive::Display;
use core::fmt::Display;

If you encounter this problem, there is a simple solution: use fmt_derive::Debug; also pulls in the [std::fmt::Debug]/core::fmt::Debug trait, there is no need to use the standard library Debug.

use fmt_derive::Debug; // replace `use std::fmt::Debug;` and `use core::fmt::Debug;`

struct Unprintable;

#[derive(Debug)]
struct Printable(Unprintable);

fn main() {
  // error[E0277]: `Unprintable` doesn't implement `Debug`
  // println!("{:?}", Unprintable);

  assert_eq!(format!("{:?}", &Printable(Unprintable) as &dyn Debug), "Printable(<Unprintable>)");
}

§More Versatile

The derived implementation can be easily customized using additional attributes.

§Custom Format Expressions

A custom representation can be quickly derived using a format expression for the whole structure, enumeration, or untagged unions. This is the expected case when deriving Display or when a member needs to be formatted in a special manner:

use fmt_derive::{Debug, Display};

#[derive(Display, Debug)]
#[debug("T<0x{:X}>", self.0)]
#[display("A thing that sits on the number {}", self.0)]
struct Thing(u32);

fn main() {
  assert_eq!(format!("{:?}", Thing(0xF7A)), "T<0xF7A>");
  assert_eq!(format!("{}", Thing(42)), "A thing that sits on the number 42");
}

§Custom Format Expressions for Enumeration Variants

For enumerations, variants can also be customized:

use fmt_derive::Debug;

#[derive(Debug)]
enum Thing{
  // tuple members are exposed as `_0`, `_1`, and so forth
  #[debug("Thing::VariantA(0x{:X}, {})", _0, _1)]
  VariantA(u32, u32),
  // struct members are exposed under their name
  #[debug("Thing::VariantB({})", x)]
  VariantB{
    x: u32,
    unused: u32,
  }
}

fn main() {
  assert_eq!(format!("{:?}", Thing::VariantA(0xF7A, 42)), "Thing::VariantA(0xF7A, 42)");
  assert_eq!(format!("{:?}", Thing::VariantB{x: 42, unused: 0}), "Thing::VariantB(42)");
}

§Custom Format Expressions for Individual Fields

Or by customizing an individual field:

use fmt_derive::Debug;

#[derive(Debug)]
struct Thing(#[debug("0x{:X}", self.0)] u32);

fn main() {
  assert_eq!(format!("{:?}", Thing(0xF7A)), "Thing(0xF7A)");
}

§Ignoring a Field

Although it is possible to derive a debug message for any field, it is sometimes preferable to not print a field at all:

use fmt_derive::Debug;

#[derive(Debug)]
struct Function(#[debug(ignore)] fn());

fn main() {
  assert_eq!(format!("{:?}", Function(main)), "Function");
}

Traits§

Debug
The trait and macro from the standard library. Only the trait is actually exposed by this crate. ? formatting.
Display
The trait and macro from the standard library. Only the trait is actually exposed by this crate. Format trait for an empty format, {}.

Derive Macros§

Debug
Derive implementations of Debug for arbitrary structs and enums (unions are supported only with a top-level format directive). useing fmt_derive::Debug, will also pull in the core::fmt::Debug/[std::fmt::Debug] trait (but the macro of the same name will be replaced with this one).
Debug
The trait and macro from the standard library. Only the trait is actually exposed by this crate. Derive macro generating an impl of the trait Debug.
Display
Derive implementations of Display for arbitrary structs and enums (unions are supported only with a top-level format directive).. useing fmt_derive::Display, will also pull in the core::fmt::Display/[std::fmt::Display] trait (but the macro of the same name will be replaced with this one).