What is the idiomatic way to represent the adapter pattern in Rust?


#1

I have a trait Foo that exposes a number of methods. I want to create an adapter Bar that delegates (passes through) all calls to the Foo implementation except one, which it wraps. Is there a way to cleanly do this without having to write all the pass-through methods?


trait Foo {
  fn method_0();  // <-- I need to wrap this
  fn method_1();
  fn method_2();
  // ...
}

struct Adapter<F: Foo> {
  wrapped: F
}

// How do I structure Adapter so that I don't have to
// create pass-throughs for all of Foo's implementation?


#2

There is no way to do it.


#3

There’s no simple + idiomatic way to do it. The simple way is to use Deref, which is not considered idiomatic. The idiomatic way is to create the pass-throughs yourself.


#4

In case it wasn’t clear from @steveklabnik’s comment, don’t use Deref for this. It’s too easy to accidentally Deref and call the method on the Deref target (been there, done that).


#5

I’m hoping that we can develop some kind of macro-based solution. Either using macros 1.1, 2.0 or existing macro-rules (macro-attr crate?) to make this easier.

Cover your eyes, this is a bit insane, but it’s a macro that creates a trait implementation macro from the trait’s definition. The implementation macro can only make straight delegation impls. (Think delegating from Foo<T> to T or from &T to T).

Trait definition and macro definition; and application. That’s about half way there, needs some way to plug in and replace just the method you wanted to override, and it needs to support more self modes, and need fewer annotations.


#6

Just “for science” how would I use Deref to do this? Is there an example you can point me to?


#7

I’m kinda amazed, and terrified - in equal parts :slight_smile: I’ll take a closer look later tonight!


#8

There is some exaplanation here.

I also made an example overriding only one method: https://is.gd/iYw5kb


#9

Nice work @bluss, anything to make life easier. :grinning:

@allengeorge there’s an RFC for this, delegation of implementation. I hope it gets accepted.