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 过程宏

Download history 32390/week @ 2024-04-08 29721/week @ 2024-04-15 31666/week @ 2024-04-22 31566/week @ 2024-04-29 40562/week @ 2024-05-06 36499/week @ 2024-05-13 34662/week @ 2024-05-20 32942/week @ 2024-05-27 42177/week @ 2024-06-03 32832/week @ 2024-06-10 35272/week @ 2024-06-17 33426/week @ 2024-06-24 30099/week @ 2024-07-01 37466/week @ 2024-07-08 35640/week @ 2024-07-15 37506/week @ 2024-07-22

142,232 每月下载量
367 个crates中使用 (直接使用74个)

MIT/Apache

56KB
781

更简洁的方法委托

Build Status Crates.io

此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-2.0 许可证定义的,您有意提交的任何贡献,均应按照上述方式双许可,无需附加条款或条件。

行为准则

请遵循 Rust 行为准则。对于升级或调解问题,请联系 Cargo.toml 中列出的 crate 作者。

依赖项

~280–740KB
~18K SLoC