educe/
lib.rs

1/*!
2# Educe
3
4This crate provides procedural macros to help you implement Rust-built-in traits quickly.
5
6## Features
7
8By default, every trait this crate supports will be enabled. You can disable all of them by disabling the default features and enable only the traits that you want to use by adding them to `features` explictly.
9
10For example,
11
12```toml
13[dependencies.educe]
14version = "*"
15features = ["Debug", "Default", "Hash", "Clone", "Copy"]
16default-features = false
17```
18
19## Debug
20
21Use `#[derive(Educe)]` and `#[educe(Debug)]` to implement the `Debug` trait for a struct, an enum, or a union. It supports to change the name of your types, variants and fields. You can also ignore some fields, or set a trait and/or a method to replace the `Debug` trait used by default. Also, you can even format a struct to a tuple, and vice versa.
22
23#### Basic Usage
24
25```rust
26#[macro_use] extern crate educe;
27
28#[derive(Educe)]
29#[educe(Debug)]
30struct Struct {
31    f1: u8
32}
33
34#[derive(Educe)]
35#[educe(Debug)]
36enum Enum {
37    V1,
38    V2 {
39        f1: u8,
40    },
41    V3(u8),
42}
43```
44
45#### Change the Name of a Type, a Variant or a Field
46
47The `name` attribute can help you rename a type, a variant or a field.
48
49```rust
50#[macro_use] extern crate educe;
51
52#[derive(Educe)]
53#[educe(Debug(name = "Struct2"))]
54struct Struct {
55    #[educe(Debug(name = "f"))]
56    f1: u8
57}
58
59#[derive(Educe)]
60#[educe(Debug(name = true))]
61enum Enum {
62    #[educe(Debug(name = false))]
63    V1,
64    #[educe(Debug(name = "V"))]
65    V2 {
66        #[educe(Debug(name = "f"))]
67        f1: u8,
68    },
69    #[educe(Debug(name = false))]
70    V3(u8),
71}
72```
73
74#### Ignore Fields
75
76The `ignore` attribute can ignore specific fields.
77
78```rust
79#[macro_use] extern crate educe;
80
81#[derive(Educe)]
82#[educe(Debug)]
83struct Struct {
84    #[educe(Debug(ignore))]
85    f1: u8
86}
87
88#[derive(Educe)]
89#[educe(Debug)]
90enum Enum {
91    V1,
92    V2 {
93        #[educe(Debug(ignore))]
94        f1: u8,
95    },
96    V3(
97        #[educe(Debug(ignore))]
98        u8
99    ),
100}
101```
102
103#### Fake Structs and Tuples
104
105With the `named_field` attribute, structs can be formatted as tuples and tuples can be formatted as structs.
106
107```rust
108#[macro_use] extern crate educe;
109
110#[derive(Educe)]
111#[educe(Debug(named_field = false))]
112struct Struct {
113    f1: u8
114}
115
116#[derive(Educe)]
117#[educe(Debug)]
118enum Enum {
119    V1,
120    #[educe(Debug(named_field = false))]
121    V2 {
122        f1: u8,
123    },
124    #[educe(Debug(named_field = true))]
125    V3(
126        u8,
127        #[educe(Debug(name = "value"))]
128        i32
129    ),
130}
131```
132
133#### Use Another Method or Trait to Do the Format Thing
134
135The `trait` and `method` attributes can be used to replace the `Debug` trait for fields. If you only set the `trait` parameter, the `method` will be set to `fmt` automatically by default.
136
137```rust
138#[macro_use] extern crate educe;
139
140use std::fmt::{self, Formatter};
141
142fn fmt(_s: &u8, f: &mut Formatter) -> fmt::Result {
143    f.write_str("Hi")
144}
145
146trait A {
147    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
148        f.write_str("Hi")
149    }
150}
151
152impl A for i32 {};
153impl A for u64 {};
154
155#[derive(Educe)]
156#[educe(Debug)]
157enum Enum<T: A> {
158    V1,
159    V2 {
160        #[educe(Debug(method = "fmt"))]
161        f1: u8,
162    },
163    V3(
164        #[educe(Debug(trait = "std::fmt::UpperHex"))]
165        u8,
166        #[educe(Debug(trait = "A"))]
167        T
168    ),
169}
170```
171
172#### Generic Parameters Bound to the `Debug` Trait or Others
173
174The `#[educe(Debug(bound))]` attribute can be used to add the `Debug` trait bound to all generic parameters for the `Debug` implementation.
175
176```rust
177#[macro_use] extern crate educe;
178
179#[derive(Educe)]
180#[educe(Debug(bound))]
181enum Enum<T, K> {
182    V1,
183    V2 {
184        f1: K,
185    },
186    V3(
187        T
188    ),
189}
190```
191
192Or you can set the where predicates by yourself.
193
194```rust
195#[macro_use] extern crate educe;
196
197use std::fmt::{self, Formatter};
198
199fn fmt(_s: &u8, f: &mut Formatter) -> fmt::Result {
200    f.write_str("Hi")
201}
202
203trait A {
204    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
205        f.write_str("Hi")
206    }
207}
208
209impl A for i32 {};
210impl A for u64 {};
211
212#[derive(Educe)]
213#[educe(Debug(bound = "T: std::fmt::Debug, K: A"))]
214enum Enum<T, K> {
215    V1,
216    V2 {
217        #[educe(Debug(trait = "A"))]
218        f1: K,
219    },
220    V3(
221        T
222    ),
223}
224```
225
226#### Union
227
228A union will be formatted to a `u8` slice, because we don't know it's field at runtime. The fields of a union cannot be ignored, renamed or formated with other methods or traits.
229
230```rust
231#[macro_use] extern crate educe;
232
233#[derive(Educe)]
234#[educe(Debug)]
235struct Union {
236    f1: u8,
237    f2: i32,
238}
239```
240
241## PartialEq
242
243Use `#[derive(Educe)]` and `#[educe(ParitalEq)]` to implement the `ParitalEq` trait for a struct or an enum. It supports to ignore some fields, or set a trait and/or a method to replace the `ParitalEq` trait used by default.
244
245#### Basic Usage
246
247```rust
248#[macro_use] extern crate educe;
249
250#[derive(Educe)]
251#[educe(PartialEq)]
252struct Struct {
253    f1: u8
254}
255
256#[derive(Educe)]
257#[educe(PartialEq)]
258enum Enum {
259    V1,
260    V2 {
261        f1: u8,
262    },
263    V3(u8),
264}
265```
266
267#### Ignore Fields
268
269The `ignore` attribute can ignore specific fields.
270
271```rust
272#[macro_use] extern crate educe;
273
274#[derive(Educe)]
275#[educe(PartialEq)]
276struct Struct {
277    #[educe(PartialEq(ignore))]
278    f1: u8
279}
280
281#[derive(Educe)]
282#[educe(PartialEq)]
283enum Enum {
284    V1,
285    V2 {
286        #[educe(PartialEq(ignore))]
287        f1: u8,
288    },
289    V3(
290        #[educe(PartialEq(ignore))]
291        u8
292    ),
293}
294```
295
296#### Use Another Method or Trait to Do Comparing
297
298The `trait` and `method` attributes can be used to replace the `PartialEq` trait for fields. If you only set the `trait` parameter, the `method` will be set to `eq` automatically by default.
299
300```rust
301#[macro_use] extern crate educe;
302
303fn eq(a: &u8, b: &u8) -> bool {
304    a + 1 == *b
305}
306
307trait A {
308    fn eq(&self, b: &Self) -> bool;
309}
310
311impl A for i32 {
312    fn eq(&self, b: &i32) -> bool {
313        self + 1 == *b
314    }
315}
316
317impl A for u64 {
318    fn eq(&self, b: &u64) -> bool {
319        self + 1 == *b
320    }
321}
322
323#[derive(Educe)]
324#[educe(PartialEq)]
325enum Enum<T: A> {
326    V1,
327    V2 {
328        #[educe(PartialEq(method = "eq"))]
329        f1: u8,
330    },
331    V3(
332        #[educe(PartialEq(trait = "A"))]
333        T
334    ),
335}
336```
337
338#### Generic Parameters Bound to the `PartialEq` Trait or Others
339
340The `#[educe(PartialEq(bound))]` attribute can be used to add the `PartialEq` trait bound to all generaic parameters for the `PartialEq` implementation.
341
342```rust
343#[macro_use] extern crate educe;
344
345#[derive(Educe)]
346#[educe(PartialEq(bound))]
347enum Enum<T, K> {
348    V1,
349    V2 {
350        f1: K,
351    },
352    V3(
353        T
354    ),
355}
356```
357
358Or you can set the where predicates by yourself.
359
360```rust
361#[macro_use] extern crate educe;
362
363trait A {
364    fn eq(&self, b: &Self) -> bool;
365}
366
367impl A for i32 {
368    fn eq(&self, b: &i32) -> bool {
369        self + 1 == *b
370    }
371}
372
373impl A for u64 {
374    fn eq(&self, b: &u64) -> bool {
375        self + 1 == *b
376    }
377}
378
379#[derive(Educe)]
380#[educe(PartialEq(bound = "T: std::cmp::PartialEq, K: A"))]
381enum Enum<T, K> {
382    V1,
383    V2 {
384        #[educe(PartialEq(trait = "A"))]
385        f1: K,
386    },
387    V3(
388        T
389    ),
390}
391```
392
393## Eq
394
395Use `#[derive(Educe)]` and `#[educe(Eq)]` to implement the `Eq` trait for a struct, an enum or a union.
396
397#### Basic Usage
398
399```rust
400#[macro_use] extern crate educe;
401
402#[derive(Educe)]
403#[educe(PartialEq, Eq)]
404struct Struct {
405    f1: u8
406}
407
408#[derive(Educe)]
409#[educe(PartialEq, Eq)]
410enum Enum {
411    V1,
412    V2 {
413        f1: u8,
414    },
415    V3(u8),
416}
417```
418
419#### Generic Parameters Bound to the `Eq` Trait or Others
420
421The `#[educe(Eq(bound))]` attribute can be used to add the `Eq` trait bound to all generaic parameters for the `Eq` implementation.
422
423```rust
424#[macro_use] extern crate educe;
425
426#[derive(Educe)]
427#[educe(PartialEq(bound), Eq(bound))]
428enum Enum<T, K> {
429    V1,
430    V2 {
431        f1: K,
432    },
433    V3(
434        T
435    ),
436}
437```
438
439Or you can set the where predicates by yourself. (NOTE: The `Eq` trait depends on the `PartialEq` (`PartialEq<Self>`) trait.)
440
441```rust
442#[macro_use] extern crate educe;
443
444trait A {
445    fn eq(&self, b: &Self) -> bool;
446}
447
448impl A for i32 {
449    fn eq(&self, b: &i32) -> bool {
450        self + 1 == *b
451    }
452}
453
454impl A for u64 {
455    fn eq(&self, b: &u64) -> bool {
456        self + 1 == *b
457    }
458}
459
460#[derive(Educe)]
461#[educe(PartialEq(bound = "T: std::cmp::PartialEq, K: A"), Eq(bound = "T: std::cmp::PartialEq, K: A"))]
462enum Enum<T, K> {
463    V1,
464    V2 {
465        #[educe(PartialEq(trait = "A"))]
466        f1: K,
467    },
468    V3(
469        T
470    ),
471}
472```
473
474## PartialOrd
475
476Use `#[derive(Educe)]` and `#[educe(PartialOrd)]` to implement the `PartialOrd` trait for a struct or an enum. It supports to ignore some fields, or set a trait and/or a method to replace the `PartialOrd` trait used by default. The rank of variants and fields can also be modified.
477
478#### Basic Usage
479
480```rust
481#[macro_use] extern crate educe;
482
483#[derive(Educe)]
484#[educe(PartialEq, PartialOrd)]
485struct Struct {
486    f1: u8
487}
488
489#[derive(Educe)]
490#[educe(PartialEq, PartialOrd)]
491enum Enum {
492    V1,
493    V2 {
494        f1: u8,
495    },
496    V3(u8),
497}
498```
499
500#### Ignore Fields
501
502The `ignore` attribute can ignore specific fields.
503
504```rust
505#[macro_use] extern crate educe;
506
507#[derive(Educe)]
508#[educe(PartialEq, PartialOrd)]
509struct Struct {
510    #[educe(PartialOrd(ignore))]
511    f1: u8
512}
513
514#[derive(Educe)]
515#[educe(PartialEq, PartialOrd)]
516enum Enum {
517    V1,
518    V2 {
519        #[educe(PartialOrd(ignore))]
520        f1: u8,
521    },
522    V3(
523        #[educe(PartialOrd(ignore))]
524        u8
525    ),
526}
527```
528
529#### Use Another Method or Trait to Do Comparing
530
531The `trait` and `method` attributes can be used to replace the `PartialOrd` trait for fields. If you only set the `trait` parameter, the `method` will be set to `partial_cmp` automatically by default.
532
533```rust
534#[macro_use] extern crate educe;
535
536use std::cmp::Ordering;
537
538fn partial_cmp(a: &u8, b: &u8) -> Option<Ordering> {
539    if a > b {
540        Some(Ordering::Less)
541    } else if a < b {
542        Some(Ordering::Greater)
543    } else {
544        Some(Ordering::Equal)
545    }
546}
547
548trait A {
549    fn partial_cmp(&self, b: &Self) -> Option<Ordering>;
550}
551
552impl A for i32 {
553    fn partial_cmp(&self, b: &i32) -> Option<Ordering> {
554        if self > b {
555            Some(Ordering::Less)
556        } else if self < b {
557            Some(Ordering::Greater)
558        } else {
559            Some(Ordering::Equal)
560        }
561    }
562}
563
564#[derive(Educe)]
565#[educe(PartialEq, PartialOrd)]
566enum Enum<T: std::cmp::PartialEq + A> {
567    V1,
568    V2 {
569        #[educe(PartialOrd(method = "partial_cmp"))]
570        f1: u8,
571    },
572    V3(
573        #[educe(PartialOrd(trait = "A"))]
574        T
575    ),
576}
577```
578
579#### Generic Parameters Bound to the `PartialOrd` Trait or Others
580
581The `#[educe(PartialOrd(bound))]` attribute can be used to add the `PartialOrd` trait bound to all generaic parameters for the `PartialOrd` implementation.
582
583```rust
584#[macro_use] extern crate educe;
585
586#[derive(Educe)]
587#[educe(PartialEq(bound), PartialOrd(bound))]
588enum Enum<T, K> {
589    V1,
590    V2 {
591        f1: K,
592    },
593    V3(
594        T
595    ),
596}
597```
598
599Or you can set the where predicates by yourself. (NOTE: The `PartialOrd` trait depends on the `PartialEq` (`PartialEq<Self>`) trait.)
600
601```rust
602#[macro_use] extern crate educe;
603
604use std::cmp::Ordering;
605
606trait A {
607    fn partial_cmp(&self, b: &Self) -> Option<Ordering>;
608}
609
610impl A for i32 {
611    fn partial_cmp(&self, b: &i32) -> Option<Ordering> {
612        if self > b {
613            Some(Ordering::Less)
614        } else if self < b {
615            Some(Ordering::Greater)
616        } else {
617            Some(Ordering::Equal)
618        }
619    }
620}
621
622#[derive(Educe)]
623#[educe(PartialEq(bound), PartialOrd(bound = "T: std::cmp::PartialOrd, K: std::cmp::PartialOrd + A"))]
624enum Enum<T, K> {
625    V1,
626    V2 {
627        #[educe(PartialOrd(trait = "A"))]
628        f1: K,
629    },
630    V3(
631        T
632    ),
633}
634```
635
636#### Ranking
637
638Each field can add a `#[educe(PartialOrd(rank = priority_value))]` attribute where `priority_value` is a positive integer value to determine their comparing precedence (lower `priority_value` leads to higher priority). The default `priority_value` for a field dependends on its ordinal (the lower the front) and is always lower than any custom `priority_value`.
639
640```rust
641#[macro_use] extern crate educe;
642
643#[derive(Educe)]
644#[educe(PartialEq, PartialOrd)]
645struct Struct {
646    #[educe(PartialOrd(rank = 1))]
647    f1: u8,
648    #[educe(PartialOrd(rank = 0))]
649    f2: u8,
650}
651```
652
653Each variant can add a `#[educe(PartialOrd(rank = comparison_value))]` attribute where `comparison_value` is a positive integer value to override the value or the ordinal of a variant for comparison.
654
655```rust
656#[macro_use] extern crate educe;
657
658#[derive(Educe)]
659#[educe(PartialEq, PartialOrd)]
660enum Enum {
661    #[educe(PartialOrd(rank = 2))]
662    Two,
663    #[educe(PartialOrd(rank = 1))]
664    One,
665}
666```
667
668## Ord
669
670Use `#[derive(Educe)]` and `#[educe(Ord)]` to implement the `Ord` trait for a struct or an enum. It supports to ignore some fields, or set a trait and/or a method to replace the `Ord` trait used by default. The rank of variants and fields can also be modified.
671
672#### Basic Usage
673
674```rust
675#[macro_use] extern crate educe;
676
677#[derive(Educe)]
678#[educe(PartialEq, Eq, PartialOrd, Ord)]
679struct Struct {
680    f1: u8
681}
682
683#[derive(Educe)]
684#[educe(PartialEq, Eq, PartialOrd, Ord)]
685enum Enum {
686    V1,
687    V2 {
688        f1: u8,
689    },
690    V3(u8),
691}
692```
693
694#### Ignore Fields
695
696The `ignore` attribute can ignore specific fields.
697
698```rust
699#[macro_use] extern crate educe;
700
701#[derive(Educe)]
702#[educe(PartialEq, Eq, PartialOrd, Ord)]
703struct Struct {
704    #[educe(Ord(ignore))]
705    f1: u8
706}
707
708#[derive(Educe)]
709#[educe(PartialEq, Eq, PartialOrd, Ord)]
710enum Enum {
711    V1,
712    V2 {
713        #[educe(Ord(ignore))]
714        f1: u8,
715    },
716    V3(
717        #[educe(Ord(ignore))]
718        u8
719    ),
720}
721```
722
723#### Use Another Method or Trait to Do Comparing
724
725The `trait` and `method` attributes can be used to replace the `Ord` trait for fields. If you only set the `trait` parameter, the `method` will be set to `cmp` automatically by default.
726
727```rust
728#[macro_use] extern crate educe;
729
730use std::cmp::Ordering;
731
732fn cmp(a: &u8, b: &u8) -> Ordering {
733    if a > b {
734        Ordering::Less
735    } else if a < b {
736        Ordering::Greater
737    } else {
738        Ordering::Equal
739    }
740}
741
742trait A {
743    fn cmp(&self, b: &Self) -> Ordering;
744}
745
746impl A for i32 {
747    fn cmp(&self, b: &i32) -> Ordering {
748        if self > b {
749            Ordering::Less
750        } else if self < b {
751            Ordering::Greater
752        } else {
753            Ordering::Equal
754        }
755    }
756}
757
758#[derive(Educe)]
759#[educe(PartialEq, Eq, PartialOrd, Ord)]
760enum Enum<T: std::cmp::PartialOrd + A> {
761    V1,
762    V2 {
763        #[educe(Ord(method = "cmp"))]
764        f1: u8,
765    },
766    V3(
767        #[educe(Ord(trait = "A"))]
768        T
769    ),
770}
771```
772
773#### Generic Parameters Bound to the `Ord` Trait or Others
774
775The `#[educe(Ord(bound))]` attribute can be used to add the `Ord` trait bound to all generaic parameters for the `Ord` implementation.
776
777```rust
778#[macro_use] extern crate educe;
779
780#[derive(Educe)]
781#[educe(PartialEq(bound), Eq(bound), PartialOrd(bound), Ord(bound))]
782enum Enum<T, K> {
783    V1,
784    V2 {
785        f1: K,
786    },
787    V3(
788        T
789    ),
790}
791```
792
793Or you can set the where predicates by yourself. (NOTE: The `Ord` trait depends on the `PartialOrd` (`PartialOrd<Self>`) trait and the `Eq` trait.)
794
795```rust
796#[macro_use] extern crate educe;
797
798use std::cmp::Ordering;
799
800trait A {
801    fn cmp(&self, b: &Self) -> Ordering;
802}
803
804impl A for i32 {
805    fn cmp(&self, b: &i32) -> Ordering {
806        if self > b {
807            Ordering::Less
808        } else if self < b {
809            Ordering::Greater
810        } else {
811            Ordering::Equal
812        }
813    }
814}
815
816#[derive(Educe)]
817#[educe(PartialEq(bound), Eq(bound), PartialOrd(bound), Ord(bound = "T: std::cmp::Ord, K: std::cmp::Ord + A"))]
818enum Enum<T, K> {
819    V1,
820    V2 {
821        #[educe(Ord(trait = "A"))]
822        f1: K,
823    },
824    V3(
825        T
826    ),
827}
828```
829
830#### Ranking
831
832Each field can add a `#[educe(Ord(rank = priority_value))]` attribute where `priority_value` is a positive integer value to determine their comparing precedence (lower `priority_value` leads to higher priority). The default `priority_value` for a field dependends on its ordinal (the lower the front) and is always lower than any custom `priority_value`.
833
834```rust
835#[macro_use] extern crate educe;
836
837#[derive(Educe)]
838#[educe(PartialEq, Eq, PartialOrd, Ord)]
839struct Struct {
840    #[educe(Ord(rank = 1))]
841    f1: u8,
842    #[educe(Ord(rank = 0))]
843    f2: u8,
844}
845```
846
847Each variant can add a `#[educe(Ord(rank = comparison_value))]` attribute where `comparison_value` is a positive integer value to override the value or the ordinal of a variant for comparison.
848
849```rust
850#[macro_use] extern crate educe;
851
852#[derive(Educe)]
853#[educe(PartialEq, Eq, PartialOrd, Ord)]
854enum Enum {
855    #[educe(Ord(rank = 2))]
856    Two,
857    #[educe(Ord(rank = 1))]
858    One,
859}
860```
861
862## Hash
863
864Use `#[derive(Educe)]` and `#[educe(Hash)]` to implement the `Hash` trait for a struct or an enum. It supports to ignore some fields, or set a trait and/or a method to replace the `Hash` trait used by default.
865
866#### Basic Usage
867
868```rust
869#[macro_use] extern crate educe;
870
871#[derive(Educe)]
872#[educe(Hash)]
873struct Struct {
874    f1: u8
875}
876
877#[derive(Educe)]
878#[educe(Hash)]
879enum Enum {
880    V1,
881    V2 {
882        f1: u8,
883    },
884    V3(u8),
885}
886```
887
888#### Ignore Fields
889
890The `ignore` attribute can ignore specific fields.
891
892```rust
893#[macro_use] extern crate educe;
894
895#[derive(Educe)]
896#[educe(Hash)]
897struct Struct {
898    #[educe(Hash(ignore))]
899    f1: u8
900}
901
902#[derive(Educe)]
903#[educe(Hash)]
904enum Enum {
905    V1,
906    V2 {
907        #[educe(Hash(ignore))]
908        f1: u8,
909    },
910    V3(
911        #[educe(Hash(ignore))]
912        u8
913    ),
914}
915```
916
917#### Use Another Method or Trait to Do Hashing
918
919The `trait` and `method` attributes can be used to replace the `Hash` trait for fields. If you only set the `trait` parameter, the `method` will be set to `hash` automatically by default.
920
921```rust
922#[macro_use] extern crate educe;
923
924use std::hash::{Hash, Hasher};
925
926fn hash<H: Hasher>(_s: &u8, state: &mut H) {
927    Hash::hash(&100, state)
928}
929
930trait A {
931    fn hash<H: Hasher>(&self, state: &mut H) {
932        Hash::hash(&100, state)
933    }
934}
935
936impl A for i32 {};
937impl A for u64 {};
938
939#[derive(Educe)]
940#[educe(Hash)]
941enum Enum<T: A> {
942    V1,
943    V2 {
944        #[educe(Hash(method = "hash"))]
945        f1: u8,
946    },
947    V3(
948        #[educe(Hash(trait = "A"))]
949        T
950    ),
951}
952```
953
954#### Generic Parameters Bound to the `Hash` Trait or Others
955
956The `#[educe(Hash(bound))]` attribute can be used to add the `Hash` trait bound to all generaic parameters for the `Hash` implementation.
957
958```rust
959#[macro_use] extern crate educe;
960
961#[derive(Educe)]
962#[educe(Hash(bound))]
963enum Enum<T, K> {
964    V1,
965    V2 {
966        f1: K,
967    },
968    V3(
969        T
970    ),
971}
972```
973
974Or you can set the where predicates by yourself.
975
976```rust
977#[macro_use] extern crate educe;
978
979use std::hash::{Hash, Hasher};
980
981fn hash<H: Hasher>(_s: &u8, state: &mut H) {
982    Hash::hash(&100, state)
983}
984
985trait A {
986    fn hash<H: Hasher>(&self, state: &mut H) {
987        Hash::hash(&100, state)
988    }
989}
990
991impl A for i32 {};
992impl A for u64 {};
993
994#[derive(Educe)]
995#[educe(Hash(bound = "T: std::hash::Hash, K: A"))]
996enum Enum<T, K> {
997    V1,
998    V2 {
999        #[educe(Hash(trait = "A"))]
1000        f1: K,
1001    },
1002    V3(
1003        T
1004    ),
1005}
1006```
1007
1008## Default
1009
1010Use `#[derive(Educe)]` and `#[educe(Default)]` to implement the `Default` trait for a struct, an enum, or a union. It supports to set the default value for your type directly, or set the default values for specific fields.
1011
1012#### Basic Usage
1013
1014For enums and unions, you need to assign a variant (of a enum) and a field (of a union) as default unless the number of variants of an enum or the number of fields of a union is exactly one.
1015
1016```rust
1017#[macro_use] extern crate educe;
1018
1019#[derive(Educe)]
1020#[educe(Default)]
1021struct Struct {
1022    f1: u8
1023}
1024
1025#[derive(Educe)]
1026#[educe(Default)]
1027enum Enum {
1028    V1,
1029    #[educe(Default)]
1030    V2 {
1031        f1: u8,
1032    },
1033    V3(u8),
1034}
1035
1036#[derive(Educe)]
1037#[educe(Default)]
1038union Union {
1039    f1: u8,
1040    #[educe(Default)]
1041    f2: f64,
1042}
1043```
1044
1045#### The Default Value for the Whole Type
1046
1047The `#[educe(Default(expression = "expression"))]` attribute can be used to set the default value for your type by an expression.
1048
1049```rust
1050#[macro_use] extern crate educe;
1051
1052#[derive(Educe)]
1053#[educe(Default(expression = "Struct { f1: 1 }"))]
1054struct Struct {
1055    f1: u8
1056}
1057
1058#[derive(Educe)]
1059#[educe(Default(expression = "Enum::Struct { f1: 1 }"))]
1060enum Enum {
1061    Unit,
1062    Struct {
1063        f1: u8
1064    },
1065    Tuple(u8),
1066}
1067
1068#[derive(Educe)]
1069#[educe(Default(expression = "Union { f1: 1 }"))]
1070union Union {
1071    f1: u8,
1072    f2: f64,
1073}
1074```
1075
1076#### The Default Values for Specific Fields
1077
1078The `#[educe(Default = literal)]` attribute or the `#[educe(Default(expression = "expression"))]` attribute can be used to set the default value for a specific field by a literal value or an expression.
1079
1080```rust
1081#[macro_use] extern crate educe;
1082
1083#[derive(Educe)]
1084#[educe(Default)]
1085struct Struct {
1086    #[educe(Default = 1)]
1087    f1: u8,
1088    #[educe(Default = 11111111111111111111111111111)]
1089    f2: i128,
1090    #[educe(Default = 1.1)]
1091    f3: f64,
1092    #[educe(Default = true)]
1093    f4: bool,
1094    #[educe(Default = "Hi")]
1095    f5: &'static str,
1096    #[educe(Default = "Hello")]
1097    f6: String,
1098    #[educe(Default = 'M')]
1099    f7: char,
1100}
1101
1102#[derive(Educe)]
1103#[educe(Default)]
1104enum Enum {
1105    Unit,
1106    #[educe(Default)]
1107    Tuple(
1108        #[educe(Default(expression = "0 + 1"))]
1109        u8,
1110        #[educe(Default(expression = "-11111111111111111111111111111 * -1"))]
1111        i128,
1112        #[educe(Default(expression = "1.0 + 0.1"))]
1113        f64,
1114        #[educe(Default(expression = "!false"))]
1115        bool,
1116        #[educe(Default(expression = "\"Hi\""))]
1117        &'static str,
1118        #[educe(Default(expression = "String::from(\"Hello\")"))]
1119        String,
1120        #[educe(Default(expression = "'M'"))]
1121        char,
1122    ),
1123}
1124
1125#[derive(Educe)]
1126#[educe(Default)]
1127union Union {
1128    f1: u8,
1129    f2: i128,
1130    f3: f64,
1131    f4: bool,
1132    #[educe(Default = "Hi")]
1133    f5: &'static str,
1134    f6: char,
1135}
1136```
1137
1138#### Generic Parameters Bound to the `Default` Trait or Others
1139
1140The `#[educe(Default(bound))]` attribute can be used to add the `Default` trait bound to all generaic parameters for the `Default` implementation.
1141
1142```rust
1143#[macro_use] extern crate educe;
1144
1145#[derive(Educe)]
1146#[educe(Default(bound))]
1147enum Enum<T> {
1148    Unit,
1149    #[educe(Default)]
1150    Struct {
1151        f1: T
1152    },
1153    Tuple(T),
1154}
1155```
1156
1157Or you can set the where predicates by yourself.
1158
1159```rust
1160#[macro_use] extern crate educe;
1161
1162#[derive(Educe)]
1163#[educe(Default(bound = "T: std::default::Default"))]
1164enum Enum<T> {
1165    Unit,
1166    #[educe(Default)]
1167    Struct {
1168        f1: T
1169    },
1170    Tuple(T),
1171}
1172```
1173
1174#### The `new` Associated Function
1175
1176With the `#[educe(Default(new))]` attribute, your type will have an extra associated function called `new`. That can be used to invoke the `default` method of the `Default` trait.
1177
1178```rust
1179#[macro_use] extern crate educe;
1180
1181#[derive(Educe)]
1182#[educe(Default(new))]
1183struct Struct {
1184    f1: u8
1185}
1186```
1187
1188## Clone
1189
1190Use `#[derive(Educe)]` and `#[educe(Clone)]` to implement the `Clone` trait for a struct, an enum, or a union. It supports to set a trait and/or a method to replace the `Clone` trait used by default.
1191
1192#### Basic Usage
1193
1194```rust
1195#[macro_use] extern crate educe;
1196
1197#[derive(Educe)]
1198#[educe(Clone)]
1199struct Struct {
1200    f1: u8
1201}
1202
1203#[derive(Educe)]
1204#[educe(Clone)]
1205enum Enum {
1206    V1,
1207    V2 {
1208        f1: u8,
1209    },
1210    V3(u8),
1211}
1212```
1213
1214#### Use Another Method or Trait to Do Cloning
1215
1216The `trait` and `method` attributes can be used to replace the `Clone` trait for fields. If you only set the `trait` parameter, the `method` will be set to `clone` automatically by default.
1217
1218```rust
1219#[macro_use] extern crate educe;
1220
1221fn clone(v: &u8) -> u8 {
1222    v + 100
1223}
1224
1225trait A {
1226    fn clone(&self) -> Self;
1227}
1228
1229impl A for i32 {
1230    fn clone(&self) -> i32 {
1231        self + 100
1232    }
1233}
1234
1235impl A for u64 {
1236    fn clone(&self) -> u64 {
1237        self + 100
1238    }
1239}
1240
1241#[derive(Educe)]
1242#[educe(Clone)]
1243enum Enum<T: A> {
1244    V1,
1245    V2 {
1246        #[educe(Clone(method = "clone"))]
1247        f1: u8,
1248    },
1249    V3(
1250        #[educe(Clone(trait = "A"))]
1251        T
1252    ),
1253}
1254```
1255
1256#### Generic Parameters Bound to the `Clone` Trait or Others
1257
1258The `#[educe(Clone(bound))]` attribute can be used to add the `Clone` trait bound or the `Copy` trait bound (if the `#[educe(Copy)]` attribute exists) to all generaic parameters for the `Clone` implementation.
1259
1260```rust
1261#[macro_use] extern crate educe;
1262
1263#[derive(Educe)]
1264#[educe(Clone(bound))]
1265enum Enum<T, K> {
1266    V1,
1267    V2 {
1268        f1: K,
1269    },
1270    V3(
1271        T
1272    ),
1273}
1274```
1275
1276Or you can set the where predicates by yourself.
1277
1278```rust
1279#[macro_use] extern crate educe;
1280
1281fn clone(v: &u8) -> u8 {
1282    v + 100
1283}
1284
1285trait A {
1286    fn clone(&self) -> Self;
1287}
1288
1289impl A for i32 {
1290    fn clone(&self) -> i32 {
1291        self + 100
1292    }
1293}
1294
1295impl A for u64 {
1296    fn clone(&self) -> u64 {
1297        self + 100
1298    }
1299}
1300
1301#[derive(Educe)]
1302#[educe(Clone(bound = "T: std::clone::Clone, K: A"))]
1303enum Enum<T, K> {
1304    V1,
1305    V2 {
1306        #[educe(Clone(trait = "A"))]
1307        f1: K,
1308    },
1309    V3(
1310        T
1311    ),
1312}
1313```
1314
1315#### Union
1316
1317The `#[educe(Clone)]` attribute can be used for a union which also needs to implement the `Copy` trait. The fields of a union cannot be cloned with other methods or traits.
1318
1319```rust
1320#[macro_use] extern crate educe;
1321
1322#[derive(Educe)]
1323#[educe(Copy, Clone)]
1324union Union {
1325    f1: u8,
1326}
1327```
1328
1329## Copy
1330
1331Use `#[derive(Educe)]` and `#[educe(Copy)]` to implement the `Copy` trait for a struct, an enum, or a union.
1332
1333#### Basic Usage
1334
1335```rust
1336#[macro_use] extern crate educe;
1337
1338#[derive(Educe)]
1339#[educe(Copy, Clone)]
1340struct Struct {
1341    f1: u8
1342}
1343
1344#[derive(Educe)]
1345#[educe(Copy, Clone)]
1346enum Enum {
1347    V1,
1348    V2 {
1349        f1: u8,
1350    },
1351    V3(u8),
1352}
1353```
1354
1355#### Generic Parameters Bound to the `Copy` Trait or Others
1356
1357The `#[educe(Copy(bound))]` attribute can be used to add the `Copy` trait bound to all generaic parameters for the `Copy` implementation.
1358
1359```rust
1360#[macro_use] extern crate educe;
1361
1362#[derive(Educe)]
1363#[educe(Copy(bound), Clone(bound))]
1364enum Enum<T, K> {
1365    V1,
1366    V2 {
1367        f1: K,
1368    },
1369    V3(
1370        T
1371    ),
1372}
1373```
1374
1375Or you can set the where predicates by yourself.
1376
1377```rust
1378#[macro_use] extern crate educe;
1379
1380fn clone(v: &u8) -> u8 {
1381    v + 100
1382}
1383
1384trait A {
1385    fn clone(&self) -> Self;
1386}
1387
1388impl A for i32 {
1389    fn clone(&self) -> i32 {
1390        self + 100
1391    }
1392}
1393
1394impl A for u64 {
1395    fn clone(&self) -> u64 {
1396        self + 100
1397    }
1398}
1399
1400#[derive(Educe)]
1401#[educe(Copy(bound = "T: Copy, K: A + Copy"), Clone(bound = "T: Copy, K: A + Copy"))]
1402enum Enum<T, K> {
1403    V1,
1404    V2 {
1405        #[educe(Clone(trait = "A"))]
1406        f1: K,
1407    },
1408    V3(
1409        T
1410    ),
1411}
1412```
1413
1414#### Copy and Clone
1415
1416If you implement both of the `Copy` trait and the `Clone` trait by Educe, the bound for the `Clone` trait needs to include the `Copy` trait due to `Copy, Clone` optimization.
1417
1418## Deref
1419
1420Use `#[derive(Educe)]` and `#[educe(Deref)]` to implement the `Deref` trait for a struct or an enum.
1421
1422#### Basic Usage
1423
1424You need to assign a field as a default inmutable dereferencing field unless the number of fields is exactly one.
1425
1426```rust
1427#[macro_use] extern crate educe;
1428
1429#[derive(Educe)]
1430#[educe(Deref)]
1431struct Struct {
1432    f1: u8,
1433    #[educe(Deref)]
1434    f2: u8,
1435}
1436
1437#[derive(Educe)]
1438#[educe(Deref)]
1439enum Enum {
1440    Struct {
1441        f1: u8
1442    },
1443    Struct2 {
1444        f1: u8,
1445        #[educe(Deref)]
1446        f2: u8,
1447    },
1448    Tuple(u8),
1449    Tuple2(
1450        u8,
1451        #[educe(Deref)]
1452        u8
1453    ),
1454}
1455```
1456
1457## DerefMut
1458
1459Use `#[derive(Educe)]` and `#[educe(DerefMut)]` to implement the `DerefMut` trait for a struct or an enum.
1460
1461#### Basic Usage
1462
1463You need to assign a field as a default mutable dereferencing field unless the number of fields is exactly one.
1464
1465```rust
1466#[macro_use] extern crate educe;
1467
1468#[derive(Educe)]
1469#[educe(Deref, DerefMut)]
1470struct Struct {
1471    f1: u8,
1472    #[educe(Deref, DerefMut)]
1473    f2: u8,
1474}
1475
1476#[derive(Educe)]
1477#[educe(Deref, DerefMut)]
1478enum Enum {
1479    Struct {
1480        f1: u8
1481    },
1482    Struct2 {
1483        f1: u8,
1484        #[educe(Deref, DerefMut)]
1485        f2: u8,
1486    },
1487    Tuple(u8),
1488    Tuple2(
1489        #[educe(DerefMut)]
1490        u8,
1491        #[educe(Deref)]
1492        u8
1493    ),
1494}
1495```
1496
1497The mutable dereferencing fields don't need to be the same as the inmutable dereferencing fields. But their type must be the same.
1498
1499## TODO
1500
1501There is a lot of work to be done. Unimplemented traits are listed below:
1502
15031. `From`
15041. `Into`
15051. `FromStr`
15061. `TryFrom`
15071. `TryInto`
1508
1509*/
1510
1511#![recursion_limit = "128"]
1512
1513#[macro_use]
1514extern crate enum_ordinalize;
1515
1516mod panic;
1517mod support_traits;
1518mod trait_handlers;
1519
1520use std::collections::BTreeMap;
1521
1522use proc_macro2::TokenStream;
1523use quote::ToTokens;
1524use support_traits::Trait;
1525use syn::{DeriveInput, Meta, NestedMeta};
1526use trait_handlers::TraitHandler;
1527
1528fn derive_input_handler(ast: DeriveInput) -> TokenStream {
1529    let mut tokens = TokenStream::new();
1530    let mut trait_meta_map: BTreeMap<Trait, Meta> = BTreeMap::new();
1531
1532    for attr in ast.attrs.iter() {
1533        if attr.path.is_ident("educe") {
1534            let attr_meta = attr.parse_meta().unwrap();
1535
1536            match attr_meta {
1537                Meta::List(list) => {
1538                    for p in list.nested {
1539                        match p {
1540                            NestedMeta::Meta(meta) => {
1541                                let meta_name = meta.path().into_token_stream().to_string();
1542
1543                                let t = Trait::from_str(meta_name);
1544
1545                                if trait_meta_map.contains_key(&t) {
1546                                    panic::reuse_a_trait(t);
1547                                }
1548
1549                                trait_meta_map.insert(t, meta);
1550                            },
1551                            NestedMeta::Lit(_) => {
1552                                panic::educe_format_incorrect();
1553                            },
1554                        }
1555                    }
1556                },
1557                _ => {
1558                    panic::educe_format_incorrect();
1559                },
1560            }
1561        }
1562    }
1563
1564    let traits: Vec<Trait> = trait_meta_map.keys().copied().collect();
1565
1566    #[cfg(feature = "Debug")]
1567    {
1568        if let Some(meta) = trait_meta_map.get(&Trait::Debug) {
1569            trait_handlers::debug::DebugHandler::trait_meta_handler(
1570                &ast,
1571                &mut tokens,
1572                &traits,
1573                meta,
1574            );
1575        }
1576    }
1577
1578    #[cfg(feature = "PartialEq")]
1579    {
1580        if let Some(meta) = trait_meta_map.get(&Trait::PartialEq) {
1581            trait_handlers::partial_eq::PartialEqHandler::trait_meta_handler(
1582                &ast,
1583                &mut tokens,
1584                &traits,
1585                meta,
1586            );
1587        }
1588    }
1589
1590    #[cfg(feature = "Eq")]
1591    {
1592        if let Some(meta) = trait_meta_map.get(&Trait::Eq) {
1593            trait_handlers::eq::EqHandler::trait_meta_handler(&ast, &mut tokens, &traits, meta);
1594        }
1595    }
1596
1597    #[cfg(feature = "PartialOrd")]
1598    {
1599        if let Some(meta) = trait_meta_map.get(&Trait::PartialOrd) {
1600            trait_handlers::partial_ord::PartialOrdHandler::trait_meta_handler(
1601                &ast,
1602                &mut tokens,
1603                &traits,
1604                meta,
1605            );
1606        }
1607    }
1608
1609    #[cfg(feature = "Ord")]
1610    {
1611        if let Some(meta) = trait_meta_map.get(&Trait::Ord) {
1612            trait_handlers::ord::OrdHandler::trait_meta_handler(&ast, &mut tokens, &traits, meta);
1613        }
1614    }
1615
1616    #[cfg(feature = "Hash")]
1617    {
1618        if let Some(meta) = trait_meta_map.get(&Trait::Hash) {
1619            trait_handlers::hash::HashHandler::trait_meta_handler(&ast, &mut tokens, &traits, meta);
1620        }
1621    }
1622
1623    #[cfg(feature = "Default")]
1624    {
1625        if let Some(meta) = trait_meta_map.get(&Trait::Default) {
1626            trait_handlers::default::DefaultHandler::trait_meta_handler(
1627                &ast,
1628                &mut tokens,
1629                &traits,
1630                meta,
1631            );
1632        }
1633    }
1634
1635    #[cfg(feature = "Clone")]
1636    {
1637        if let Some(meta) = trait_meta_map.get(&Trait::Clone) {
1638            trait_handlers::clone::CloneHandler::trait_meta_handler(
1639                &ast,
1640                &mut tokens,
1641                &traits,
1642                meta,
1643            );
1644        }
1645    }
1646
1647    #[cfg(feature = "Copy")]
1648    {
1649        if let Some(meta) = trait_meta_map.get(&Trait::Copy) {
1650            trait_handlers::copy::CopyHandler::trait_meta_handler(&ast, &mut tokens, &traits, meta);
1651        }
1652    }
1653
1654    #[cfg(feature = "Deref")]
1655    {
1656        if let Some(meta) = trait_meta_map.get(&Trait::Deref) {
1657            trait_handlers::deref::DerefHandler::trait_meta_handler(
1658                &ast,
1659                &mut tokens,
1660                &traits,
1661                meta,
1662            );
1663        }
1664    }
1665
1666    #[cfg(feature = "DerefMut")]
1667    {
1668        if let Some(meta) = trait_meta_map.get(&Trait::DerefMut) {
1669            trait_handlers::deref_mut::DerefMutHandler::trait_meta_handler(
1670                &ast,
1671                &mut tokens,
1672                &traits,
1673                meta,
1674            );
1675        }
1676    }
1677
1678    if tokens.is_empty() {
1679        panic::derive_attribute_not_set_up_yet("Educe");
1680    }
1681
1682    tokens
1683}
1684
1685#[proc_macro_derive(Educe, attributes(educe))]
1686pub fn educe_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
1687    derive_input_handler(syn::parse(input).unwrap()).into()
1688}