# derive_utils
[](https://travis-ci.org/taiki-e/derive_utils)
[](https://crates.io/crates/derive_utils/)
[](https://docs.rs/derive_utils/)
[](https://crates.io/crates/derive_utils/)
[](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html)
A procedural macro helper for easily writing [custom derives] for enums.
[custom derives]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-mode-macros
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
derive_utils = "0.7"
```
The current version of derive_utils requires Rust 1.31 or later.
## Examples
`quick_derive!` macro make easy to write `proc_macro_derive` like deriving trait to enum so long as all variants are implemented that trait.
```rust
extern crate proc_macro;
use derive_utils::quick_derive;
use proc_macro::TokenStream;
#[proc_macro_derive(Iterator)]
pub fn derive_iterator(input: TokenStream) -> TokenStream {
quick_derive! {
input,
// trait
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
}
}
}
#[proc_macro_derive(ExactSizeIterator)]
pub fn derive_exact_size_iterator(input: TokenStream) -> TokenStream {
quick_derive! {
input,
// super trait's associated types
Item,
// trait
trait ExactSizeIterator: Iterator {
fn len(&self) -> usize;
}
}
}
#[proc_macro_derive(FusedIterator)]
pub fn derive_fused_iterator(input: TokenStream) -> TokenStream {
quick_derive! {
input,
// super trait's associated types
Item,
// path
(std::iter::FusedIterator),
// trait
trait FusedIterator: Iterator {},
}
}
```
### Generated code
When deriving for enum like the following:
```rust
#[derive(Iterator, ExactSizeIterator, FusedIterator)]
enum Iter<A, B> {
A(A),
B(B),
}
```
Code like this will be generated:
```rust
enum Iter<A, B> {
A(A),
B(B),
}
impl<A, B> Iterator for Iter<A, B>
where
A: Iterator,
B: Iterator<Item = <A as Iterator>::Item>,
{
type Item = <A as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
match self {
Iter::A(x) => x.next(),
Iter::B(x) => x.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
Iter::A(x) => x.size_hint(),
Iter::B(x) => x.size_hint(),
}
}
}
impl<A, B> ExactSizeIterator for Iter<A, B>
where
A: ExactSizeIterator,
B: ExactSizeIterator<Item = <A as Iterator>::Item>,
{
fn len(&self) -> usize {
match self {
Iter::A(x) => x.len(),
Iter::B(x) => x.len(),
}
}
}
impl<A, B> std::iter::FusedIterator for Iter<A, B>
where
A: std::iter::FusedIterator,
B: std::iter::FusedIterator<Item = <A as Iterator>::Item>,
{
}
```
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.