#enum #macros #derive

derive_utils

A procedural macro helper for easily writing derive macros for enums

19 releases (8 breaking)

✓ Uses Rust 2018 edition

0.9.1 Sep 15, 2019
0.8.0 Jun 25, 2019
0.7.0 Mar 13, 2019
0.5.3 Dec 27, 2018

#10 in Procedural macros

Download history 2486/week @ 2019-12-02 3143/week @ 2019-12-09 1734/week @ 2019-12-16 601/week @ 2019-12-23 654/week @ 2019-12-30 1410/week @ 2020-01-06 1934/week @ 2020-01-13 2139/week @ 2020-01-20 2906/week @ 2020-01-27 2889/week @ 2020-02-03 2987/week @ 2020-02-10 2987/week @ 2020-02-17 2340/week @ 2020-02-24 2321/week @ 2020-03-02 2691/week @ 2020-03-09 2582/week @ 2020-03-16

7,007 downloads per month
Used in 27 crates (5 directly)

Apache-2.0/MIT

38KB
650 lines

derive_utils

Build Status Crates.io Docs.rs License Minimum supported Rust version

A procedural macro helper for easily writing derives macros for enums.

Usage

Add this to your Cargo.toml:

[dependencies]
derive_utils = "0.9"

The current 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.

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 {},
    }
}

#[proc_macro_derive(Future)]
pub fn derive_future(input: TokenStream) -> TokenStream {
    quick_derive! {
        input,
        // path
        (std::future::Future),
        // trait
        trait Future {
            type Output;
            fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>)
                -> std::task::Poll<Self::Output>;
        }
    }
}

Generated code

When deriving for enum like the following:

#[derive(Iterator, ExactSizeIterator, FusedIterator, Future)]
enum Enum<A, B> {
    A(A),
    B(B),
}

Code like this will be generated:

enum Enum<A, B> {
    A(A),
    B(B),
}

impl<A, B> Iterator for Enum<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 {
            Enum::A(x) => x.next(),
            Enum::B(x) => x.next(),
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            Enum::A(x) => x.size_hint(),
            Enum::B(x) => x.size_hint(),
        }
    }
}

impl<A, B> ExactSizeIterator for Enum<A, B>
where
    A: ExactSizeIterator,
    B: ExactSizeIterator<Item = <A as Iterator>::Item>,
{
    fn len(&self) -> usize {
        match self {
            Enum::A(x) => x.len(),
            Enum::B(x) => x.len(),
        }
    }
}

impl<A, B> std::iter::FusedIterator for Enum<A, B>
where
    A: std::iter::FusedIterator,
    B: std::iter::FusedIterator<Item = <A as Iterator>::Item>,
{
}

impl<A, B> std::future::Future for Enum<A, B>
where
    A: std::future::Future,
    B: std::future::Future<Output = <A as std::future::Future>::Output>,
{
    type Output = <A as std::future::Future>::Output;

    fn poll(
        self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Self::Output> {
        unsafe {
            match self.get_unchecked_mut() {
                Enum::A(x) => std::pin::Pin::new_unchecked(x).poll(cx),
                Enum::B(x) => std::pin::Pin::new_unchecked(x).poll(cx),
            }
        }
    }
}

License

Licensed under either of

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.

Dependencies

~450–760KB
~18K SLoC