1个稳定版本
1.0.0 | 2024年3月17日 |
---|
#789 在 Rust模式
22KB
52 行
您正在阅读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 结构体的属性宏
允许你定义一个构造函数,在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
此实现为每个枚举实现 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