如何创建tokio专用传输以覆盖默认的tick实现?

时间:2017-06-17 00:05:40

标签: rust rust-tokio

我试图在传输中使用非默认tick()方法编写流式流水线服务器。我以为会这样做:

use std::io;

use mio::net::TcpListener;
use tokio_core::reactor::PollEvented;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use tokio_proto::streaming::pipeline::Transport;

use codec::PacketCodec;

type GearmanIO = PollEvented<TcpListener>;
type GearmanFramed = Framed<GearmanIO, PacketCodec>;

impl Transport for GearmanFramed {
    fn tick(&mut self) {
        trace!("tick!");
    }

    fn cancel(&mut self) -> io::Result<()> {
        trace!("cancel!");
    }
}

但是,尝试构建此文件会产生以下结果:

error[E0119]: conflicting implementations of trait `tokio_proto::streaming::pipeline::Transport` for type `tokio_io::codec::Framed<tokio_core::reactor::PollEvented<mio::net::TcpListener>, codec::PacketCodec>`:
  --> src/transport.rs:14:1
   |
14 | / impl Transport for GearmanFramed
15 | | {
16 | |     fn tick(&mut self) {
17 | |         trace!("tick!");
...  |
22 | |     }
23 | | }
   | |_^
   |
   = note: conflicting implementation in crate `tokio_proto`

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
  --> src/transport.rs:14:1
   |
14 | / impl Transport for GearmanFramed
15 | | {
16 | |     fn tick(&mut self) {
17 | |         trace!("tick!");
...  |
22 | |     }
23 | | }
   | |_^ impl doesn't use types inside crate
   |
   = note: the impl does not reference any types defined in this crate
   = note: define and implement a trait or new type instead

我原本预计GearmanFramed的特定性质会允许我实施Transport特性,因为&#34; specialization&#34;,但这个特性仍然与默认值相冲突,在这里:

use tokio_io as new_io;

// ...

impl<T, C> Transport for new_io::codec::Framed<T,C>
    where T: new_io::AsyncRead + new_io::AsyncWrite + 'static,
          C: new_io::codec::Encoder<Error=io::Error> +
                new_io::codec::Decoder<Error=io::Error> + 'static,
{}

1 个答案:

答案 0 :(得分:0)

经过几天的挣扎,我想出了这个。答案是使用newtype来包围Framed,从而避免默认实现。

use std::io;

use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use tokio_proto::streaming::pipeline::Transport;
use futures::{Poll, Sink, StartSend, Stream};

use codec::PacketCodec;

pub struct GearmanFramed<T>(pub Framed<T, PacketCodec>);

impl<T> Transport for GearmanFramed<T>
    where T: AsyncRead + AsyncWrite + 'static
{
    fn tick(&mut self) {
        trace!("tick!");
    }

    fn cancel(&mut self) -> io::Result<()> {
        trace!("cancel!");
        Ok(())
    }
}

impl<T> Stream for GearmanFramed<T>
    where T: AsyncRead
{
    type Item = <PacketCodec as Decoder>::Item;
    type Error = <PacketCodec as Decoder>::Error;
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.0.poll()
    }
}

impl<T> Sink for GearmanFramed<T>
    where T: AsyncWrite
{
    type SinkItem = <PacketCodec as Encoder>::Item;
    type SinkError = <PacketCodec as Encoder>::Error;
    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.0.start_send(item)
    }
    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.0.poll_complete()
    }
    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.0.close()
    }
}