Abstract out NetworkStream
This introduces a new Trait, NetworkStream, which abstracts over the functionality provided by TcpStream so that it can be easily mocked and extended in testing and hyper can be used for other connection sources.
This commit is contained in:
committed by
Jonathan Reem
parent
a8d7b681da
commit
0285fc2acc
120
src/net.rs
Normal file
120
src/net.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
//! A collection of traits abstracting over Listeners and Streams.
|
||||
use std::io::{IoResult, Stream, Listener, Acceptor};
|
||||
use std::io::net::ip::{SocketAddr, Port};
|
||||
use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor};
|
||||
|
||||
/// An abstraction to listen for connections on a certain port.
|
||||
pub trait NetworkListener<S: NetworkStream, A: NetworkAcceptor<S>>: Listener<S, A> {
|
||||
/// Bind to a socket.
|
||||
///
|
||||
/// Note: This does not start listening for connections. You must call
|
||||
/// `listen()` to do that.
|
||||
fn bind(host: &str, port: Port) -> IoResult<Self>;
|
||||
|
||||
/// Get the address this Listener ended up listening on.
|
||||
fn socket_name(&mut self) -> IoResult<SocketAddr>;
|
||||
}
|
||||
|
||||
/// An abstraction to receive `HttpStream`s.
|
||||
pub trait NetworkAcceptor<S: NetworkStream>: Acceptor<S> + Clone + Send {
|
||||
/// Closes the Acceptor, so no more incoming connections will be handled.
|
||||
fn close(&mut self) -> IoResult<()>;
|
||||
}
|
||||
|
||||
/// An abstraction over streams that a Server can utilize.
|
||||
pub trait NetworkStream: Stream + Clone {
|
||||
/// Get the remote address of the underlying connection.
|
||||
fn peer_name(&mut self) -> IoResult<SocketAddr>;
|
||||
|
||||
/// Connect to a remote address.
|
||||
fn connect(host: &str, port: Port) -> IoResult<Self>;
|
||||
}
|
||||
|
||||
/// A `NetworkListener` for `HttpStream`s.
|
||||
pub struct HttpListener {
|
||||
inner: TcpListener
|
||||
}
|
||||
|
||||
impl Listener<HttpStream, HttpAcceptor> for HttpListener {
|
||||
#[inline]
|
||||
fn listen(self) -> IoResult<HttpAcceptor> {
|
||||
Ok(HttpAcceptor {
|
||||
inner: try!(self.inner.listen())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkListener<HttpStream, HttpAcceptor> for HttpListener {
|
||||
#[inline]
|
||||
fn bind(host: &str, port: Port) -> IoResult<HttpListener> {
|
||||
Ok(HttpListener {
|
||||
inner: try!(TcpListener::bind(host, port))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn socket_name(&mut self) -> IoResult<SocketAddr> {
|
||||
self.inner.socket_name()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `NetworkAcceptor` for `HttpStream`s.
|
||||
#[deriving(Clone)]
|
||||
pub struct HttpAcceptor {
|
||||
inner: TcpAcceptor
|
||||
}
|
||||
|
||||
impl Acceptor<HttpStream> for HttpAcceptor {
|
||||
#[inline]
|
||||
fn accept(&mut self) -> IoResult<HttpStream> {
|
||||
Ok(HttpStream {
|
||||
inner: try!(self.inner.accept())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkAcceptor<HttpStream> for HttpAcceptor {
|
||||
#[inline]
|
||||
fn close(&mut self) -> IoResult<()> {
|
||||
self.inner.close_accept()
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper around a TcpStream.
|
||||
#[deriving(Clone)]
|
||||
pub struct HttpStream {
|
||||
inner: TcpStream
|
||||
}
|
||||
|
||||
impl Reader for HttpStream {
|
||||
#[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for HttpStream {
|
||||
#[inline]
|
||||
fn write(&mut self, msg: &[u8]) -> IoResult<()> {
|
||||
self.inner.write(msg)
|
||||
}
|
||||
#[inline]
|
||||
fn flush(&mut self) -> IoResult<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl NetworkStream for HttpStream {
|
||||
#[inline]
|
||||
fn peer_name(&mut self) -> IoResult<SocketAddr> {
|
||||
self.inner.peer_name()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn connect(host: &str, port: Port) -> IoResult<HttpStream> {
|
||||
Ok(HttpStream {
|
||||
inner: try!(TcpStream::connect(host, port))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user