2

I have a trait for readable and writable streams (like TcpStream):

pub trait MyTraitPool<T: Read + Write> {
    fn acquire(&self, &String) -> T;
    fn free(&self, T);
}

I want to implement that trait with TcpStream as T, so I would like to write

struct MyPool;

impl<T> MyTraitPool<T> for MyPool
    where T: Read + Write {

    fn acquire(&self, addr: &String) -> T {
        TcpStream::connect(addr.as_str()).unwrap()
    }

    fn free(&self, con: T) {
        con.shutdown(Shutdown::Both);
    }
}

I get the error "expected type parameter, found struct std::net::TcpStream" in the acquire method. As for the free method, I know that shutdown is TcpStream-specific, but I would like to have an implementation specific for TcpStreams at that point and hence be able to call TcpStream-specific methods. So how do I go about doing so?

As a side note: the implementation is just an example for what kind of things I would like to do, not for how the code operates later!

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Maru
  • 894
  • 1
  • 12
  • 29
  • I'm getting different issues: "expected type parameter, found enum `std::result::Result`" (are you missing an `unwrap` in the code above?) and "no method named `shutdown` found for type `T` in the current scope" (assuming you are using only `std::net::{TcpStream, Shutdown}` and `std::io::{Read, Write}`). – ljedrz Feb 01 '17 at 13:42
  • @ljedrz the implementation above is only a sample, so I did not check for the return types or error management etc. (I wanted to keep the purpose simple and readable). The second problem is actually mentioned in the text above ;) – Maru Feb 01 '17 at 14:23
  • 1
    Ah yes, I wasn't reading carefully enough :). Nevertheless, it is always a good idea to provide code that reproduces the exact issue you are having upon compilation ([MCVE](http://stackoverflow.com/help/mcve)) - it makes it much easier to find the solution applicable to your specific case. – ljedrz Feb 01 '17 at 14:30

1 Answers1

1

Instead of making the MyTraitPool trait generic, you'd make your MyPool generic and you'd create an intermediate MyStream trait to offer you all methods you need:

trait MyStream: Read + Write {
    fn connect(&str) -> Self;
    fn shutdown(self);
}
impl MyStream for TcpStream {
    fn connect(addr: &str) -> Self { TcpStream::connect(addr) }
    fn shutdown(self) { TcpStream::shutdown(self, Shutdown::Both); }
}
impl<T: MyStream> MyTraitPool for MyPool<T> {
    fn acquire(&self, addr: &str) -> T {
        MyStream::connect(addr)
    }
    fn free(&self, con: T) {
        con.shutdown()
    }
}

Streams which do not actually need to shutdown, would simply leave the implementation empty.

oli_obk
  • 28,729
  • 6
  • 82
  • 98
  • That looks like a good idea and I managed to make it compile, thank you a lot! I think I learned something new today :) – Maru Feb 01 '17 at 14:33