#constructor #derive #tryfrom #try-from #from #struct-fields #field-name

derive_constructors_proc

通过 From、TryFrom 和创建 new_with_*args* 函数进行派生

1 个稳定版本

1.0.0 2024年3月17日

#4 in #tryfrom


derive_constructors 中使用

自定义许可证

42KB
503 代码行

crates.io GitHub Actions Workflow Status docs.rs GitHub License

您正在阅读 derive_constructors 版本 1.0.0 的文档

允许通过提供如字段名称等简单信息来派生多个构造函数,并为结构体实现 [From] 和 [TryFrom] 特性。

还允许为枚举派生 [From]。

1 结构体的 Derive 宏:From 和 TryFrom

参考:derive_constructors_proc::From, derive_constructors_proc::TryFrom

这些允许您在需要将字段元组传递给 From::fromTryFrom::try_from 函数的地方派生 [From] 和 [TryFrom] 特性,例如

#[derive(derive_constructors::From, PartialEq, Debug)]
struct CharacterInfo{
    name: String,
    age: u8,
    #[no_from]
    times_appeared: u8,
    #[no_from(4)]
    years_studied: u8
}

let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_from, expected_character);

2 结构体的属性宏

参考:derive_constructors_proc::constructor

允许您定义一个构造函数,在 proc 属性中,您可以通过以下属性自定义实现(注意每个属性都是可选的)

  • 命名:函数名称,构造函数通常命名为 'with_字段名称',因为调用它们时非常易读,例如 CharacterInfo::with_name_and_age("Jorge", 23)
    注意:如果没有提供此字段,则不会实现 'with_*' 构造函数,而是实现 [From] 或 [TryFrom] 特性。

  • 模式(值:[From, TryFrom],默认:From)

    • 当使用 From 模式时,函数接收字段作为参数并返回具有这些值的此结构体,这通常是您所寻找的。
    • 当使用TryFrom模式时,函数接收实现了Into、Into...等类型的参数,如果所有字段都能成功转换到您的字段,则返回包含您的结构的[Ok],否则返回包含无法初始化的字段和错误原因的[Err],以下示例说明了这一点。
  • 字段(默认值:未包含在'defaults'属性中的所有字段):您要为构造函数创建的字段名称,例如:fields(age, name)可能生成如下函数:fn new(age: u8, name: String) -> CharacterInfo

  • 默认值:说明如何初始化《code>fields属性中未涵盖的字段,例如:defaults(years_studied(4))
    如果一个字段既不在《code>fields也不在《code>defaults属性中,它将视为通过Default::default初始化,这意味着,未涵盖的《code>times_appeared字段将初始化为0(因为u8::default()是0)。

  • error_enum_named(仅适用于TryFrom模式):指定了当TryFrom函数失败时返回的枚举错误的名称。

  • error_enum_metadata(仅适用于TryFrom模式):声明了当TryFrom函数失败时返回的枚举错误的元数据,您可能需要在其中写入error_enum_metadata(#[derive(Debug)])

2.1 示例1:空构造函数

如果您只应用[constructor]属性,它将仅实现[From]特质,其中它将接收一个由所有字段组成的元组,在这种情况下,from(value: (String, u8)) -> CharacterInfo

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor]
struct CharacterInfo{
    name: String,
    age: u8,
}

let character_using_from = CharacterInfo::from(("Jorge".to_string(), 23));
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23 };
assert_eq!(character_using_from, expected_character);

2.2 示例2:使用特定字段的新构造函数

以下示例创建了一个名为new(name: String, age: u8) -> CharacterInfo的函数。

由于指定了《code>years_studied,它将初始化为4,而《code>times_appeared没有指定,它将初始化为u8::default()(即0)。

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor(named(new), fields(name, age), defaults(years_studied(4)))]
struct CharacterInfo{
    name: String,
    age: u8,
    times_appeared: u8,
    years_studied: u8
}

let character_using_from = CharacterInfo::new("Jorge".to_string(), 23);
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_from, expected_character);

2.3 示例3:使用TryFrom模式的新构造函数

以下示例创建了一个名为 new(name: T where String: TryFrom<T>, age: U where String: TryFrom<U>) -> Result<CharacterInfo, MyEnumError> 的函数。

由于指定了《code>years_studied,它将初始化为4,而《code>times_appeared没有指定,它将初始化为u8::default()(即0)。

如果出现错误,它将返回一个名为 MyEnumError 的枚举的变体,此枚举被指定为派生 [Debug] 和 [PartialEq]。

let character_using_try_from = CharacterInfo::new("Jorge", 23_u16).unwrap();
let expected_character = CharacterInfo { name: "Jorge".to_string(), age: 23, times_appeared: 0, years_studied: 4};
assert_eq!(character_using_try_from, expected_character);

let produced_error = u8::try_from(23000_u16).unwrap_err();
let forced_error_using_try_from = CharacterInfo::new("Jorge", 23000_u16).unwrap_err();
let expected_error_on_try_from = MyEnumError::AgeError(produced_error);
assert_eq!(forced_error_using_try_from, expected_error_on_try_from);

#[derive(Debug, PartialEq)]
#[derive_constructors::constructor(
    named(new),
    fields(name, age),
    defaults(years_studied(4)),
    pattern(TryFrom),
    error_enum_named(MyEnumError),
    error_enum_metadata(#[derive(Debug, PartialEq)])
)]
struct CharacterInfo{
    name: String,
    age: u8,
    times_appeared: u8,
    years_studied: u8,
}

3 枚举的 Derive 宏:From

参考:derive_constructors_proc::From

此实现为每个枚举实现了 From 特性,通过在每个枚举上创建一个 From::from 函数,并将每个字段作为值,例如

#[derive(derive_constructors::From, Debug, PartialEq)]
enum MyValue{
    StaticString(&'static str),
    Number(i32),
    Boolean(bool),
}

let scattered_values = vec![MyValue::from("Age "), MyValue::from(23), MyValue::from(", over age "), MyValue::from(true)];
let specified = vec![MyValue::StaticString("Age "), MyValue::Number(23), MyValue::StaticString(", over age "), MyValue::Boolean(true)];
assert_eq!(scattered_values, specified);

依赖项

~2MB
~43K SLoC