Derive helper methods for enum variants that are familiar from Option
& Result
such as unwrap_or
or and_then
.
#[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())
}
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:
If the enum is of the given variant, returns a Some
containing the inner variant value. Otherwise, return None.
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)
If the enum is of the given variant, returns a Some
containing a ref to the inner variant value. Otherwise, return None.
let color = Color::HSV(1,2,3);
let option = color.hsv_ref();
assert_eq!(Some((&1, &2, &3)), option);
let color = Color::FromOutOfSpace;
assert_eq!(None, color.rgb_ref());
Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)
If the enum is of the given variant, returns a Some
containing a mutable ref to the inner variant value. Otherwise, return None.
let mut color = Color::HSV(1,2,3);
let option = color.hsv_mut();
assert_eq!(Some((&mut 1, &mut 2, &mut 3)), option);
let mut color = Color::FromOutOfSpace;
assert_eq!(None, color.rgb_mut());
Note: Available only for tuple-style variants such as Color::RGB(200, 40, 180), or Color::Grey(10)
If the enum is of the given variant, returns a Result::Ok
containing the inner value. Otherwise, return Result::Err
containing err
.
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)
If the enum is of the given variant, returns a Result::Ok
containing a ref to the inner value. Otherwise, return Result::Err
containing err
.
let color = Color::HSV(1,2,3);
let result = color.hsv_ref_or("Error: Not an HSV!");
assert_eq!(Ok((&1, &2, &3)), result);
let color = Color::FromOutOfSpace;
let result = color.hsv_ref_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)
If the enum is of the given variant, returns a Result::Ok
containing a mutable ref to the inner value. Otherwise, return Result::Err
containing err
.
let mut color = Color::HSV(1,2,3);
let result = color.hsv_mut_or("Error: Not an HSV!");
assert_eq!(Ok((&mut 1, &mut 2, &mut 3)), result);
let mut color = Color::FromOutOfSpace;
let result = color.hsv_mut_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)
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
.
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)
If the enum is of the given variant, returns a Result::Ok
containing a ref to the inner variant value. Otherwise, calls f
to calculate a Result::Err
.
let color = Color::HSV(1,2,3);
let result = color.hsv_ref_or_else(|| "This is an expensive error to create.");
assert_eq!(Ok((&1, &2, &3)), result);
let color = Color::FromOutOfSpace;
let result = color.hsv_ref_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)
If the enum is of the given variant, returns a Result::Ok
containing a mut ref to the inner variant value. Otherwise, calls f
to calculate a Result::Err
.
let mut color = Color::HSV(1,2,3);
let result = color.hsv_mut_or_else(|| "This is an expensive error to create.");
assert_eq!(Ok((&mut 1, &mut 2, &mut 3)), result);
let mut color = Color::FromOutOfSpace;
let result = color.hsv_mut_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)
Use the below methods to easily access the inner value of a given variant.
Returns the contained value.
Panics if the enum is not of the given variant with the custom message msg
.
#[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)
Returns the contained value.
Panics if the enum is not of the given variant.
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)
Returns the contained value if the enum is of the given variant, otherwise returns the provided fallback
.
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)
Returns the contained value if the enum is of the given variant, otherwise computes a fallback from f
.
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)
Use the below methods to test whether a variant is of the given type.
Returns true
if the enum is of the given variant.
let color = Color::FromOutOfSpace;
assert!(color.is_from_out_of_space());
Note: Available for all variant types
Returns true
if the enum is not of the given variant.
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.
Returns enum_b
if both self and enum_b
are of the given variant. Otherwise returns self
.
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
Returns the enum as is if it is not of the given variant, otherwise calls f
with the wrapped value and returns the result.
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)
Returns self
if it is of the given variant, otherwise returns enum_b
.
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
Returns self
if it is of the given variant, otherwise calls f
and returns the result.
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.
#[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:
#[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.
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.