21个版本 (11个破坏性更新)
0.12.0 | 2023年12月22日 |
---|---|
0.10.0 | 2023年6月29日 |
0.9.0 | 2023年1月16日 |
0.8.0 | 2022年9月7日 |
0.1.3 | 2018年5月31日 |
#18 in 过程宏
142,232 每月下载量
在 367 个crates中使用 (直接使用74个)
56KB
781 行
更简洁的方法委托
此crate消除了将一些方法委托给其字段之一的结构体的部分样板代码。
它提供了一个delegate!
宏,该方法调用委托给选定的表达式(通常是内部字段)。
示例
使用委托实现的Stack数据结构。
use delegate::delegate;
#[derive(Clone, Debug)]
struct Stack<T> {
inner: Vec<T>,
}
impl<T> Stack<T> {
pub fn new() -> Self<T> {
Self { inner: vec![] }
}
delegate! {
to self.inner {
pub fn is_empty(&self) -> bool;
pub fn push(&mut self, value: T);
pub fn pop(&mut self) -> Option<T>;
pub fn clear(&mut self);
#[call(len)]
pub fn size(&self) -> usize;
#[call(last)]
pub fn peek(&self) -> Option<&T>;
}
}
}
功能
-
委托给不同名称的方法
struct Stack { inner: Vec<u32> } impl Stack { delegate! { to self.inner { #[call(push)] pub fn add(&mut self, value: u32); } } }
-
使用任意的内部字段表达式
struct Wrapper { inner: Rc<RefCell<Vec<u32>>> } impl Wrapper { delegate! { to self.inner.deref().borrow_mut() { pub fn push(&mut self, val: u32); } } }
-
委托给枚举变体
use delegate::delegate; enum Enum { A(A), B(B), C { v: C }, } struct A { val: usize, } impl A { fn dbg_inner(&self) -> usize { dbg!(self.val); 1 } } struct B { val_a: String, } impl B { fn dbg_inner(&self) -> usize { dbg!(self.val_a.clone()); 2 } } struct C { val_c: f64, } impl C { fn dbg_inner(&self) -> usize { dbg!(self.val_c); 3 } } impl Enum { delegate! { // transformed to // // ```rust // match self { // Enum::A(a) => a.dbg_inner(), // Enum::B(b) => { println!("i am b"); b }.dbg_inner(), // Enum::C { v: c } => { c }.dbg_inner(), // } // ``` to match self { Enum::A(a) => a, Enum::B(b) => { println!("i am b"); b }, Enum::C { v: c } => { c }, } { fn dbg_inner(&self) -> usize; } } }
-
使用修改器来改变生成的方程序码
use delegate::delegate; struct Inner; impl Inner { pub fn method(&self, num: u32) -> u32 { num } pub fn method_res(&self, num: u32) -> Result<u32, ()> { Ok(num) } } struct Wrapper { inner: Inner } impl Wrapper { delegate! { to self.inner { // calls method, converts result to u64 using `From` #[into] pub fn method(&self, num: u32) -> u64; // calls method, returns () #[call(method)] pub fn method_noreturn(&self, num: u32); // calls method, converts result to i6 using `TryFrom` #[try_into] #[call(method)] pub fn method2(&self, num: u32) -> Result<u16, std::num::TryFromIntError>; // calls method_res, unwraps the result #[unwrap] pub fn method_res(&self, num: u32) -> u32; // calls method_res, unwraps the result, then calls into #[unwrap] #[into] #[call(method_res)] pub fn method_res_into(&self, num: u32) -> u64; // specify explicit type for into #[into(u64)] #[call(method)] pub fn method_into_explicit(&self, num: u32) -> u64; } } }
-
向方法添加额外的参数
struct Inner(u32); impl Inner { pub fn new(m: u32) -> Self { // some "very complex" constructing work Self(m) } pub fn method(&self, n: u32) -> u32 { self.0 + n } } struct Wrapper { inner: OnceCell<Inner>, } impl Wrapper { pub fn new() -> Self { Self { inner: OnceCell::new(), } } fn content(&self, val: u32) -> &Inner { self.inner.get_or_init(|| Inner(val)) } delegate! { to |k: u32| self.content(k) { // `wrapper.method(k, num)` will call `self.content(k).method(num)` pub fn method(&self, num: u32) -> u32; } } }
-
在异步函数上调用
await
struct Inner; impl Inner { pub async fn method(&self, num: u32) -> u32 { num } } struct Wrapper { inner: Inner } impl Wrapper { delegate! { to self.inner { // calls method(num).await, returns impl Future<Output = u32> pub async fn method(&self, num: u32) -> u32; // calls method(num).await.into(), returns impl Future<Output = u64> #[into] #[call(method)] pub async fn method_into(&self, num: u32) -> u64; } } }
您可以在委托方法上使用
#[await(true/false)]
属性来指定是否应在委托表达式后生成.await
。如果委托方法是async
,则默认生成。 -
委托给多个字段
struct MultiStack { left: Vec<u32>, right: Vec<u32>, } impl MultiStack { delegate! { to self.left { /// Push an item to the top of the left stack #[call(push)] pub fn push_left(&mut self, value: u32); } to self.right { /// Push an item to the top of the right stack #[call(push)] pub fn push_right(&mut self, value: u32); } } }
-
自动插入
#[inline(always)]
(除非您在方法上手动指定#[inline]
) -
您可以使用属性对整个段进行操作,以自动将其应用于该段中的所有方法
struct Wrapper { inner: Inner } impl Wrapper { delegate! { #[unwrap] to self.inner { fn foo(&self) -> u32; // calls self.inner.foo().unwrap() fn bar(&self) -> u32; // calls self.inner.bar().unwrap() } } }
-
在签名中指定用作委托参数的表达式
use delegate::delegate; struct Inner; impl Inner { pub fn polynomial(&self, a: i32, x: i32, b: i32, y: i32, c: i32) -> i32 { a + x * x + b * y + c } } struct Wrapper { inner: Inner, a: i32, b: i32, c: i32 } impl Wrapper { delegate! { to self.inner { // Calls `polynomial` on `inner` with `self.a`, `self.b` and // `self.c` passed as arguments `a`, `b`, and `c`, effectively // calling `polynomial(self.a, x, self.b, y, self.c)`. pub fn polynomial(&self, [ self.a ], x: i32, [ self.b ], y: i32, [ self.c ]) -> i32 ; // Calls `polynomial` on `inner` with `0`s passed for arguments // `a` and `x`, and `self.b` and `self.c` for `b` and `c`, // effectively calling `polynomial(0, 0, self.b, y, self.c)`. #[call(polynomial)] pub fn linear(&self, [ 0 ], [ 0 ], [ self.b ], y: i32, [ self.c ]) -> i32 ; } } }
-
使用参数属性修饰符修改输入参数如何传递给委托方法。当前支持以下修饰符:
#[into]
:在传递给委托方法的参数上调用.into()
。#[as_ref]
:在传递给委托方法的参数上调用.as_ref()
。#[newtype]
:访问传递给委托方法的参数的第一个元组元素(.0
)。
use delegate::delegate; struct InnerType {} impl InnerType { fn foo(&self, other: Self) {} } impl From<Wrapper> for InnerType { fn from(wrapper: Wrapper) -> Self { wrapper.0 } } struct Wrapper(InnerType); impl Wrapper { delegate! { to self.0 { // Calls `self.0.foo(other.into());` pub fn foo(&self, #[into] other: Self); // Calls `self.0.bar(other.0);` pub fn bar(&self, #[newtype] other: Self); } } }
许可
根据您选择以下任一项许可:
- Apache License,版本 2.0,(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任您选择。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交的任何贡献,均应按照上述方式双许可,无需附加条款或条件。
行为准则
请遵循 Rust 行为准则。对于升级或调解问题,请联系 Cargo.toml
中列出的 crate 作者。
依赖项
~280–740KB
~18K SLoC