61 个版本 (稳定版)
4.0.1 | 2024 年 8 月 1 日 |
---|---|
4.0.0 | 2023 年 10 月 9 日 |
4.0.0-alpha.6 | 2023 年 2 月 7 日 |
4.0.0-alpha.2 | 2022 年 12 月 8 日 |
0.1.2 | 2020 年 7 月 3 日 |
#14 在 #patterns
23,694 每月下载量
用于 90 个 crate (15 直接使用)
255KB
5K SLoC
Rust Amplify 库:派生宏
增强 Rust 语言功能:多个泛型特质的实现,类型包装,派生宏。
这是 Rust 语言增强库的一部分,提供所需的派生宏。
最低支持的 Rust 编译器版本 (MSRV):1.60.0。Rust 版本 2021。
概述
显示派生
- 使用其他格式化特质生成
Display
描述#[derive(Display, Debug)] #[display(Debug)] struct Some { /* ... */ }
- 使用现有函数显示描述
格式化函数必须返回#[derive(Display)] #[display(Int::print)] union Int { uint: u32, int: i32 }; impl Int { pub fn print(&self) -> String { s!("Integer representation") } }
String
并接受单个self
参数(如果您需要带有流式输出的格式化,请使用第 1 部分中所示的一个现有格式化特质)。 - 自定义格式字符串
#[derive(Display)] #[display("({x}, {y})")] struct Point { x: u32, y: u32 }
- 使用文档注释来表示描述。在这种情况下,文档注释也可能包含类似于情况 3 的格式化
您还可以在此模式下与其他特定选项上的显示标签混合;在这种情况下,文档注释将被忽略#[macro_use] extern crate amplify; #[derive(Display)] #[display(doc_comments)] enum Variants { /// Letter A A, /// Letter B B, /// This comment is ignored #[display("Letter C")] C, /// Letter {_0} Letter(String) }; assert_eq!(format!("{}", Variants::C), "Letter C"); assert_eq!(format!("{}", Variants::Letter(s!("K"))), " Letter K");
示例
高级使用枚举
#[derive(Debug, Display)]
#[display(Debug)]
enum Test {
Some,
#[display = "OtherName"]
Other,
Named {
x: u8,
},
#[display = "Custom{x}"]
NamedCustom {
x: u8,
},
Unnamed(u16),
// NB: Use `_`-prefixed indexes for tuple values
#[display = "Custom{_0}"]
UnnamedCustom(String),
}
错误派生
错误推导宏仅在与其他错误推导宏一起使用时才能完全工作。使用 #[derive(Display)]
和 [display(doc_comments)]
时,它使用文档注释来生成错误描述;使用 #[derive(From)]
时,它可以自动实现来自其他错误类型的转换。
#[derive(Debug, Display, Error)]
#[display(doc_comments)]
enum Error {
/// I/O operation error
Io,
/// Math overflow
Overflow,
/// Zero division with {_0}
ZeroDivision(u16),
}
来自 derive
实现了整个实体及其单独字段的对 From
特质的实现。与 #[derive(Error)]
一起工作良好,并且在许多情况下可能需要 Default
的实现(详细信息,请参见下面的示例)
示例
#[derive(From, Default)]
#[from(::std::io::Error)]
// Structure may contain no parameters
pub struct IoErrorUnit;
#[derive(From, Default)]
#[from(::std::io::Error)] // When no explicit binding is given, structure must implement `Default`
pub struct IoError {
details: String,
#[from]
kind: IoErrorUnit,
}
#[derive(From)]
pub enum Error {
// You can specify multiple conversions with separate attributes
#[from(::std::io::Error)]
#[from(IoError)]
Io,
#[from]
Format(::std::fmt::Error),
#[from]
WithFields { details: ::std::str::Utf8Error },
MultipleFields {
// ...and you can also covert error type
#[from(IoErrorUnit)]
// rest of parameters must implement `Default`
io: IoError,
details: String,
},
}
#[derive(From)]
pub struct Wrapper(u32, i16);
包装推导
创建一个包装现有类型的 rust 新类型。可用于包含多个命名或未命名字段的结构体中;在这种情况下,您希望包装的字段应该用 #[wrap]
属性标记;否则假定第一个字段是包装的字段。
使用多个字段需要您在主结构体上实现 From
和 Default
的推导。
支持自动实现以下特质
放大::包装器
AsRef
AsMut
借用
借用Mut
Deref
DerefMut
只有在使用带有 trivial_bounds
特性门和 nightly
特性集的夜间 rust 编译器的夜间 rust 编译器时,才能完整使用此推导宏。这将为额外的特质提供自动实现,如果它们为包装类型实现
显示
LowerHex
UpperHex
LowerExp
UpperExp
八进制
索引
索引Mut
加
加分配
减
减分配
乘
乘分配
除
除分配
其他特质,如 PartialEq
、Eq
、PartialOrd
、Ord
、Hash
可以通过在相同的 #[derive]
属性中实现,与 Default
、Debug
和 From
以相同的方式实现
示例
use std::marker::PhantomData;
use amplify::Wrapper;
#[derive(Clone, Wrapper, Default, From, Debug)]
struct Wrapped<T, U>(
#[wrap]
#[from]
HashMap<usize, Vec<U>>,
PhantomData<T>,
)
where
U: Sized + Clone;
let w = Wrapped::<(), u8>::default();
assert_eq!(w.into_inner(), HashMap::<usize, Vec<u8>>::default());
获取器推导
为结构体内的所有字段(包括公共和私有字段)创建与字段名称匹配的获取器方法。获取器返回引用类型。
示例
#[derive(Getters, Default)]
struct One {
a: Vec<u8>,
pub b: bool,
pub(self) c: u8,
}
let one = One::default();
assert_eq!(one.a(), &Vec::<u8>::default());
assert_eq!(one.b(), &bool::default());
assert_eq!(one.c(), &u8::default());
AsAny derive
特性 amplify::AsAny
允许将任何类型简单地转换为通用的“胖”指针 &dyn Any
(参见 ::core::any::Any
),之后可以将它转换回原始类型,对于所有其他转换将以优雅的方式失败。`AsAny` derive 宏允许在任意类型上轻松实现此特性。
示例
# #[macro_use] extern crate amplify_derive;
extern crate amplify;
use amplify::AsAny;
#[derive(AsAny, Copy, Clone, PartialEq, Eq, Debug)]
struct Point {
pub x: u64,
pub y: u64,
}
#[derive(AsAny, PartialEq, Debug)]
struct Circle {
pub radius: f64,
pub center: Point,
}
let mut point = Point { x: 1, y: 2 };
let point_ptr = point.as_any();
let mut circle = Circle {
radius: 18.,
center: point,
};
let circle_ptr = circle.as_any();
assert_eq!(point_ptr.downcast_ref(), Some(&point));
assert_eq!(circle_ptr.downcast_ref(), Some(&circle));
assert_eq!(circle_ptr.downcast_ref::<Point>(), None);
let p = point_ptr.downcast_ref::<Point>().unwrap();
assert_eq!(p.x, 1)
依赖项
~1.5MB
~36K SLoC