[−][src]Crate educe
Educe
This crate provides procedural macros to help you implement Rust-built-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 ), }
Default
Use #[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.
Basic Usage
For 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.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default)] struct Struct { f1: u8 } #[derive(Educe)] #[educe(Default)] enum Enum { V1, #[educe(Default)] V2 { f1: u8, }, V3(u8), } #[derive(Educe)] #[educe(Default)] union Union { f1: u8, #[educe(Default)] f2: f64, }
The Default Value for the Whole Type
The #[educe(Default(expression = "expression"))]
attribute can be used to set the default value for your type by an expression.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default(expression = "Struct { f1: 1 }"))] struct Struct { f1: u8 } #[derive(Educe)] #[educe(Default(expression = "Enum::Struct { f1: 1 }"))] enum Enum { Unit, Struct { f1: u8 }, Tuple(u8), } #[derive(Educe)] #[educe(Default(expression = "Union { f1: 1 }"))] union Union { f1: u8, f2: f64, }
The Default Values for Specific Fields
The #[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.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default)] struct Struct { #[educe(Default = 1)] f1: u8, #[educe(Default = 11111111111111111111111111111)] f2: i128, #[educe(Default = 1.1)] f3: f64, #[educe(Default = true)] f4: bool, #[educe(Default = "Hi")] f5: &'static str, #[educe(Default = "Hello")] f6: String, #[educe(Default = 'M')] f7: char, } #[derive(Educe)] #[educe(Default)] enum Enum { Unit, #[educe(Default)] Tuple( #[educe(Default(expression = "0 + 1"))] u8, #[educe(Default(expression = "-11111111111111111111111111111 * -1"))] i128, #[educe(Default(expression = "1.0 + 0.1"))] f64, #[educe(Default(expression = "!false"))] bool, #[educe(Default(expression = "\"Hi\""))] &'static str, #[educe(Default(expression = "String::from(\"Hello\")"))] String, #[educe(Default(expression = "'M'"))] char, ), } #[derive(Educe)] #[educe(Default)] union Union { f1: u8, f2: i128, f3: f64, f4: bool, #[educe(Default = "Hi")] f5: &'static str, f6: char, }
Generic Parameters Bound to the Default
Trait or Others
The #[educe(Default(bound))]
attribute can be used to add the Default
trait bound to all generaic parameters for the Default
implementation.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default(bound))] enum Enum<T> { Unit, #[educe(Default)] Struct { f1: T }, Tuple(T), }
Or you can set the where predicates by yourself.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default(bound = "T: std::default::Default"))] enum Enum<T> { Unit, #[educe(Default)] Struct { f1: T }, Tuple(T), }
The new
Associated Function
With 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.
#[macro_use] extern crate educe; #[derive(Educe)] #[educe(Default(new))] struct Struct { f1: u8 }
TODO
There is a lot of work to be done. Unimplemented traits are listed below:
Clone
Copy
PartialOrd
Ord
From
Into
FromStr
TryFrom
Deref
DerefMut
Derive Macros
Educe |