6个稳定版本
1.0.5 | 2024年6月27日 |
---|---|
1.0.3 | 2024年6月26日 |
1.0.2 | 2024年6月25日 |
1.0.0 | 2024年6月15日 |
在过程宏中排名201
每月下载量42
46KB
413 行
更好的默认值
具有更多自定义功能和一些升级的std Default derive。
此crate提供了一个名为Default
的单个derive特型。此derive特型充当std Default
derive特型,但允许修改每个字段的默认值。它还允许将具有字段的枚举变体标记为默认值。
功能
- 执行std
Default
derive特型所做的所有事情 - 支持将具有字段的枚举变体标记为默认值
- 支持覆盖每个字段的默认值
- 支持无std,这意味着它将输出无std的代码。**注意,该库本身需要std库**。
请参阅Examples
章节中的所有这些功能。
如何使用
在此处做任何事情之前,如果您想覆盖枚举变体的字段,请**首先将其标记为默认值**
use better_default::Default;
#[derive(Default)]
enum Enum {
#[default]
Variant {
...
},
...
}
1. 覆盖默认值
有两种覆盖默认值的方法:使用逐字段属性或顶层默认属性。
逐字段属性
逐字段属性只是您放在要覆盖默认值的字段之上的属性。
语法如下
#[default( <expression> )]
<field_ident>: <field_type>
您可以在expression
块中放置任何您想要的内容,只要它可以通过syn::Expr正确解析即可。
以下是一个此方法实施的示例
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
#[default] // mark the variant as default (this is mandatory)
Variant1 {
#[default(1)] // set the default value of `first` to 1
first: u32,
// keep the default value for `second`
second: String,
},
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1 { first: 1, second: "" }"
println!("{:?}", default);
}
顶层默认属性
您不需要在结构体/枚举变体的所有字段上放置属性,只需在顶部放置一个属性,其中包含所有默认值覆盖。
顶层属性的语法如下
use better_default::Default;
#[derive(Default)]
#[default((<field_id>: <expression>),*)]
struct Struct {
...
} // the struct can have unnamed fields
#[derive(Default)]
enum Enum {
#[default((<field_id>: <expression>),*)]
Variant { ... } // the variant can have unnamed fields
}
field_id
在这里可以表示两种含义:如果您处理命名字段,则应在此处放置字段标识符。如果您处理未命名字段,则**您应放置字段的顺序**(第一个为0,第二个为1,依此类推)。
再次强调,您可以在 expression
块中放入您想要的任何内容,只要它能被 syn::Expr 正确解析。
以下是两个示例,一个涵盖未命名字段,另一个涵盖已命名字段。
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
// mark the variant as default, and also specifies the default values :
// - the default value of the first field (which is at index 0) is set to 2
// - the second field (which is at index 1) will have it's default value set to "Hello world!"
#[default(0: 2, 1: "Hello world!".to_string())]
Variant1(u32, String),
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1(2, "Hello world!")"
println!("{:?}", default);
}
use better_default::Default;
#[derive(Default, Debug)]
#[default(field1: 1, field2: "Hello world!".to_string())]
struct Struct {
field1: u32,
field2: String
}
fn main() {
let default = Struct::default();
println!("{:?}", default) // should print "Struct { field1: 1, field2: "Hello world!" }"
}
最后一点:这两种方法可以结合使用,这意味着您可以有一个包含一些默认值的顶层属性,同时某些字段有自己的属性。
示例
- 按字段方式:使用按字段属性
按字段属性更适合具有命名字段的 struct / enum 变体。
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
#[default] // mark the variant as default (this is mandatory)
Variant1 {
#[default(1)] // set the default value of `first` to 1
first: u32,
// keep the default value for `second`
second: String,
},
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1 { first: 1, second: "" }"
println!("{:?}", default);
}
use better_default::Default;
#[derive(Default, Debug)]
// Structs don't need to be mark as default with a top attribute. They're optional.
struct Struct {
#[default(10)] // set the default value of field1 to be 10
field1: u32,
// keeps the usual default value for field2
field2: String,
}
fn main() {
let default = Struct::default();
println!("{:?}", default) // should print "Struct { field1: 10, field2: "" }"
}
虽然不推荐,但您也可以在未命名字段上使用它们。
use better_default::Default;
#[derive(Default, Debug)]
// Structs don't need to be mark as default with a top attribute. They're optional.
struct Struct (
#[default(10)] // set the default value of field1 to be 10
u32,
// keeps the usual default value for field2
String,
);
fn main() {
let default = Struct::default();
println!("{:?}", default) // should print "Struct(10, "")"
}
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
#[default] // mark the variant as default (this is mandatory)
Variant1 (
#[default(1)] // set the default value to 1
u32,
// keep the default value
String,
),
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1(1, "")"
println!("{:?}", default);
}
- 一次性方式:使用顶层默认属性
顶层属性的特别之处在于您可以在同一个地方定义所有默认值。
这里不需要表示所有字段,只需要您想修改的字段。
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
// mark the variant as default, and also specifies the default values :
// - the first field keeps it's usual default value.
// - the second field (which is at index 1) will have it's default value set to "Hello world!"
#[default(1: "Hello world!".to_string())]
Variant1(u32, String),
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1(0, "Hello world!")"
println!("{:?}", default);
}
use better_default::Default;
#[derive(Default, Debug)]
// here we can use the top default attribute to customize the default values of our fields.
// - we change the default value of the first field (represented by the index 0) to 1
#[default(0: 1, 1: "a".to_string())]
struct Struct(u32, String);
fn main() {
let default = Struct::default();
println!("{:?}", default) // should print "Struct(1, "a")"
}
这也可以用于命名字段
use better_default::Default;
#[derive(Default, Debug)]
enum Enum {
// mark the variant as default, and also specifies the default values :
// - the first field keeps it's usual default value.
// - the second field (field2) will have it's default value set to "Hello world!"
#[default(field2: "Hello world!".to_string())]
Variant1 {
field1: u32,
field2: String
},
Variant2,
Variant3,
}
fn main() {
let default = Enum::default();
// should print "Variant1 { 0, "Hello world!" }"
println!("{:?}", default);
}
use better_default::Default;
#[derive(Default, Debug)]
#[default(field1: 1, field2: "Hello world!".to_string())]
struct Struct {
field1: u32,
field2: String
}
fn main() {
let default = Struct::default();
println!("{:?}", default) // should print "Struct { field1: 1, field2: "Hello world!" }"
}
贡献
您可以通过创建 pull request 来为项目做出贡献。
以下是我在这个库中使用的工具
- rustdoc-include,它允许我直接将说明文导入到
lib.rs
而无需复制。这就是为什么您可以在lib.rs
中看到那些// #[include_doc(...)]
。使用scripts
文件夹中的build_crate_doc
脚本来更新它们。
许可证
Apache 2.0 许可证。
依赖关系
~315–780KB
~19K SLoC