# Integral enum
A simple way to define integer-like enums.
This macro implements bunch of traits that are usually implemented via looooong `derive(..)` attribute.
# Tour
## IntegralEnum
By default [`IntegralEnum`] assumes that you want all trait implementations: `PartialOrd`, `Ord`, `PartialEq`, `Eq`, `Debug`, `Clone`, `Copy`, `TryFrom`
```rust
use integral_enum::IntegralEnum;
#[derive(IntegralEnum)]
pub enum Sex {
Male,
Female,
}
assert_ne!(Sex::Male, Sex::Female);
assert!(Sex::Female > Sex::Male);
assert_eq!(Sex::try_from(0), Ok(Sex::Male));
assert_eq!(format!("{:?}", Sex::Male), "Male");
assert_eq!(Sex::Female.clone(), Sex::Female);
```
But you may disable some implementations by applying the `#[enum_disable(..)]` attribute (this will fail to compile due to disabled `Debug` trait implementation):
```rust compile_fail
#[derive(IntegralEnum)]
#[enum_disable(debug)]
pub enum Sex {
Male,
Female,
}
assert_eq!(format!("{:?}", Sex::Male), "Male");
```
This is useful if you want to compose [`IntegralEnum`] with some other macro or your own trait implementations, consider example with the `thiserror::Error` macro
(**IT IS MARKED AS COMPILE FAIL ONLY DUE TO LACK OF `thiserror` DEPENDENCY**):
```rust compile_fail
use integral_enum::IntegralEnum;
use thiserror::Error;
#[derive(IntegralEnum, Error)]
pub enum SendError {
#[error("The remote side is closed connection")]
Closed,
#[error("Client with specified id was not found")]
NotFound,
}
```
## StrictIntegralEnum
On the other hand you may want to enable __certain__ implementations, here the [`StrictIntegralEnum`] serves you:
```rust
use integral_enum::StrictIntegralEnum;
#[derive(StrictIntegralEnum)]
#[enum_impl(debug, partial_eq, try_from)]
pub enum Sex {
Male,
Female
}
assert_eq!(Sex::try_from(0), Ok(Sex::Male));
```
There's no other real use-case other than implementing the `try_from`, but I left possibility to autoimplement other traits for convenience.
## Dependencies
Some traits are depending on others, for example `Copy` depends on `Clone`, so, if you disable `Clone` implementation, then `Copy` implementation will be disabled too. For strict enums rules are the same, but differs in details: if you enable `Clone` implementation it will not enable the `Copy`. So, here the dependencies:
- `Clone` depends on `Copy`
- `Eq` depends on `PartialEq`
- `PartialOrd` depends on `Eq`, `Copy`
- `Ord` depends on `PartialOrd`
# Limitations
`IntegralEnum` tries to determine the discriminant exact type based on the following conditions:
- `#[repr(..)]` attribute
- deducing by the number of variants
So, macro will generate wrong code if there is no `#[repr(..)]` or discriminant type will deduced wrongly. It is quite impossible to infer exact discriminant type with the only AST data, consider the following examples:
```rust
// Complete type inference is impossible
const A: u8 = 0;
pub enum TryToDetermineMyTag {
Tag = A,
}
```
```rust
// Deduction is not watching to the enum tag's values
// (it is quite hard or even impossible to do it the correct way as stated above,
// since tags are just expressions, whose types we can't precisely infer and it just,
// overcomplicated? This crate is not a all-in solution, just simple pattern implementation,
// own type-inference will be overkill)
pub enum U16Tag {
Tag = 0xFF_FF,
}
```
And the macro will only get the enum definition, so exact type inference is impossible.