# auto_enums [![crates.io](https://img.shields.io/crates/v/auto_enums?style=flat-square&logo=rust)](https://crates.io/crates/auto_enums) [![docs.rs](https://img.shields.io/badge/docs.rs-auto__enums-blue?style=flat-square&logo=docs.rs)](https://docs.rs/auto_enums) [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) [![msrv](https://img.shields.io/badge/msrv-1.56-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) [![github actions](https://img.shields.io/github/actions/workflow/status/taiki-e/auto_enums/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/auto_enums/actions) A library for to allow multiple return types by automatically generated enum. This crate is a procedural macro implementation of the features discussions in [rust-lang/rfcs#2414]. This idea is also known as ["Anonymous sum types"][rust-lang/rfcs#294]. 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`: ```toml [dependencies] auto_enums = "0.8" ``` ## 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. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { 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: ```rust fn foo(x: i32) -> impl Iterator { #[::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](tests/expand/enum_derive/example-1.expanded.rs) `#[auto_enum]` can also parse nested arms/branches by using the `#[nested]` attribute. ```rust use auto_enums::auto_enum; #[auto_enum(Iterator)] fn foo(x: i32) -> impl Iterator { match x { 0 => 1..10, #[nested] _ => match x { 1 => vec![5, 10].into_iter(), _ => 0..=x, }, } } ``` See [documentation](https://docs.rs/auto_enums) 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][futures03], [tokio][tokio1], [http_body][http_body1]. **See [documentation](https://docs.rs/auto_enums/latest/auto_enums/#supported-traits) 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][proc-macro-derive], or you can define derives macros yourself ([derive_utils] probably can help it). Basic usage of `#[enum_derive]` ```rust use auto_enums::enum_derive; // `#[enum_derive]` implements `Iterator`, and `#[derive]` implements `Clone`. #[enum_derive(Iterator, Clone)] enum Foo { 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][futures03] traits. - **`futures01`** - Enable to use [futures v0.1][futures01] traits. - **`rayon`** - Enable to use [rayon] traits. - **`serde`** - Enable to use [serde] traits. - **`tokio1`** - Enable to use [tokio v1][tokio1] traits. - **`tokio03`** - Enable to use [tokio v0.3][tokio03] traits. - **`tokio02`** - Enable to use [tokio v0.2][tokio02] traits. - **`tokio01`** - Enable to use [tokio v0.1][tokio01] traits. - **`http_body1`** - Enable to use [http_body v1][http_body1] traits. - **`coroutine_trait`** - Enable to use `[std|core]::ops::Coroutine` 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: ```rust use auto_enums::auto_enum; #[auto_enum] // there is no need to specify std library's traits fn func1(x: i32) -> impl Iterator { 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 = 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][proc-macro-derive] for enums. - [io-enum]: \#\[derive(Read, Write, Seek, BufRead)\] for enums. - [iter-enum]: \#\[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)\] for enums. [derive_utils]: https://github.com/taiki-e/derive_utils [futures01]: https://docs.rs/futures/0.1 [futures03]: https://docs.rs/futures/0.3 [io-enum]: https://github.com/taiki-e/io-enum [iter-enum]: https://github.com/taiki-e/iter-enum [proc-macro-derive]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros [rayon]: https://docs.rs/rayon/1 [rust-lang/rfcs#294]: https://github.com/rust-lang/rfcs/issues/294 [rust-lang/rfcs#2414]: https://github.com/rust-lang/rfcs/issues/2414 [serde]: https://docs.rs/serde/1 [tokio01]: https://docs.rs/tokio/0.1 [tokio02]: https://docs.rs/tokio/0.2 [tokio03]: https://docs.rs/tokio/0.3 [tokio1]: https://docs.rs/tokio/1 [http_body1]: https://docs.rs/http_body/1 ## License Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) 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.