#constructor #derive #tryfrom #try-from #from

derive_constructors

通过提供简单的信息,如字段的名称,派生From、TryFrom以及创建新的with_*args*函数

1个稳定版本

1.0.0 2024年3月17日

#789Rust模式

自定义许可证

22KB
52

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或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属性中,你可以通过以下属性自定义实现(注意每个属性都是可选的)

  • named:函数的名称,构造函数通常以'with_字段名称'的形式命名,如调用它们时相当可读,例如 CharacterInfo::with_name_and_age("Jorge", 23)
    注意:如果没有提供此字段,则不会实现'with_*'构造函数,而是实现[From]或[TryFrom]特质。

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

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

  • 默认值:指定如何初始化 'fields' 属性未涵盖的字段,例如:defaults(years_studied(4))
    如果一个字段既不在 'fields' 也不在 'defaults' 属性中,它将被视为通过 Default::default 初始化,这意味着,未涵盖的 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' 构造函数

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

由于指定了 years_studied,它将被初始化为 4,而由于没有指定 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' 构造函数

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

由于指定了 years_studied,它将被初始化为 4,而由于没有指定 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 trait,通过在每个枚举上创建一个 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