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.hsvor("Error: Not an HSV!"); asserteq!(Ok((1, 2, 3)), result);

let color = Color::FromOutOfSpace; let result = color.hsvor("Error: Not an HSV!"); asserteq!(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.hsvorelse(|| "This is an expensive error to create."); assert_eq!(Ok((1, 2, 3)), result);

let color = Color::FromOutOfSpace; let result = color.hsvorelse(|| "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 colora = Color::HSV(1,2,3); let colorb = Color::Grey(10);

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

let grey = colorb.expectgrey("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 colora = Color::HSV(1,2,3); let colorb = Color::Grey(10);

let (h, s, v) = colora.unwraphsv(); assert_eq!((h, s, v), (1, 2, 3));

let grey = colorb.unwrapgrey(); 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 colora = Color::HSV(1,2,3); let colorb = Color::Grey(10);

let (h, s, v) = colora.unwraporhsv((4, 5, 6)); asserteq!((h, s, v), (1, 2, 3));

let color = colorb.unwraporrgb((4, 5, 6)); asserteq!(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 colora = Color::HSV(1,2,3); let colorb = Color::Grey(10);

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

let (h, s, v) = colorb.unwraporelsehsv(|| (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 = colora.andthenhsv(|(h, s, _)| (h, s, 4)); asserteq!( 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.isvarianta()); `` Methods associated withSomeVariantWithALongNamewill now be accessible only with thevarianta suffix, such as.unwraporelsevarianta(). This can help control overly verbose fn names. Note that the input torename` is used as is and is not coerced into snakecase.

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 therenameattribute in the above, both variants would create conflicting functions such as.isabc()` due to the coercion to snakecase. This is avoided by using the rename input to create meaningful and unique fn names.

License

Licensed under MIT license.


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.