1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
# Custom attributes
The `Debug` trait supports the following attributes:
* **Container attributes**
* [`Debug(bound="<where-clause or empty>")`](#custom-bound)
* [`Debug="transparent"`](#hiding-newtypes)
* **Variant attributes**
* [`Debug="transparent"`](#hiding-newtypes)
* **Field attributes**
* [`Debug(bound="<where-clause or empty>")`](#custom-bound)
* [`Debug(format_with="<path>")`](#format-with)
* [`Debug="ignore"`](#ignoring-a-field)
# Ignoring a field
You can use *derivative* to hide fields from a structure or enumeration `Debug`
implementation:
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Debug)]
struct Foo {
foo: u8,
#[derivative(Debug="ignore")]
bar: u8,
}
println!("{:?}", Foo { foo: 42, bar: 1 }); // Foo { foo: 42 }
```
# Hiding newtypes
You can use *derivative* to automatically unwrap newtypes and enumeration
variants with only one field:
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Debug="transparent")]
struct A(isize);
#[derive(Derivative)]
#[derivative(Debug)]
enum C {
Foo(u8),
#[derivative(Debug="transparent")]
Bar(u8),
}
println!("{:?}", A(42)); // 42
println!("{:?}", C::Bar(42)); // 42
// But:
println!("{:?}", C::Foo(42)); // Foo(42)
```
# Format with
You can pass a field to a format function:
```rust
# extern crate derivative;
# use derivative::Derivative;
# mod path {
# pub struct SomeTypeThatMightNotBeDebug;
# pub mod to {
# pub fn my_fmt_fn(_: &super::SomeTypeThatMightNotBeDebug, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { unimplemented!() }
# }
# }
# use path::SomeTypeThatMightNotBeDebug;
#[derive(Derivative)]
#[derivative(Debug)]
struct Foo {
foo: u32,
#[derivative(Debug(format_with="path::to::my_fmt_fn"))]
bar: SomeTypeThatMightNotBeDebug,
}
```
The field `bar` will be displayed with `path::to::my_fmt_fn(&bar, &mut fmt)`
where `fmt` is the current [`Formatter`].
The function must the following prototype:
```rust,ignore
fn fmt(&T, &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>;
```
# Custom bound
Usually, *derivative* will add a `T: Debug` bound for each type parameter `T`
of the current type. If you do not want that, you can specify an explicit bound:
* Either on the type. This replaces all bounds:
```rust
# extern crate derivative;
# use derivative::Derivative;
# trait MyDebug {
# fn my_fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>;
# }
# use std::fmt::Debug;
#[derive(Derivative)]
#[derivative(Debug(bound="T: Debug, U: MyDebug"))]
struct Foo<T, U> {
foo: T,
#[derivative(Debug(format_with="MyDebug::my_fmt"))]
bar: U,
}
```
* Or on a field. This replaces the bound *derivative* guessed for that field. The example below is equivalent to the above:
```rust
# extern crate derivative;
# use derivative::Derivative;
# trait MyDebug {
# fn my_fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>;
# }
#[derive(Derivative)]
#[derivative(Debug)]
struct Foo<T, U> {
foo: T,
#[derivative(Debug(format_with="MyDebug::my_fmt", bound="U: MyDebug"))]
bar: U,
}
```
With `bound=""` it is possible to remove any bound for the type. This is useful
if your type contains a `Foo<T>` that is `Debug` even if `T` is not.
[`Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
# Packed structures
You can use *derivative* to implement `Debug` on packed structures. Unlike the standard `derive(debug)`, *derivative* does not require the structure itself to be `Copy`, but like the standard `derive(debug)`, it requires each (non-ignored) field to be `Copy`.
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Debug)]
#[repr(C, packed)]
struct Foo {
foo: u8,
// `String` isn't `Copy` so it must be ignored to derive `Debug`
#[derivative(Debug="ignore")]
bar: String,
}
```
|