tokio-rs/tokio-core

Make Sink::SinkItem a generic parameter

Closed this issue · 2 comments

This would allow Sinks to accept values of multiple different types. I'm sure there's a reason it's an associated type right now, but I can't quite figure out why that is.

Example:

pub trait Sink<Item> {
    type SinkError;
    fn start_send(
        &mut self, 
        item: Item
    ) -> StartSend<Item, Self::SinkError>;
    fn poll_complete(&mut self) -> Poll<(), Self::SinkError>;
    ...
}

The same goes for the tokio-io Encoder trait:

pub trait Encoder<Item> {
    type Error: From<Error>;
    fn encode(
        &mut self, 
        item: Item, 
        dst: &mut BytesMut
    ) -> Result<(), Self::Error>;
}

This would solve this tokio-io issue, because users could write an impl like:

struct Bytes;

impl<'a> Encoder<&'a [u8]> for Bytes {
    type Error = io::Error;
    fn encode(&mut self, data: &'a [u8]>, buf: &mut BytesMut) -> io::Result<()> {
        buf.put(data);
        Ok(())
    }
}

impl Encoder<Vec<u8>> for Bytes {
    type Error = io::Error;
    fn encode(&mut self, data: Vec<u8>, buf: &mut BytesMut) -> io::Result<()> {
        buf.put(&data[..]);
        Ok(())
    }
}

Conceptually, Item is an input to a Sync or Encoder, rather than an output like it is in Stream, Future, and Iterator. As an input, it makes sense for it to be variant. For other examples of this design, see the Fn<...> traits, which use Args as a generic parameter, and Output as an associated type.

Actually, this issue belongs in the futures-rs repo, so I'll close this and move it.