mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-27 00:00:12 +02:00
Refactor framing to use Streams and Sinks
- Gets rid of `easy` module, instead providing framing support directly in the `io` module. - In particular, adds a framing adapter directly to the `Io` trait, which gives you a Stream + Sink object. That object can then be `split` into separate `Stream` and `Sink` objects if needed. - Deprecates the `FramedIo` trait; that's now just Stream + Sink. - Updates the line framing test to use the stream/sink combinators.
This commit is contained in:
+13
-68
@@ -5,85 +5,30 @@ extern crate futures;
|
||||
use std::io;
|
||||
use std::net::Shutdown;
|
||||
|
||||
use futures::{Future, Async, Poll};
|
||||
use futures::stream::Stream;
|
||||
use tokio_core::io::{FramedIo, write_all, read};
|
||||
use tokio_core::easy::{Encode, Decode, EasyFramed, EasyBuf};
|
||||
use futures::{Future, Stream, Sink};
|
||||
use tokio_core::io::{write_all, read, Encode, Decode, EasyBuf, Io};
|
||||
use tokio_core::net::{TcpListener, TcpStream};
|
||||
use tokio_core::reactor::Core;
|
||||
|
||||
pub struct LineDecoder;
|
||||
pub struct LineEncoder;
|
||||
pub struct Line(EasyBuf);
|
||||
|
||||
impl Decode for LineDecoder {
|
||||
type Out = EasyBuf;
|
||||
|
||||
fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<EasyBuf>, io::Error> {
|
||||
impl Decode for Line {
|
||||
fn decode(buf: &mut EasyBuf) -> Result<Option<Line>, io::Error> {
|
||||
match buf.as_slice().iter().position(|&b| b == b'\n') {
|
||||
Some(i) => Ok(Some(buf.drain_to(i + 1).into())),
|
||||
Some(i) => Ok(Some(Line(buf.drain_to(i + 1).into()))),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn done(&mut self, buf: &mut EasyBuf) -> io::Result<EasyBuf> {
|
||||
fn done(buf: &mut EasyBuf) -> io::Result<Line> {
|
||||
let amt = buf.len();
|
||||
Ok(buf.drain_to(amt))
|
||||
Ok(Line(buf.drain_to(amt)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for LineEncoder {
|
||||
type In = EasyBuf;
|
||||
|
||||
fn encode(&mut self, msg: EasyBuf, into: &mut Vec<u8>) {
|
||||
into.extend_from_slice(msg.as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EchoFramed<T> {
|
||||
inner: T,
|
||||
eof: bool,
|
||||
}
|
||||
|
||||
impl<T, U> Future for EchoFramed<T>
|
||||
where T: FramedIo<In = U, Out = Option<U>>,
|
||||
{
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<(), ()> {
|
||||
// Try to write out any buffered messages if we have them.
|
||||
if self.inner.flush().expect("flush error").is_not_ready() {
|
||||
return Ok(Async::NotReady)
|
||||
}
|
||||
|
||||
// Wait until we can simultaneously read and write a message
|
||||
while !self.eof &&
|
||||
self.inner.poll_read().is_ready() &&
|
||||
self.inner.poll_write().is_ready() {
|
||||
let frame = match self.inner.read() {
|
||||
Ok(Async::Ready(Some(frame))) => frame,
|
||||
Ok(Async::Ready(None)) => {
|
||||
self.eof = true;
|
||||
break
|
||||
}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(e) => panic!("error in read: {}", e),
|
||||
};
|
||||
|
||||
match self.inner.write(frame) {
|
||||
Ok(Async::Ready(())) => {}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(e) => panic!("error in write: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// If we wrote some frames try to flush again. Ignore whether this is
|
||||
// ready to finish or not as we're going to continue to return NotReady
|
||||
if self.inner.flush().expect("flush error").is_ready() && self.eof {
|
||||
Ok(().into())
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
impl Encode for Line {
|
||||
fn encode(self, into: &mut Vec<u8>) {
|
||||
into.extend_from_slice(self.0.as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +42,8 @@ fn echo() {
|
||||
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
let srv = listener.incoming().for_each(move |(socket, _)| {
|
||||
let framed = EasyFramed::new(socket, LineDecoder, LineEncoder);
|
||||
handle.spawn(EchoFramed { inner: framed, eof: false });
|
||||
let (stream, sink) = socket.framed::<Line, Line>().split();
|
||||
handle.spawn(sink.send_all(stream).map(|_| ()).map_err(|_| ()));
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user