Derive helper methods for enum variants that are familiar from Option
& Result
such as unwrap_or
or and_then
.
```rust
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())
} ```
In the naming of all methods described here, replace the {variant_name}
with the snake_case formatted name of the given variant.
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.
```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
.
```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
.
```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)
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 if the enum is not of the given variant with the custom message msg
.
```rust
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 if the enum is not of the given variant.
```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
.
```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
.
```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)
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.
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.
rust
let color = Color::HSV(1,2,3);
assert!(color.is_not_rgb());
Note: Available for all variant types
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
.
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.
```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
.
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.
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)
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
enum SomeEnum { #[variantly(rename = "variant_a")] SomeVariantWithALongName(String), VariantB, }
let variant = SomeEnum::SomeVariantWithALongName(String::from("Hello"));
assert!(variant.isvarianta());
``
Methods associated with
SomeVariantWithALongNamewill now be accessible only with the
varianta
suffix, such as
.unwraporelsevarianta(). This can help control overly verbose fn names.
Note that the input to
rename` 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
enum SomeEnum {
#[variantly(rename = "capital")]
ABC,
#[variantly(rename = "lower")]
abc,
}
``
Without the
renameattribute 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.
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.