use std::io::{Read, Write, Result};
use session::Session;
pub struct Stream<'a, S: 'a + Session + ?Sized, T: 'a + Read + Write + ?Sized> {
pub sess: &'a mut S,
pub sock: &'a mut T,
}
impl<'a, S, T> Stream<'a, S, T> where S: 'a + Session, T: 'a + Read + Write {
pub fn new(sess: &'a mut S, sock: &'a mut T) -> Stream<'a, S, T> {
Stream { sess, sock }
}
fn complete_prior_io(&mut self) -> Result<()> {
if self.sess.is_handshaking() {
self.sess.complete_io(self.sock)?;
}
if self.sess.wants_write() {
self.sess.complete_io(self.sock)?;
}
Ok(())
}
}
impl<'a, S, T> Read for Stream<'a, S, T> where S: 'a + Session, T: 'a + Read + Write {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.complete_prior_io()?;
while
self.sess.wants_read() &&
self.sess.complete_io(self.sock)?.0 != 0
{ }
self.sess.read(buf)
}
}
impl<'a, S, T> Write for Stream<'a, S, T> where S: 'a + Session, T: 'a + Read + Write {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.complete_prior_io()?;
let len = self.sess.write(buf)?;
self.sess.complete_io(self.sock)?;
Ok(len)
}
fn flush(&mut self) -> Result<()> {
self.complete_prior_io()?;
self.sess.flush()?;
if self.sess.wants_write() {
self.sess.complete_io(self.sock)?;
}
Ok(())
}
}
pub struct StreamOwned<S: Session + Sized, T: Read + Write + Sized> {
pub sess: S,
pub sock: T,
}
impl<S, T> StreamOwned<S, T> where S: Session, T: Read + Write {
pub fn new(sess: S, sock: T) -> StreamOwned<S, T> {
StreamOwned { sess, sock }
}
}
impl<'a, S, T> StreamOwned<S, T> where S: Session, T: Read + Write {
fn as_stream(&'a mut self) -> Stream<'a, S, T> {
Stream { sess: &mut self.sess, sock: &mut self.sock }
}
}
impl<S, T> Read for StreamOwned<S, T> where S: Session, T: Read + Write {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.as_stream().read(buf)
}
}
impl<S, T> Write for StreamOwned<S, T> where S: Session, T: Read + Write {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.as_stream().write(buf)
}
fn flush(&mut self) -> Result<()> {
self.as_stream().flush()
}
}
#[cfg(test)]
mod tests {
use super::{Stream, StreamOwned};
use session::Session;
use client::ClientSession;
use server::ServerSession;
use std::net::TcpStream;
#[test]
fn stream_can_be_created_for_session_and_tcpstream() {
fn _foo<'a>(sess: &'a mut Session, sock: &'a mut TcpStream) -> Stream<'a, Session, TcpStream> {
Stream {
sess,
sock,
}
}
}
#[test]
fn streamowned_can_be_created_for_client_and_tcpstream() {
fn _foo(sess: ClientSession, sock: TcpStream) -> StreamOwned<ClientSession, TcpStream> {
StreamOwned {
sess,
sock,
}
}
}
#[test]
fn streamowned_can_be_created_for_server_and_tcpstream() {
fn _foo(sess: ServerSession, sock: TcpStream) -> StreamOwned<ServerSession, TcpStream> {
StreamOwned {
sess,
sock,
}
}
}
}