variantly 0.2.0

Derive helper methods for enum variants that are familiar from `std::option::Option` & `std::result::Result` such as `unwrap_or` or `and_then`.
Documentation
# Variantly
Derive helper methods for enum variants that are familiar from `Option` & `Result` such as `unwrap_or` or `and_then`.
# Example
```rust
#[derive(variantly::Variantly)]
enum Color {
    RGB(u8, u8, u8),
    HSV(u8, u8, u8),
    Grey(u8),
    FromOutOfSpace,
    #[variantly(rename = "darkness")]
    Black,
}

fn example() {
    let color = Color::HSV(123, 45, 67);

    // boolean helper method for determining variant:
    assert!(color.is_hsv());
    assert!(!color.is_rgb());

    // Get inner values:
    let (h, s, v) = color.unwrap_hsv();
    assert_eq!((h, s, v), (123, 45, 67));

    // Single values don't require tuple destructuring:
    let color = Color::Grey(128);
    let value = color.unwrap_grey();
    assert_eq!(value, 128);

    // Alter inner value, only if hsv:
    let color = Color::HSV(111, 22, 33);
    let color = color.and_then_hsv(|(h, s, _)| (h, s, 100));
    assert_eq!(color.unwrap_hsv(), (111, 22, 100));

    // Safely unwrap with a fallback:
    let color = Color::RGB(255, 255, 0);
    let (r, g, b) = color.unwrap_or_rgb((0, 0, 0));
    assert_eq!((r, g, b), (255, 255, 0));
    // Since color is of the HSV variant, the default is not used.

    // Safely unwrap using the fallback
    let color = Color::FromOutOfSpace;
    let (r, g, b) = color.unwrap_or_rgb((0, 0, 0));
    assert_eq!((r, g, b), (0, 0, 0));

    // Convert into an Option
    let color = Color::RGB(0, 255, 255);
    let optional_rgb = color.rgb();
    assert_eq!(Some((0, 255, 255)), optional_rgb);

    // Convert into a Result
    let color = Color::RGB(255, 0, 255);
    let result_rgb = color.rgb_or("Error: This is not an RGB variant!");
    assert_eq!(Ok((255, 0, 255)), result_rgb);

    // Operations like this can also use their familiar `_else` versions:
    let color = Color::FromOutOfSpace;
    let result_rgb = color.rgb_or_else(|| Some("This is a computationally expensive error!"));
    assert!(result_rgb.is_err());

    // The `#[variantly(rename = "darkness")]` attribute renames derived methods:
    let color = Color::Black;
    assert!(color.is_darkness())
}
```
# Derived Methods
In the naming of all methods described here, replace the `{variant_name}` with the snake_case formatted name of the given variant.

## Option & Result Conversion
Use the below methods to convert the enum into either an option or result:

### `pub fn {variant_name}(self) -> Option(...)`
If the enum is of the given variant, returns a `Some` containing the inner variant value. Otherwise, return None.

#### Example
```rust
let color = Color::HSV(1,2,3);

let option = color.hsv();
assert_eq!(Some((1, 2, 3)), option);

let color = Color::FromOutOfSpace;
assert_eq!(None, color.rgb());
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

### `pub fn {variant_name}_or<E>(self, err: E) -> Result<(...), E>`
If the enum is of the given variant, returns a `Result::Ok` containing the inner value. Otherwise, return `Result::Err` containing `err`.

#### Example
```rust
let color = Color::HSV(1,2,3);

let result = color.hsv_or("Error: Not an HSV!");
assert_eq!(Ok((1, 2, 3)), result);

let color = Color::FromOutOfSpace;
let result = color.hsv_or("Error: Not an HSV!");
assert_eq!(Err("Error: Not an HSV!"), result);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

### `pub fn {variant_name}_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(...), E>`
If the enum is of the given variant, returns a `Result::Ok` containing the inner variant value. Otherwise, calls `f` to calculate a `Result::Err`.

#### Example
```rust
let color = Color::HSV(1,2,3);

let result = color.hsv_or_else(|| "This is an expensive error to create.");
assert_eq!(Ok((1, 2, 3)), result);

let color = Color::FromOutOfSpace;
let result = color.hsv_or_else(|| "This is an expensive error to create.");
assert_eq!(Err("This is an expensive error to create."), result);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

## Accessing Inner Values
Use the below methods to easily access the inner value of a given variant.

## `pub fn expect_{variant_name}(self, msg: &str) -> (...)`
Returns the contained value.

### Panics
Panics if the enum is not of the given variant with the custom message `msg`.

### Example
```rust
#[derive(variantly::Variantly)]
enum Color {
    HSV(u8, u8, u8),
    Grey(u8),
}

let color_a = Color::HSV(1,2,3);
let color_b = Color::Grey(10);

let (h, s, v) = color_a.expect_hsv("This should be an hsv");
assert_eq!((h, s, v), (1, 2, 3));

let grey = color_b.expect_grey("This should be grey");
assert_eq!(grey, 10);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

## `pub fn unwrap_{variant_name}(self) -> (...)`
Returns the contained value.

### Panics
Panics if the enum is not of the given variant.

### Example
```rust
let color_a = Color::HSV(1,2,3);
let color_b = Color::Grey(10);

let (h, s, v) = color_a.unwrap_hsv();
assert_eq!((h, s, v), (1, 2, 3));

let grey = color_b.unwrap_grey();
assert_eq!(grey, 10);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

## `pub fn unwrap_or_{variant_name}(self, fallback: (...)) -> (...)`
Returns the contained value if the enum is of the given variant, otherwise returns the provided `fallback`.

### Example
```rust
let color_a = Color::HSV(1,2,3);
let color_b = Color::Grey(10);

let (h, s, v) = color_a.unwrap_or_hsv((4, 5, 6));
assert_eq!((h, s, v), (1, 2, 3));

let color = color_b.unwrap_or_rgb((4, 5, 6));
assert_eq!(color, (4, 5, 6));
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

## `pub fn unwrap_or_else_{variant_name}<F: FnOnce() -> (...)>(self, f: F) -> (...)`
Returns the contained value if the enum is of the given variant, otherwise computes a fallback from `f`.

### Example
```rust
let color_a = Color::HSV(1,2,3);
let color_b = Color::Grey(10);

let (h, s, v) = color_a.unwrap_or_else_hsv(|| (4,5,6));
assert_eq!((h, s, v), (1, 2, 3));

let (h, s, v) = color_b.unwrap_or_else_hsv(|| (4,5,6));
assert_eq!((h, s, v), (4, 5, 6));
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

## Testing Variant Type
Use the below methods to test whether a variant is of the given type.

### `pub fn is_{variant_name}(self) -> bool`
Returns `true` if the enum is of the given variant.

#### Example
```rust
let color = Color::FromOutOfSpace;
assert!(color.is_from_out_of_space());
```

*Note: Available for all variant types*

### `pub fn is_not_{variant_name}(self) -> bool`
Returns `true` if the enum is *not* of the given variant.

#### Example
```rust
let color = Color::HSV(1,2,3);
assert!(color.is_not_rgb());
```

*Note: Available for all variant types*

## Compare & Process Specific Variant
Use the below to process and compare a specific enum variant.

### `pub fn and_{variant_name}(self, enum_b: GivenEnum) -> GivenEnum`
Returns `enum_b` if both self and `enum_b` are of the given variant. Otherwise returns `self`.

#### Example
```rust
let color_a = Color::HSV(1,2,3);
let color_b = Color::HSV(4,5,6);
let and = color_a.and_hsv(color_b);
assert_eq!(
    and,
    Color::HSV(4,5,6),
);
```

*Available for all variant types*

### `pub fn and_then_{variant_name}<F: FnOnce((...)) -> (...)>(self, f: F) -> Self`
Returns the enum as is if it is not of the given variant, otherwise calls `f` with the wrapped value and returns the result.

#### Example
```rust
let color_a = Color::HSV(1,2,3);

let and = color_a.and_then_hsv(|(h, s, _)| (h, s, 4));
assert_eq!(
    and,
    Color::HSV(1, 2, 4),
);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

### `pub fn or_{variant_name}(self, enum_b: GivenEnum) -> GivenEnum`
Returns `self` if it is of the given variant, otherwise returns `enum_b`.

#### Example
```rust
let color_a = Color::HSV(1,2,3);
let color_b = Color::RGB(4,5,6);
let or = color_a.or_rgb(color_b);
assert_eq!(
    or,
    Color::RGB(4,5,6),
);
```

*Available for all variant types*

### `pub fn or_else_{variant_name}<F: FnOnce() -> (...)>(self, f: F) -> Self {`
Returns `self` if it is of the given variant, otherwise calls `f` and returns the result.

#### Example
```rust
let color = Color::HSV(1,2,3);
let color = color.or_else_rgb(|| (4,5,6));
assert_eq!(
    color,
    Color::RGB(4,5,6),
);
```

*Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)*

# Renaming Methods
The `variantly` attribute may be placed on a variant in order to customize the resulting method names. The value set against `rename` inside the attribute will be used in place of the snake_cased variant name when constructing derived method names.
```rust
#[derive(variantly::Variantly)]
enum SomeEnum {
    #[variantly(rename = "variant_a")]
    SomeVariantWithALongName(String),
    VariantB,
}

let variant = SomeEnum::SomeVariantWithALongName(String::from("Hello"));
assert!(variant.is_variant_a());
```
Methods associated with `SomeVariantWithALongName` will now be accessible only with the `variant_a`
suffix, such as `.unwrap_or_else_variant_a()`. This can help control overly verbose fn names.
Note that the input to `rename` is used as is and is not coerced into snake_case.

The above is also relevant when two variant names would expand to create conflicting method names:
```rust
#[derive(variantly::Variantly)]
enum SomeEnum {
    #[variantly(rename = "capital")]
    ABC,
    #[variantly(rename = "lower")]
    abc,
}
```
Without the `rename` attribute in the above, both variants would create conflicting functions such as `.is_abc()` due to the coercion to snake_case.
This is avoided by using the rename input to create meaningful and unique fn names.

#### License

<sup>
Licensed under <a href="LICENSE">MIT license</a>.
</sup>

<br>

<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate shall be licensed as above, without any additional terms or conditions.
</sub>