The predfined macros
For frequently used traits in std, this library provides macros such as
impl_trait!()
to implement these traits without the need of writing trait
methods.
Syntax of impl_trait!{}
The full form is
#![allow(unused)] fn main() { impl_trait! { _impl!( Generics ) Path::Of::Trait _for!( Type ) _where!( Clause ) } }
Generics
and Clause
are optional:
#![allow(unused)] fn main() { impl_trait!{ _impl!() Path::Of::Trait _for!( Type ) _where!() } }
and the wrapped macros can be omitted:
#![allow(unused)] fn main() { impl_trait!{ Path::Of::Trait _for!( Type )} }
Supported forms of types in _for!()
The _for!()
macro supports two forms of types.
One is ad-hoc enums:
#![allow(unused)] fn main() { impl_trait!{ Path::Of::Trait _for!( Enum![1..=16] )} }
The other is the enum type definition copied in _def!()
macro:
#![allow(unused)] fn main() { impl_trait!{ Path::Of::Trait _for!( _def!( enum Value { Bin( Vec<u8> ), Text( String ), } ))} }
Note: _def!()
does not define any enum, so Value
should have been defined elsewhere.
The _where!()
macro
You can write any where clause in this macro.
Note: you do not need write _where!( _Variants!(): Path::Of::Trait )
which the
impl_trait!{}
macro will generate it silently.
Traits in std prelude
AsRef
AsMut
DoubleEndedIterator
ExactSizeIterator
Extend
Fn
Iterator
The example of implementing Iterator
:
#![allow(unused)] fn main() { impl_trait!{ Iterator _for!( Type )} }
The example of implementing Fn
:
#![allow(unused)] fn main() { impl_trait!{ _impl!(Args) Fn<Args> _for!( Type )} }
Traits with full path
std::error::Error
std::fmt::Debug
std::fmt::Display
std::iter::FusedIterator
std::iter::TrustedLen
std::io::BufRead
std::io::Read
std::io::Seek
std::io::Write
std::ops::Deref
std::ops::DerefMut
std::ops::Generator
std::ops::Index
std::ops::IndexMut
std::ops::RangeBounds
The example of implementing std::ops::Generator
:
#![allow(unused)] fn main() { impl_trait!{ _impl!(R) std::ops::Generator<R> _for!( Type )} }
Unstable traits
To implement these traits, the crate feature "unstable" should be opted in.
Fn
std::iter::TrustedLen
std::ops::Generator
impl_super_traits!{}
and impl_all_traits!{}
The syntax of these two traits are similar with impl_trait!{}
.
The impl_super_traits!{}
macro helps to implement the super trait(s) of the
mentioned trait, e.g. impl_super_traits!{ _impl!(Args) Fn<Args> _for!( Type )}
will implement FnMut
and FnOnce
for Type
, but NOT Fn
.
The impl_all_traits!{}
macro does what impl_trait!{}
and
impl_super_traits!{}
does, e.g.
impl_all_traits!{ _impl!(Args) Fn<Args> _for!( Type )}
will implement Fn
,
FnMut
and FnOnce
for Type
.
macro inheritance
If the library users want to support extra traits, they can write the extra
implementations in their macro, and delegate other traits to
enumx::impl_trait!()
.
#![allow(unused)] fn main() { use enumx::export::{def_impls, impl_all_traits}; macro_rules! impl_trait { ($(_impl!($($gen:tt),*))* ExtraTrait<$t:ident> _for!($($ty:tt)+) $(_where!($($pred:tt)*))*) => { // omitted }; ($($tt:tt)+) => { enumx::impl_trait!{ $($tt)+ } }; } macro_rules! impl_super_traits { ($(_impl!($($gen:tt),*))* ExtraTrait<$t:ident> _for!($($ty:tt)+) $(_where!($($pred:tt)*))*) => { // omitted }; ($($tt:tt)+) => { enumx::impl_super_traits!{ $($tt)+ } }; } }