[−][src]Crate educe
Educe
This crate provides procedural macros to help you implement Rust-build-in traits quickly.
Debug
Use #[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.
Basic Usage
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug)] struct Struct { f1: u8 } #[derive(Educe)] #[educe(Debug)] enum Enum { V1, V2 { f1: u8, }, V3(u8), }
Change the Name of a Type, a Variant or a Field
The name
attribute can help you rename a type, a variant or a field.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug(name = "Struct2"))] struct Struct { #[educe(Debug(name = "f"))] f1: u8 } #[derive(Educe)] #[educe(Debug(name = true))] enum Enum { #[educe(Debug(name = false))] V1, #[educe(Debug(name = "V"))] V2 { #[educe(Debug(name = "f"))] f1: u8, }, #[educe(Debug(name = false))] V3(u8), }
Ignore Fields
The ignore
attribute can ignore specific fields.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug)] struct Struct { #[educe(Debug(ignore))] f1: u8 } #[derive(Educe)] #[educe(Debug)] enum Enum { V1, V2 { #[educe(Debug(ignore))] f1: u8, }, V3( #[educe(Debug(ignore))] u8 ), }
Fake Structs and Tuples
With the named_field
attribute, structs can be formatted as tuples and tuples can be formatted as structs.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug(named_field = false))] struct Struct { f1: u8 } #[derive(Educe)] #[educe(Debug)] enum Enum { V1, #[educe(Debug(named_field = false))] V2 { f1: u8, }, #[educe(Debug(named_field = true))] V3( u8, #[educe(Debug(name = "value"))] i32 ), }
Use Another Method or Trait to Do the Format Thing
The format
attribute has two parameters: trait
and method
. They can be used to replace the Debug
trait on fields. If you only set the trait
parameter, the method
will be set to fmt
automatically by default.
#[macro_use] extern crate educe; use std::fmt::{self, Formatter}; fn fmt(_s: &u8, f: &mut Formatter) -> fmt::Result { f.write_str("Hi") } trait A { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str("Hi") } } impl A for i32 {}; impl A for u64 {}; #[derive(Educe)] #[educe(Debug)] enum Enum<T: A> { V1, V2 { #[educe(Debug(format(method = "fmt")))] f1: u8, }, V3( #[educe(Debug(format(trait = "std::fmt::UpperHex")))] u8, #[educe(Debug(format(trait = "A")))] T ), }
Generic Parameters Bound to the Debug
Trait or Others
The #[educe(Debug(bound))]
attribute can be used to add the Debug
trait bound to all generaic parameters for the Debug
implementation.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug(bound))] enum Enum<T, K> { V1, V2 { f1: K, }, V3( T ), }
Or you can set the where predicates by yourself.
#[macro_use] extern crate educe; use std::fmt::{self, Formatter}; fn fmt(_s: &u8, f: &mut Formatter) -> fmt::Result { f.write_str("Hi") } trait A { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str("Hi") } } impl A for i32 {}; impl A for u64 {}; #[derive(Educe)] #[educe(Debug(bound = "T: std::fmt::Debug, K: A"))] enum Enum<T, K> { V1, V2 { #[educe(Debug(format(trait = "A")))] f1: K, }, V3( T ), }
Union
A 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.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Debug)] struct Union { f1: u8, f2: i32, }
PartialEq
Use #[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.
Basic Usage
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(PartialEq)] struct Struct { f1: u8 } #[derive(Educe)] #[educe(PartialEq)] enum Enum { V1, V2 { f1: u8, }, V3(u8), }
Ignore Fields
The ignore
attribute can ignore specific fields.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(PartialEq)] struct Struct { #[educe(PartialEq(ignore))] f1: u8 } #[derive(Educe)] #[educe(PartialEq)] enum Enum { V1, V2 { #[educe(PartialEq(ignore))] f1: u8, }, V3( #[educe(PartialEq(ignore))] u8 ), }
Use Another Method or Trait to Do Comparing
The compare
attribute has two parameters: trait
and method
. They can be used to replace the PartialEq
trait on fields. If you only set the trait
parameter, the method
will be set to hacomparesh
automatically by default.
#[macro_use] extern crate educe; fn eq(a: &u8, b: &u8) -> bool { a + 1 == *b } trait A { fn eq(&self, b: &Self) -> bool; } impl A for i32 { fn eq(&self, b: &i32) -> bool { self + 1 == *b } } impl A for u64 { fn eq(&self, b: &u64) -> bool { self + 1 == *b } } #[derive(Educe)] #[educe(PartialEq)] enum Enum<T: A> { V1, V2 { #[educe(PartialEq(compare(method = "eq")))] f1: u8, }, V3( #[educe(PartialEq(compare(trait = "A")))] T ), }
Generic Parameters Bound to the PartialEq
Trait or Others
The #[educe(PartialEq(bound))]
attribute can be used to add the PartialEq
trait bound to all generaic parameters for the PartialEq
implementation.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(PartialEq(bound))] enum Enum<T, K> { V1, V2 { f1: K, }, V3( T ), }
Or you can set the where predicates by yourself.
#[macro_use] extern crate educe; fn eq(a: &u8, b: &u8) -> bool { a + 1 == *b } trait A { fn eq(&self, b: &Self) -> bool; } impl A for i32 { fn eq(&self, b: &i32) -> bool { self + 1 == *b } } impl A for u64 { fn eq(&self, b: &u64) -> bool { self + 1 == *b } } #[derive(Educe)] #[educe(PartialEq(bound = "T: std::cmp::PartialEq, K: A"))] enum Enum<T, K> { V1, V2 { #[educe(PartialEq(compare(trait = "A")))] f1: K, }, V3( T ), }
Eq
Use #[derive(Educe)]
and #[educe(Eq)]
to implement the Eq
trait for a struct, an enum or a union.
Basic Usage
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(PartialEq, Eq)] struct Struct { f1: u8 } #[derive(Educe)] #[educe(PartialEq, Eq)] enum Enum { V1, V2 { f1: u8, }, V3(u8), }
Generic Parameters Bound to the Eq
Trait or Others
The #[educe(Eq(bound))]
attribute can be used to add the Eq
trait bound to all generaic parameters for the Eq
implementation.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(PartialEq(bound), Eq(bound))] enum Enum<T, K> { V1, V2 { f1: K, }, V3( T ), }
Or you can set the where predicates by yourself. (NOTE: The Eq
trait depends on the PartialEq
(PartialEq<Self>
) trait.)
#[macro_use] extern crate educe; fn eq(a: &u8, b: &u8) -> bool { a + 1 == *b } trait A { fn eq(&self, b: &Self) -> bool; } impl A for i32 { fn eq(&self, b: &i32) -> bool { self + 1 == *b } } impl A for u64 { fn eq(&self, b: &u64) -> bool { self + 1 == *b } } #[derive(Educe)] #[educe(PartialEq(bound = "T: std::cmp::PartialEq, K: A"), Eq(bound = "T: std::cmp::PartialEq, K: A"))] enum Enum<T, K> { V1, V2 { #[educe(PartialEq(compare(trait = "A")))] f1: K, }, V3( T ), }
Hash
Use #[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.
Basic Usage
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Hash)] struct Struct { f1: u8 } #[derive(Educe)] #[educe(Hash)] enum Enum { V1, V2 { f1: u8, }, V3(u8), }
Ignore Fields
The ignore
attribute can ignore specific fields.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Hash)] struct Struct { #[educe(Hash(ignore))] f1: u8 } #[derive(Educe)] #[educe(Hash)] enum Enum { V1, V2 { #[educe(Hash(ignore))] f1: u8, }, V3( #[educe(Hash(ignore))] u8 ), }
Use Another Method or Trait to Do Hashing
The hash
attribute has two parameters: trait
and method
. They can be used to replace the Hash
trait on fields. If you only set the trait
parameter, the method
will be set to hash
automatically by default.
#[macro_use] extern crate educe; use std::hash::{Hash, Hasher}; fn hash<H: Hasher>(_s: &u8, state: &mut H) { Hash::hash(&100, state) } trait A { fn hash<H: Hasher>(&self, state: &mut H) { Hash::hash(&100, state) } } impl A for i32 {}; impl A for u64 {}; #[derive(Educe)] #[educe(Hash)] enum Enum<T: A> { V1, V2 { #[educe(Hash(hash(method = "hash")))] f1: u8, }, V3( #[educe(Hash(hash(trait = "A")))] T ), }
Generic Parameters Bound to the Hash
Trait or Others
The #[educe(Hash(bound))]
attribute can be used to add the Hash
trait bound to all generaic parameters for the Hash
implementation.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Hash(bound))] enum Enum<T, K> { V1, V2 { f1: K, }, V3( T ), }
Or you can set the where predicates by yourself.
#[macro_use] extern crate educe; use std::hash::{Hash, Hasher}; fn hash<H: Hasher>(_s: &u8, state: &mut H) { Hash::hash(&100, state) } trait A { fn hash<H: Hasher>(&self, state: &mut H) { Hash::hash(&100, state) } } impl A for i32 {}; impl A for u64 {}; #[derive(Educe)] #[educe(Hash(bound = "T: std::hash::Hash, K: A"))] enum Enum<T, K> { V1, V2 { #[educe(Hash(hash(trait = "A")))] f1: K, }, V3( T ), }
TODO
There is a lot of work to be done. Unimplemented traits are listed below:
Default
Clone
Copy
PartialOrd
Ord
From
Into
FromStr
TryFrom
Deref
DerefMut
Derive Macros
Educe |