taiki-e/auto_enums

A library for to allow multiple return types by automatically generated enum

This idea is also known as Anonymous sum types

auto_enums

.

This crate is a procedural macro implementation of the features discussions in rust-lang/rfcs#2414. "Anonymous sum types".

This library provides the following attribute macros:

  • #[auto_enum]

    Parses syntax, creates the enum, inserts variants, and passes specified traits to #[enum_derive].

  • #[enum_derive]

    Implements specified traits to the enum.

Usage

Add this to your Cargo.toml:

[dependencies]
auto_enums = "0.7"

Compiler support: requires rustc 1.31+

Examples

#[auto_enum]'s basic feature is to wrap the value returned by the obvious branches (match, if, return, etc..) by an enum that implemented the specified traits.

use auto_enums::auto_enum;

#[auto_enum(Iterator)]
fn foo(x: i32) -> impl Iterator<Item = i32> {
    match x {
        0 => 1..10,
        _ => vec![5, 10].into_iter(),
    }
}

#[auto_enum] generates code in two stages.

First, #[auto_enum] will do the following.

  • parses syntax
  • creates the enum
  • inserts variants

Code like this will be generated:

fn foo(x: i32) -> impl Iterator<Item = i32> {
    #[::auto_enums::enum_derive(Iterator)]
    enum __Enum1<__T1, __T2> {
        __T1(__T1),
        __T2(__T2),
    }

    match x {
        0 => __Enum1::__T1(1..10),
        _ => __Enum1::__T2(vec![5, 10].into_iter()),
    }
}

Next, #[enum_derive] implements the specified traits.

Code like this will be generated

#[auto_enum] can also parse nested arms/branches by using the #[nested] attribute.

use auto_enums::auto_enum;
#[auto_enum(Iterator)]
fn foo(x: i32) -> impl Iterator<Item = i32> {
    match x {
        0 => 1..10,
        #[nested]
        _ => match x {
            1 => vec![5, 10].into_iter(),
            _ => 0..=x,
        },
    }
}

See documentation for more details.

Supported traits

#[enum_derive] implements the supported traits and passes unsupported traits to #[derive].

#[enum_derive] supports many of the standard library traits and some popular third-party libraries traits such as rayon, futures, tokio. See documentation for a complete list of supported traits.

If you want to use traits that are not supported by #[enum_derive], you can use another crate that provides derives macros, or you can define derives macros yourself (derive_utils probably can help it).

Basic usage of #[enum_derive]

use auto_enums::enum_derive;

// `#[enum_derive]` implements `Iterator`, and `#[derive]` implements `Clone`.
#[enum_derive(Iterator, Clone)]
enum Foo<A, B> {
    A(A),
    B(B),
}

Optional features

  • std (enabled by default)
    • Enable to use std library's traits.
  • ops
    • Enable to use [std|core]::ops's Deref, DerefMut, Index, IndexMut, and RangeBounds traits.
  • convert
    • Enable to use [std|core]::convert's AsRef and AsMut traits.
  • fmt
    • Enable to use [std|core]::fmt's traits other than Debug, Display and Write.
  • transpose_methods
    • Enable to use transpose* methods.
  • futures03
    • Enable to use futures v0.3 traits.
  • futures01
    • Enable to use futures v0.1 traits.
  • rayon
    • Enable to use rayon traits.
  • serde
    • Enable to use serde traits.
  • tokio1
    • Enable to use tokio v1 traits.
  • tokio03
    • Enable to use tokio v0.3 traits.
  • tokio02
    • Enable to use tokio v0.2 traits.
  • tokio01
    • Enable to use tokio v0.1 traits.
  • generator_trait
    • Enable to use [std|core]::ops::Generator trait.
    • Note that this feature is unstable and may cause incompatible changes between patch versions.
  • fn_traits
    • Enable to use [std|core]::ops's Fn, FnMut, and FnOnce traits.
    • Note that this feature is unstable and may cause incompatible changes between patch versions.
  • trusted_len
    • Enable to use [std|core]::iter::TrustedLen trait.
    • Note that this feature is unstable and may cause incompatible changes between patch versions.

type_analysis feature

Analyze return type of function and let binding.

Note that this feature is still experimental.

Examples:

use auto_enums::auto_enum;

#[auto_enum] // there is no need to specify std library's traits
fn func1(x: i32) -> impl Iterator<Item = i32> {
    match x {
        0 => 1..10,
        _ => vec![5, 10].into_iter(),
    }
}

#[auto_enum]
fn func2(x: i32) {
    // Unlike `feature(impl_trait_in_bindings)`, this works on stable compilers.
    #[auto_enum]
    let _iter: impl Iterator<Item = i32> = match x {
        0 => Some(0).into_iter(),
        _ => 0..x,
    };
}

Please be careful if you return another traits with the same name.

Related Projects

  • derive_utils: A procedural macro helper for easily writing derives macros for enums.
  • 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 Apache License, Version 2.0 or MIT license at your option.

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.

Issues

Collection of the latest Issues

joshwd36

joshwd36

C-enhancement
Comment Icon1

I've got a situation where a function returns something like Result<impl Iterator<Item = &str>, MyError>, and it would be very useful to be able to use auto_enum on it. Is this technically possible, or is there perhaps a workaround for it?

taiki-e

taiki-e

C-enhancement
Comment Icon1

https://github.com/taiki-e/auto_enums/issues/14#issuecomment-483672675

Another problem is that the current ? operator support generates the same number of variants as the ? operators are used. This may generate code that is less efficient than boxing based error handling for functions that use many ? operators. Since proc_macro doesn't understand types (i.e., it is difficult to optimize that), proc-macro crate, which provides only this feature, it will not be very useful.

I don't know if there is any way to fix this issue at this time.

cc https://github.com/rust-lang/rfcs/issues/2414

Versions

Find the latest versions by id

v0.7.12 - Jan 05, 2021

  • Exclude unneeded files from crates.io.

v0.7.10 - Nov 15, 2020

  • Documentation improvements.

v0.7.9 - Nov 06, 2020

  • Update derive_utils to 0.11.

v0.7.8 - Oct 16, 2020

  • Add support for tokio03::{AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead}.

v0.7.7 - Oct 14, 2020

v0.7.5 - Jun 03, 2020

  • Updated derive_utils to 0.10.

v0.7.3 - Apr 19, 2020

  • Added support for tokio02::{AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead}.

  • Added support for tokio01::{AsyncRead, AsyncWrite}.

  • Added futures03 feature. This is an alias of futures feature.

v0.7.2 - Apr 13, 2020

  • Fix unused braces warnings

  • Update to support latest generator

v0.7.1 - Nov 16, 2019

  • Updated to support futures 0.3.0. (futures feature is no longer unstable)

v0.6.4 - Sep 28, 2019

  • Updated to support futures-preview 0.3.0-alpha.19.

v0.6.2 - Sep 08, 2019

  • Fixed links to generated code.

v0.6.1 - Sep 08, 2019

  • Improved documentation.

v0.6.0 - Sep 07, 2019

(There are no changes since the 0.6.0-alpha.3 release.)

v0.6.0-alpha.3 - Sep 06, 2019

v0.6.0-alpha.1 - Aug 24, 2019

  • Renamed #[rec] to #[nested].

  • Removed never option in argument position in favor of #[enum_derive] attribute.

  • Improved compile time.

  • Added "ops" crate feature, and made [std|core]::ops's Deref, DerefMut, Index, IndexMut, and RangeBounds traits optional.

  • Added "convert" crate feature, and made [std|core]::convert's AsRef and AsMut traits optional.

  • Added "generator_trait" crate feature, and made [std|core]::ops::Generator traits optional. (nightly-only)

  • Added "fn_traits" crate feature, and made Fn, FnMut, and FnOnce traits optional. (nightly-only)

  • Added "trusted_len" crate feature, and made [std|core]::iter::TrustedLen traits optional. (nightly-only)

  • Improved error messages.

v0.5.10 - Aug 15, 2019

  • Updated proc-macro2, syn, and quote to 1.0.

  • Updated derive_utils to 0.9. This improves the error message.

  • Added some generated code examples.

v0.5.9 - Jul 07, 2019

  • Updated to support futures-preview 0.3.0-alpha.17.

  • Added some generated code examples.

v0.5.8 - May 22, 2019

  • Added support for futures::io::{AsyncSeek, AsyncBufRead}.

v0.5.7 - May 12, 2019

  • Updated to new nightly. iovec stabilized. #[enum_derive] automatically detects the rustc version and supports Read::read_vectored and Write::write_vectored as the part of Read and Write.

  • Supported for latest futures 0.3.0-alpha.16.

v0.5.6 - Apr 16, 2019

  • Updated to new nightly.

v0.5.5 - Mar 29, 2019

  • Fixed trait support in "type_analysis" feature.

v0.5.4 - Mar 14, 2019

  • Fixed the problem that "failed to resolve: use of undeclared type or module" (E0433) error is shown when one or more compilation errors occur when multiple #[auto_enum] attributes are used.

  • Improved the error message of #[enum_derive] attribute.

  • Updated minimum derive_utils version to 0.7.0. This improves the error message.

v0.5.3 - Mar 13, 2019

  • Greatly improved the error message of #[auto_enum] attribute.

v0.5.2 - Mar 13, 2019

Information - Updated Sep 20, 2022

Stars: 274
Forks: 8
Issues: 5

tp-note rust based note taking application

Minimalist note taking with save and editing of your clipboard content as-well

tp-note rust based note taking application

mol-swatter is a python lib that uses rust nom to quickly parse through

mol chemical files, build adjacency graphs for the molecule, and match against various functional groups hard coded into the program

mol-swatter is a python lib that uses rust nom to quickly parse through

A library to parse the x86 CPUID instruction, written in rust with no external dependencies

The implementation closely resembles the Intel CPUID manual description

A library to parse the x86 CPUID instruction, written in rust with no external dependencies

A cross platform media service library made in Rust for Node to easily and seamelessly...

A cross platform media service library made in Rust for Node to easily and seamelessly integrate with the operating systems media service API

A cross platform media service library made in Rust for Node to easily and seamelessly...

An embedded rust no_std driver for the AHT20 temperature and humidity sensor, forked from Anthony...

An embedded rust no_std driver for the AHT20 temperature and humidity sensor, forked from Anthony Romano's docs

An embedded rust no_std driver for the AHT20 temperature and humidity sensor, forked from Anthony...

rust-nodejs-bundler

rs with actix feature enabled

rust-nodejs-bundler

nostd_env is an experimental environment to run a Rust no_std

A Rust no_std program runs on QEMU in X86 Long Mode

nostd_env is an experimental environment to run a Rust no_std

An async embedded rust no_std driver for the QMC5883L magnetometer chip based on this driver

An async embedded rust no_std driver for the QMC5883L magnetometer chip based on embassy example

An async embedded rust no_std driver for the QMC5883L magnetometer chip based on this driver
Facebook Instagram Twitter GitHub Dribbble
Privacy