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,
}
```
|