This crate removes some boilerplate for structs that simply delegate some of
their methods to one or more of their fields.
A Stack data structure implemented using an inner Vec via delegation.
-
Delegate to a method with a different name
struct Stack { inner: Vec<u32> }
impl Stack {
delegate! {
to self.inner {
#[call(push)]
pub fn add(&mut self, value: u32);
}
}
}
-
Use an arbitrary inner field expression
struct Wrapper { inner: Rc<RefCell<Vec<u32>>> }
impl Wrapper {
delegate! {
to self.inner.deref().borrow_mut() {
pub fn push(&mut self, val: u32);
}
}
}
-
Delegate to enum variants
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! {
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 modifiers that alter the generated method body
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 {
#[into]
pub fn method(&self, num: u32) -> u64;
#[call(method)]
pub fn method_noreturn(&self, num: u32);
#[try_into]
#[call(method)]
pub fn method2(&self, num: u32) -> Result<u16, std::num::TryFromIntError>;
#[unwrap]
pub fn method_res(&self, num: u32) -> u32;
#[unwrap]
#[into]
#[call(method_res)]
pub fn method_res_into(&self, num: u32) -> u64;
#[into(u64)]
#[call(method)]
pub fn method_into_explicit(&self, num: u32) -> u64;
}
}
}
-
Add additional arguments to method
struct Inner(u32);
impl Inner {
pub fn new(m: u32) -> Self {
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) {
pub fn method(&self, num: u32) -> u32;
}
}
}
-
Call await
on async functions
struct Inner;
impl Inner {
pub async fn method(&self, num: u32) -> u32 { num }
}
struct Wrapper { inner: Inner }
impl Wrapper {
delegate! {
to self.inner {
pub async fn method(&self, num: u32) -> u32;
#[into]
#[call(method)]
pub async fn method_into(&self, num: u32) -> u64;
}
}
}
You can use the #[await(true/false)]
attribute on delegated methods to specify
if .await
should be generated after the delegated expression. It will be
generated by default if the delegated method is async
.
-
Delegate to multiple fields
struct MultiStack {
left: Vec<u32>,
right: Vec<u32>,
}
impl MultiStack {
delegate! {
to self.left {
#[call(push)]
pub fn push_left(&mut self, value: u32);
}
to self.right {
#[call(push)]
pub fn push_right(&mut self, value: u32);
}
}
}
-
Inserts #[inline(always)]
automatically (unless you specify #[inline]
manually on the method)
-
You can use an attribute on a whole segment to automatically apply it to all methods in that segment:
struct Wrapper { inner: Inner }
impl Wrapper {
delegate! {
#[unwrap]
to self.inner {
fn foo(&self) -> u32; fn bar(&self) -> u32; }
}
}
-
Specify expressions in the signature that will be used as delegated arguments
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 {
pub fn polynomial(&self, [ self.a ], x: i32, [ self.b ], y: i32, [ self.c ]) -> i32 ;
#[call(polynomial)]
pub fn linear(&self, [ 0 ], [ 0 ], [ self.b ], y: i32, [ self.c ]) -> i32 ;
}
}
}
-
Modify how will an input parameter be passed to the delegated method with
parameter attribute modifiers. Currently, the following modifiers are
supported:
#[into]
: Calls .into()
on the parameter passed to the delegated method.
#[as_ref]
: Calls .as_ref()
on the parameter passed to the delegated method.
#[newtype]
: Accesses the first tuple element (.0
) of the parameter passed to the delegated method.
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 {
pub fn foo(&self, #[into] other: Self);
pub fn bar(&self, #[newtype] other: Self);
}
}
}
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.