4个版本 (破坏性)
0.4.0 | 2023年11月27日 |
---|---|
0.3.0 | 2023年11月7日 |
0.2.0 | 2021年1月13日 |
0.1.0 | 2020年12月30日 |
在 过程宏 中排名 218
每月下载 6,643 次
在 4 个 库中(直接 2 个)使用
51KB
350 行
Variantly
为从 Option
& Result
中熟悉的枚举变体提供派生辅助方法,例如 unwrap_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())
}
派生方法
在此处描述的所有方法的命名中,将 {variant_name}
替换为给定变体的snake_case格式化名称。
Option & Result 转换
使用以下方法将枚举转换为选项或结果
pub fn {variant_name}(self) ->Option(...)
如果枚举是给定变体,则返回包含内部变体值的 Some
。否则,返回 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());
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_ref(&self) ->Option(&...)
如果枚举是给定变体,则返回包含内部变体值引用的 Some
。否则,返回 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());
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_mut(&mut self) ->Option(&mut...)
如果枚举是给定变体,则返回包含内部变体值可变引用的 Some
。否则,返回 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());
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_or<E>(self,err:E) -> Result<(...), E>
如果枚举是给定变体,则返回包含内部值的 Result::Ok
。否则,返回包含 err
的 Result::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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_ref_or<E>(&self,err:E) -> Result<(&...), E>
如果枚举是给定的变体,则返回一个包含内部值引用的 Result::Ok
。否则,返回包含 err
的 Result::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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_mut_or<E>(&mut self,err:E) -> Result<(&mut...), E>
如果枚举是给定的变体,则返回一个包含内部值可变引用的 Result::Ok
。否则,返回包含 err
的 Result::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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_or_else<E, F: FnOnce() ->E>(self,f:F) -> Result<(...), E>
如果枚举是给定的变体,则返回一个包含内部变体值的 Result::Ok
。否则,调用 f
计算一个 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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_ref_or_else<E, F: FnOnce() ->E>(&self,f:F) -> Result<(&...), E>
如果枚举是给定的变体,则返回一个包含内部变体值引用的 Result::Ok
。否则,调用 f
计算一个 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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn {variant_name}_mut_or_else<E, F: FnOnce() ->E>(&mut self,f:F) -> Result<(&mut...), E>
如果枚举是给定的变体,则返回一个包含内部变体值可变引用的 Result::Ok
。否则,调用 f
计算一个 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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
访问内部值
使用以下方法可以轻松访问给定变体的内部值。
pub fn expect_{variant_name}(self,msg: &str) -> (...)
返回包含的值。
恐慌
如果枚举不是给定的变体,则使用自定义消息 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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn unwrap_{variant_name}(self) -> (...)
返回包含的值。
恐慌
如果枚举不是给定的变体,则引发恐慌。
示例
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);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn unwrap_or_{variant_name}(self,fallback: (...)) -> (...)
如果枚举是给定的变体,则返回包含的值,否则返回提供的 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));
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn unwrap_or_else_{variant_name}<F: FnOnce() -> (...)>(self,f:F) -> (...)
如果枚举是给定的变体,则返回包含的值,否则从 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));
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
测试变体类型
使用以下方法来测试变体是否为给定的类型。
pub fn is_{variant_name}(self) -> bool
如果枚举是给定的变体,则返回 true
。
示例
let color = Color::FromOutOfSpace;
assert!(color.is_from_out_of_space());
注意:适用于所有变体类型
pub fn is_not_{variant_name}(self) -> bool
如果枚举不是给定的变体,则返回 true
。
示例
let color = Color::HSV(1,2,3);
assert!(color.is_not_rgb());
注意:适用于所有变体类型
比较和特定变体处理
使用以下方法处理和比较特定枚举变体。
pub fn and_{variant_name}(self,enum_b:GivenEnum) ->GivenEnum
如果 self 和 enum_b
都是给定的变体,则返回 enum_b
。否则返回 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),
);
适用于所有变体类型
pub fn and_then_{variant_name}<F: FnOnce((...)) -> (...)>(self,f:F) -> Self
如果枚举不是给定的变体,则按原样返回枚举,否则使用包装值调用 f
并返回结果。
示例
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),
);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
pub fn or_{variant_name}(self,enum_b:GivenEnum) ->GivenEnum
如果是给定的变体,则返回 self
,否则返回 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),
);
适用于所有变体类型
pub fn or_else_{variant_name}<F: FnOnce() -> (...)>(self,f:F) -> Self {
如果是给定的变体,则返回 self
,否则调用 f
并返回结果。
示例
let color = Color::HSV(1,2,3);
let color = color.or_else_rgb(|| (4,5,6));
assert_eq!(
color,
Color::RGB(4,5,6),
);
注意:仅适用于元组样式变体,如 Color::RGB(200, 40, 180) 或 Color::Grey(10)
重命名方法
可以将 variantly
属性应用于变体,以便自定义生成的函数名称。属性中设置的 rename
值将用于构建派生函数名称时替换 snake_case 格式的变体名称。
#[derive(variantly::Variantly)]
enum SomeEnum {
#[variantly(rename = "variant_a")]
SomeVariantWithALongName(String),
VariantB,
}
let variant = SomeEnum::SomeVariantWithALongName(String::from("Hello"));
assert!(variant.is_variant_a());
与 SomeVariantWithALongName
相关的函数现在只能使用 variant_a
后缀访问,例如 .unwrap_or_else_variant_a()
。这有助于控制过长的函数名称。请注意,rename
的输入将直接使用,而不会转换为 snake_case。
当两个变体名称会扩展成冲突的方法名称时,上述内容同样适用。
#[derive(variantly::Variantly)]
enum SomeEnum {
#[variantly(rename = "capital")]
ABC,
#[variantly(rename = "lower")]
abc,
}
如果没有上述 rename
属性,两个变体都会创建冲突的函数,例如由于转换为 snake_case 而产生的 .is_abc()
。通过使用 rename
输入创建有意义的和唯一的 fn 名称来避免这种情况。
许可证
在 MIT 许可证 下授权。除非您明确声明,否则任何有意提交以包含在此包中的贡献均应按上述方式授权,不附加任何其他条款或条件。
依赖关系
~2.5MB
~52K SLoC