use std::io;
use std::io::{Read, Write};
use std::ops::{Deref, DerefMut};
#[cfg(test)]
macro_rules! assert_eq_transport_num_written_bytes {
($transport:ident, $num_written_bytes:expr) => {{
assert_eq!($transport.channel.write_bytes().len(), $num_written_bytes);
}};
}
#[cfg(test)]
macro_rules! assert_eq_transport_written_bytes {
($transport:ident, $expected_bytes:ident) => {{
assert_eq!($transport.channel.write_bytes(), &$expected_bytes);
}};
}
mod buffered;
mod framed;
mod mem;
mod socket;
pub use self::buffered::{
TBufferedReadTransport, TBufferedReadTransportFactory, TBufferedWriteTransport,
TBufferedWriteTransportFactory,
};
pub use self::framed::{
TFramedReadTransport, TFramedReadTransportFactory, TFramedWriteTransport,
TFramedWriteTransportFactory,
};
pub use self::mem::TBufferChannel;
pub use self::socket::TTcpChannel;
pub trait TReadTransport: Read {}
pub trait TReadTransportFactory {
fn create(&self, channel: Box<dyn Read + Send>) -> Box<dyn TReadTransport + Send>;
}
pub trait TWriteTransport: Write {}
pub trait TWriteTransportFactory {
fn create(&self, channel: Box<dyn Write + Send>) -> Box<dyn TWriteTransport + Send>;
}
impl<T> TReadTransport for T where T: Read {}
impl<T> TWriteTransport for T where T: Write {}
impl<T> TReadTransportFactory for Box<T>
where
T: TReadTransportFactory + ?Sized,
{
fn create(&self, channel: Box<dyn Read + Send>) -> Box<dyn TReadTransport + Send> {
(**self).create(channel)
}
}
impl<T> TWriteTransportFactory for Box<T>
where
T: TWriteTransportFactory + ?Sized,
{
fn create(&self, channel: Box<dyn Write + Send>) -> Box<dyn TWriteTransport + Send> {
(**self).create(channel)
}
}
pub trait TIoChannel: Read + Write {
fn split(
self,
) -> crate::Result<(
crate::transport::ReadHalf<Self>,
crate::transport::WriteHalf<Self>,
)>
where
Self: Sized;
}
#[derive(Debug)]
pub struct ReadHalf<C>
where
C: Read,
{
handle: C,
}
#[derive(Debug)]
pub struct WriteHalf<C>
where
C: Write,
{
handle: C,
}
impl<C> ReadHalf<C>
where
C: Read,
{
pub fn new(handle: C) -> ReadHalf<C> {
ReadHalf { handle }
}
}
impl<C> WriteHalf<C>
where
C: Write,
{
pub fn new(handle: C) -> WriteHalf<C> {
WriteHalf { handle }
}
}
impl<C> Read for ReadHalf<C>
where
C: Read,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.handle.read(buf)
}
}
impl<C> Write for WriteHalf<C>
where
C: Write,
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.handle.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.handle.flush()
}
}
impl<C> Deref for ReadHalf<C>
where
C: Read,
{
type Target = C;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl<C> DerefMut for ReadHalf<C>
where
C: Read,
{
fn deref_mut(&mut self) -> &mut C {
&mut self.handle
}
}
impl<C> Deref for WriteHalf<C>
where
C: Write,
{
type Target = C;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl<C> DerefMut for WriteHalf<C>
where
C: Write,
{
fn deref_mut(&mut self) -> &mut C {
&mut self.handle
}
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use super::*;
#[test]
fn must_create_usable_read_channel_from_concrete_read_type() {
let r = Cursor::new([0, 1, 2]);
let _ = TBufferedReadTransport::new(r);
}
#[test]
fn must_create_usable_read_channel_from_boxed_read() {
let r: Box<dyn Read> = Box::new(Cursor::new([0, 1, 2]));
let _ = TBufferedReadTransport::new(r);
}
#[test]
fn must_create_usable_write_channel_from_concrete_write_type() {
let w = vec![0u8; 10];
let _ = TBufferedWriteTransport::new(w);
}
#[test]
fn must_create_usable_write_channel_from_boxed_write() {
let w: Box<dyn Write> = Box::new(vec![0u8; 10]);
let _ = TBufferedWriteTransport::new(w);
}
#[test]
fn must_create_usable_read_transport_from_concrete_read_transport() {
let r = Cursor::new([0, 1, 2]);
let mut t = TBufferedReadTransport::new(r);
takes_read_transport(&mut t)
}
#[test]
fn must_create_usable_read_transport_from_boxed_read() {
let r = Cursor::new([0, 1, 2]);
let mut t: Box<dyn TReadTransport> = Box::new(TBufferedReadTransport::new(r));
takes_read_transport(&mut t)
}
#[test]
fn must_create_usable_write_transport_from_concrete_write_transport() {
let w = vec![0u8; 10];
let mut t = TBufferedWriteTransport::new(w);
takes_write_transport(&mut t)
}
#[test]
fn must_create_usable_write_transport_from_boxed_write() {
let w = vec![0u8; 10];
let mut t: Box<dyn TWriteTransport> = Box::new(TBufferedWriteTransport::new(w));
takes_write_transport(&mut t)
}
fn takes_read_transport<R>(t: &mut R)
where
R: TReadTransport,
{
t.bytes();
}
fn takes_write_transport<W>(t: &mut W)
where
W: TWriteTransport,
{
t.flush().unwrap();
}
}