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
|
# Custom attributes
The `PartialEq`, `Eq`, `PartialOrd` and `Eq` and traits support the following attributes:
* **Container attributes**
* [`<CmpTrait>(bound="<where-clause or empty>")`](#custom-bound)
* **Field attributes**
* [`<CmpTrait>(bound="<where-clause or empty>")`](#custom-bound)
The `PartialEq`, `PartialOrd` and `Ord` traits also supports the following attributes:
* **Container attributes**
* [`<CmpTrait>="feature_allow_slow_enum"`](#enumerations)
* **Field attributes**
* [`<CmpTrait>="ignore"`](#ignoring-a-field)
* [`<CmpTrait>(compare_with="<path>")`](#compare-with)
(These attributes are not relevant for `Eq` which is just a marker trait.)
# Enumerations
Unfortunately, there is no way for derivative to derive `PartialOrd` or `Ord` on
enumerations as efficiently as the built-in `derive(…)` yet.
If you want to use derivative on enumerations anyway, you can add
```rust,ignore
#[derivative(PartialOrd="feature_allow_slow_enum")]
```
to your enumeration. This acts as a “feature-gate”.
This attribute is also allowed for `PartialEq` for historical reason. It is not
necessary anymore as of v2.1.0. It was never necessary nor allowed for `Eq`.
# Ignoring a field
You can use *derivative* to ignore a field when comparing:
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct Foo {
foo: u8,
#[derivative(PartialEq="ignore")]
bar: u8,
}
assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7});
assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0});
```
# Compare with
Usually fields are compared using `==`, `PartialOrd::partial_cmp` or `Ord::cmp`. You can use an alternative comparison
function if you like:
```rust
# extern crate derivative;
# use derivative::Derivative;
# mod path {
# pub struct SomeTypeThatMightNotBePartialEq;
# pub mod to {
# pub fn my_cmp_fn(_: &super::SomeTypeThatMightNotBePartialEq, _: &super::SomeTypeThatMightNotBePartialEq) -> bool { false }
# }
# }
# use path::SomeTypeThatMightNotBePartialEq;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct Foo {
foo: u32,
#[derivative(PartialEq(compare_with="path::to::my_cmp_fn"))]
bar: SomeTypeThatMightNotBePartialEq,
}
```
`foo` will be compared with `==` and `bar` will be compared with
`path::to::my_cmp_fn` which must have the following prototype:
| Trait | Signature |
|--------------|-----------|
| `PartialEq` | <span class="rust">`fn my_cmp_fn(&T, &T) -> bool;`</span>
| `PartialOrd` | <span class="rust">`fn my_cmp_fn(&T, &T) -> std::option::Option<std::cmp::Ordering>;`</span>
| `Ord` | <span class="rust">`fn my_cmp_fn(&T, &T) -> std::cmp::Ordering;`</span>
# Custom bound
Usually if you derive `CmpTrait`, a `T: CmpTrait` bound is added for each type parameter `T`. You can use
override this behavior if the inferred bound is not correct for you.
Eg. comparing raw pointers does not require the type to be `Eq`, so you could
use:
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
struct WithPtr<T: ?Sized> {
#[derivative(PartialEq(bound=""))]
foo: *const T
}
```
See [`Default`'s documentation](./Default.md#custom-bound) for more details.
# Packed structures
You can use *derivative* to implement the comparison traits on packed structures. Unlike the standard `derive`, *derivative* does not require the structure itself to be `Copy`, but like the standard `derive`, it requires each (non-ignored) field to be `Copy`.
```rust
# extern crate derivative;
# use derivative::Derivative;
#[derive(Derivative)]
#[derivative(PartialEq)]
#[repr(C, packed)]
struct Foo {
f: u32,
#[derivative(PartialEq = "ignore")]
t: String,
}
```
|