# auto_enums
[![crates.io](https://img.shields.io/crates/v/auto_enums.svg?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)](https://docs.rs/auto_enums)
[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg?style=flat-square)](#license)
[![rustc](https://img.shields.io/badge/rustc-1.31+-blue.svg?style=flat-square)](https://www.rust-lang.org)
[![build status](https://img.shields.io/github/workflow/status/taiki-e/auto_enums/CI/master?style=flat-square)](https://github.com/taiki-e/auto_enums/actions?query=workflow%3ACI+branch%3Amaster)
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.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.
```rust
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:
```rust
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](docs/example-1.md)
`#[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<Item = i32> {
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]. **See [documentation](https://docs.rs/auto_enums/0.7/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, 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][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.
* **`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:
```rust
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.
[derive_utils]: https://github.com/taiki-e/derive_utils
[futures-enum]: https://github.com/taiki-e/futures-enum
[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
## Related Projects
* [derive_utils]: A procedural macro helper for easily writing [derives macros][proc-macro-derive] 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](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.