Derive associated functions for enum variants that are familiar from std::option::Option
& std::result::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 function 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.ok_rgb();
assert_eq!(Some((0, 255, 255)), optional_rgb);
// Convert into a Result
let color = Color::RGB(255, 0, 255);
let result_rgb = color.ok_or_rgb("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.ok_or_else_rgb(|| Some("This is a computationally expensive error!"));
assert!(result_rgb.is_err());
// The `#[variantly(rename = "darkness")]` attribute renames associated functions:
let color = Color::Black;
assert!(color.is_darkness())
} ```
The following are supported function types that are derived for all enum variants:
1. is
1. is_not
The following are supported function types that are derived for tuple-like structs. This includes structs that hold one or many tuple style values.
1. and
1. and_then
1. expect
1. ok
1. ok_or
1. ok_or_else
1. or
1. unwrap
1. unwrap_or
1. unwrap_or_else
Derived functions are named by parsing and combining the enum variant they correspond with and the name of the operation they perform. Simplified, this looks like: ```rust use inflector::cases::snakecase::tosnakecase;
fn namefn(operation: String, variantname: String) -> String { let snakecasevariant = tosnakecase(&variantname); format!("{}{}", snakecasevariant, operation) }
fn itmakesaname() { asserteq!( namefn("unwrap","VariantA"), "unwrapvariant_a".into() ) } ```
The varianty
attribute may be placed on a variant in order to customize the resulting associated function names.
```rust
enum SomeEnum {
#[variantly(rename = "varianta")]
SomeVariantWithALongName(String),
VariantB,
}
``
Functions 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 snake_case.
The above is also relevant when two variant names would expand to create conflicting function 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.