#enum #macros #derive

derive_utils

A procedural macro helper for easily writing derive macros for enums

20 releases

0.10.0 Jun 2, 2020
0.9.1 Sep 15, 2019
0.9.0 Aug 14, 2019
0.8.0 Jun 25, 2019
0.5.3 Dec 27, 2018

#9 in Procedural macros

Download history 4376/week @ 2020-07-07 5117/week @ 2020-07-14 4552/week @ 2020-07-21 4502/week @ 2020-07-28 4741/week @ 2020-08-04 3875/week @ 2020-08-11 5436/week @ 2020-08-18 5945/week @ 2020-08-25 5999/week @ 2020-09-01 6304/week @ 2020-09-08 5484/week @ 2020-09-15 6733/week @ 2020-09-22 6236/week @ 2020-09-29 5659/week @ 2020-10-06 6171/week @ 2020-10-13 6091/week @ 2020-10-20

21,856 downloads per month
Used in 51 crates (6 directly)

Apache-2.0 OR MIT

36KB
501 lines

derive_utils

crates-badge docs-badge license-badge rustc-badge

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

Usage

Add this to your Cargo.toml:

[dependencies]
derive_utils = "0.10"

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.

use derive_utils::quick_derive;
use proc_macro::TokenStream;

#[proc_macro_derive(Iterator)]
pub fn derive_iterator(input: TokenStream) -> TokenStream {
    quick_derive! {
        input,
        // trait path
        std::iter::Iterator,
        // trait definition
        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,
        // trait path
        std::iter::ExactSizeIterator,
        // super trait's associated types
        <Item>,
        // trait definition
        trait ExactSizeIterator: Iterator {
            fn len(&self) -> usize;
        }
    }
}

#[proc_macro_derive(Future)]
pub fn derive_future(input: TokenStream) -> TokenStream {
    quick_derive! {
        input,
        // trait path
        std::future::Future,
        // trait definition
        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, 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> std::iter::Iterator for Enum<A, B>
where
    A: std::iter::Iterator,
    B: std::iter::Iterator<Item = <A as std::iter::Iterator>::Item>,
{
    type Item = <A as std::iter::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> std::iter::ExactSizeIterator for Enum<A, B>
where
    A: std::iter::ExactSizeIterator,
    B: std::iter::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::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),
            }
        }
    }
}

Related Projects

  • auto_enums: A library for to allow multiple return types by automatically generated enum.
  • futures-enum: #[derive(Future, Stream, Sink, AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead)] for enums.
  • io-enum: #[derive(Read, Write, Seek, BufRead)] for enums.
  • iter-enum: #[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)] for enums.

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

~0.4–0.8MB
~20K SLoC