#variant #enums #variant-name #methods #helper #familiar #derive

variantly

为从 std::option::Option & std::result::Result 中熟悉的枚举变体提供派生辅助方法,例如 unwrap_orand_then

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

Download history 68/week @ 2024-04-09 171/week @ 2024-04-16 76/week @ 2024-04-23 22/week @ 2024-04-30 44/week @ 2024-05-07 52/week @ 2024-05-14 49/week @ 2024-05-21 943/week @ 2024-05-28 1599/week @ 2024-06-04 1606/week @ 2024-06-11 1269/week @ 2024-06-18 1513/week @ 2024-06-25 1770/week @ 2024-07-02 1452/week @ 2024-07-09 1301/week @ 2024-07-16 1611/week @ 2024-07-23

每月下载 6,643
4 库中(直接 2 个)使用

MIT 许可证

51KB
350

Variantly

为从 Option & Result 中熟悉的枚举变体提供派生辅助方法,例如 unwrap_orand_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。否则,返回包含 errResult::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。否则,返回包含 errResult::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。否则,返回包含 errResult::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