I would like to create a variation of a SOCKS5 proxy using asynchronous IO. I've done this before in Haskell so I thought would be a good learning challenge. I am starting with the very well-documented SOCKS5 example code.
In the example, the Transfer
struct requires the reader and writer to be of type TcpStream
. In my code these need to be polymorphic, so I started by defining:
pub trait Pollable {
fn poll_read(&self) -> Async<()>;
fn poll_write(&self) -> Async<()>;
}
impl Pollable for TcpStream {
fn poll_read(&self) -> Async<()> {
tokio_core::net::TcpStream::poll_read(&self)
}
fn poll_write(&self) -> Async<()> {
tokio_core::net::TcpStream::poll_write(&self)
}
}
pub trait AsyncStream: tokio_io::AsyncRead + tokio_io::AsyncWrite + Pollable {}
impl<T> AsyncStream for T
where
T: tokio_io::AsyncRead + tokio_io::AsyncWrite + Pollable,
{}
When I switch the type of reader
at line 510 from Rc<TcpStream>
to Rc<AsyncStream>
, the compiler fails with this error on line 598:
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/transfer.rs:125:33
|
125 | let n = try_nb!((&*self.reader).read(&mut buffer));
| ^^^^^^^^^^^^^^^ cannot borrow as mutable
Ignore the file and line number in the error message; I'm in the middle of moving the code around to multiple files but it is otherwise identical to the example.
Following advice I found elsewhere on Stack Overflow, I checked the types. Before the change, the type of &*self.reader
is &tokio_core::net::TcpStream
; after the change, the type becomes &transfer::AsyncStream + 'static
. I don't know why the 'static
lifetime comes in when I change from a concrete type to a trait...
Why does this happen? How can I fix it?