Skip to main content

Crate dumpit

Crate dumpit 

Source
Expand description

A derive macro like #[derive(Debug)] that doesn’t require all fields to implement Debug. Non-Debug fields display as <!Debug> instead of causing a compile error.

§Basic Usage

use dumpit::Dump;

struct Opaque;

#[derive(Dump)]
struct Config {
    name: String,
    secret: Opaque,
}

let cfg = Config { name: "app".into(), secret: Opaque };
assert_eq!(format!("{:?}", cfg), r#"Config { name: "app", secret: <!Debug> }"#);

§Attributes

All single-argument attributes support both Meta::NameValue (key = value) and Meta::List (key(value)) forms. Multiple arguments require Meta::List.

§#[dump(skip)]

Omit the field from output.

use dumpit::Dump;

#[derive(Dump)]
struct User {
    name: String,
    #[dump(skip)]
    internal_id: u64,
}

let u = User { name: "Alice".into(), internal_id: 42 };
assert_eq!(format!("{:?}", u), r#"User { name: "Alice" }"#);

§#[dump(skip_if = "condition")]

Omit the field when the condition evaluates to true. The expression has access to self.

use dumpit::Dump;

#[derive(Dump)]
struct User {
    name: String,
    #[dump(skip_if = "self.email.is_empty()")]
    email: String,
}

let u1 = User { name: "Alice".into(), email: String::new() };
assert_eq!(format!("{:?}", u1), r#"User { name: "Alice" }"#);

let u2 = User { name: "Bob".into(), email: "bob@example.com".into() };
assert_eq!(format!("{:?}", u2), r#"User { name: "Bob", email: "bob@example.com" }"#);

§#[dump(format("fmt", args...))]

Format the field using a format!-style string. Arguments can reference self.

use dumpit::Dump;

#[derive(Dump)]
struct Person {
    #[dump(format("{} years", self.age))]
    age: u32,
}

let p = Person { age: 30 };
assert_eq!(format!("{:?}", p), "Person { age: 30 years }");

§#[dump(literal = value)]

Replace the field output with a literal value.

use dumpit::Dump;

#[derive(Dump)]
struct Credentials {
    user: String,
    #[dump(literal = "<redacted>")]
    #[allow(dead_code)]
    password: String,
}

let c = Credentials { user: "admin".into(), password: "secret".into() };
assert_eq!(format!("{:?}", c), r#"Credentials { user: "admin", password: "<redacted>" }"#);

§#[dump(with = "path::to::function")]

Use a custom function to format the field. The function signature must be fn(&&FieldType, &mut Formatter) -> fmt::Result.

use dumpit::Dump;

fn mask(_: &&String, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    f.write_str("****")
}

#[derive(Dump)]
struct Config {
    #[dump(with = "mask")]
    api_key: String,
}

let c = Config { api_key: "sk-12345".into() };
assert_eq!(format!("{:?}", c), "Config { api_key: **** }");

§#[dump(take = N)]

Call .iter().take(N) on the field and debug-print the collected elements. The field name becomes name(n/total) showing how many elements were taken vs the collection’s total length.

use dumpit::Dump;

#[derive(Dump)]
struct Data {
    #[dump(take = 3)]
    items: Vec<i32>,
}

let d = Data { items: vec![10, 20, 30, 40, 50] };
assert_eq!(format!("{:?}", d), "Data { items(3/5): [10, 20, 30] }");

§#[dump(truncate = N)]

Truncate the debug output to at most N characters, appending ... if exceeded.

use dumpit::Dump;

#[derive(Dump)]
struct Post {
    #[dump(truncate = 10)]
    body: String,
}

let p = Post { body: "Hello, world!".into() };
assert_eq!(format!("{:?}", p), r#"Post { body: "Hello, wo... }"#);

§Generics

For concrete types, Dump automatically detects whether a field implements Debug. For generic type parameters, add a Debug bound to get proper output:

use dumpit::Dump;

#[derive(Dump)]
struct Wrapper<T: std::fmt::Debug> {
    value: T,
}

let w = Wrapper { value: 42 };
assert_eq!(format!("{:?}", w), "Wrapper { value: 42 }");

Without the bound, generic fields display as <!Debug>.

§Enums

All enum variant types are supported.

use dumpit::Dump;

struct Opaque;

#[derive(Dump)]
enum Message {
    Text(String),
    Binary(Opaque),
    Ping,
}

assert_eq!(format!("{:?}", Message::Text("hi".into())), r#"Text("hi")"#);
assert_eq!(format!("{:?}", Message::Binary(Opaque)), "Binary(<!Debug>)");
assert_eq!(format!("{:?}", Message::Ping), "Ping");

Structs§

DebugAs
DebugWrap
Formatted
TakeIter
TruncateWrap
WithFn

Traits§

DebugFallbackBuild
TakeIterLen
Trait to get the length of a collection. Uses autoref specialization: types with .len() use the inherent method; others fall back to .into_iter().count().

Derive Macros§

Dump
The main entry point for the #[derive(Dump)] macro.