Struct io_streams::BufDuplexer[][src]

pub struct BufDuplexer<Inner: HalfDuplex> { /* fields omitted */ }

Wraps a reader and writer and buffers their output.

It can be excessively inefficient to work directly with something that implements Write. For example, every call to write on TcpStream results in a system call. A BufDuplexer<Inner> keeps an in-memory buffer of data and writes it to an underlying writer in large, infrequent batches.

It can be excessively inefficient to work directly with a Read instance. For example, every call to read on TcpStream results in a system call. A BufDuplexer<Inner> performs large, infrequent reads on the underlying Read and maintains an in-memory buffer of the results.

BufDuplexer<Inner> can improve the speed of programs that make small and repeated write calls to the same file or network socket. It does not help when writing very large amounts at once, or writing just one or a few times. It also provides no advantage when writing to a destination that is in memory, like a Vec<u8>.

BufDuplexer<Inner> can improve the speed of programs that make small and repeated read calls to the same file or network socket. It does not help when reading very large amounts at once, or reading just one or a few times. It also provides no advantage when reading from a source that is already in memory, like a Vec<u8>.

It is critical to call flush before BufDuplexer<Inner> is dropped. Though dropping will attempt to flush the contents of the writer buffer, any errors that happen in the process of dropping will be ignored. Calling flush ensures that the writer buffer is empty and thus dropping will not even attempt file operations.

When the BufDuplexer<Inner> is dropped, the contents of its reader buffer will be discarded. Creating multiple instances of a BufDuplexer<Inner> on the same stream can cause data loss. Reading from the underlying reader after unwrapping the BufDuplexer<Inner> with BufDuplexer::into_inner can also cause data loss.

Examples

Let’s write the numbers one through ten to a TcpStream:

use std::{io::prelude::*, net::TcpStream};

let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();

for i in 0..10 {
    stream.write(&[i + 1]).unwrap();
}

Because we’re not buffering, we write each one in turn, incurring the overhead of a system call per byte written. We can fix this with a BufDuplexer<Inner>:

use io_streams::BufDuplexer;
use std::{io::prelude::*, net::TcpStream};

let mut stream = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

for i in 0..10 {
    stream.write(&[i + 1]).unwrap();
}
stream.flush().unwrap();

By wrapping the stream with a BufDuplexer<Inner>, these ten writes are all grouped together by the buffer and will all be written out in one system call when the stream is flushed.

use io_streams::BufDuplexer;
use std::{io::prelude::*, net::TcpStream};

fn main() -> std::io::Result<()> {
    let mut stream = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

    let mut line = String::new();
    let len = stream.read_line(&mut line)?;
    println!("First line is {} bytes long", len);
    Ok(())
}

Implementations

impl<Inner: HalfDuplex> BufDuplexer<Inner>[src]

pub fn new(inner: Inner) -> Self[src]

Creates a new BufDuplexer<Inner> with default buffer capacities. The default is currently 8 KB, but may change in the future.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let mut buffer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

pub fn with_capacities(
    reader_capacity: usize,
    writer_capacity: usize,
    inner: Inner
) -> Self
[src]

Creates a new BufDuplexer<Inner> with the specified buffer capacities.

Examples

Creating a buffer with ten bytes of reader capacity and a writer buffer of a hundered bytes:

use io_streams::BufDuplexer;
use std::net::TcpStream;

let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
let mut buffer = BufDuplexer::with_capacities(10, 100, stream);

pub fn get_ref(&self) -> &Inner[src]

Gets a reference to the underlying reader/writer.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let mut buffer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

// we can use reference just like buffer
let reference = buffer.get_ref();

pub fn get_mut(&mut self) -> &mut Inner[src]

Gets a mutable reference to the underlying reader/writer.

It is inadvisable to directly write to the underlying reader/writer.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let mut buffer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

// we can use reference just like buffer
let reference = buffer.get_mut();

pub fn writer_buffer(&self) -> &[u8][src]

Returns a reference to the internally buffered writer data.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let buf_writer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

// See how many bytes are currently buffered
let bytes_buffered = buf_writer.writer_buffer().len();

pub fn reader_buffer(&self) -> &[u8][src]

Returns a reference to the internally buffered reader data.

Unlike fill_buf, this will not attempt to fill the buffer if it is empty.

Examples

use char_device::CharDevice;
use io_streams::BufDuplexer;
use std::{fs::File, io::BufRead};

fn main() -> std::io::Result<()> {
    let f = CharDevice::new(File::open("/dev/ttyS0")?)?;
    let mut reader = BufDuplexer::new(f);
    assert!(reader.reader_buffer().is_empty());

    if reader.fill_buf()?.len() > 0 {
        assert!(!reader.reader_buffer().is_empty());
    }
    Ok(())
}

pub fn writer_capacity(&self) -> usize[src]

Returns the number of bytes the internal writer buffer can hold without flushing.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let buf_duplexer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

// Check the capacity of the inner buffer
let capacity = buf_duplexer.writer_capacity();
// Calculate how many bytes can be written without flushing
let without_flush = capacity - buf_duplexer.writer_buffer().len();

pub fn reader_capacity(&self) -> usize[src]

Returns the number of bytes the internal reader buffer can hold at once.

Examples

use char_device::CharDevice;
use io_streams::BufDuplexer;
use std::{fs::File, io::BufRead};

fn main() -> std::io::Result<()> {
    let f = CharDevice::new(File::open("/dev/tty")?)?;
    let mut reader = BufDuplexer::new(f);

    let capacity = reader.reader_capacity();
    let buffer = reader.fill_buf()?;
    assert!(buffer.len() <= capacity);
    Ok(())
}

pub fn into_inner(self) -> Result<Inner, IntoInnerError<Self>>[src]

Unwraps this BufDuplexer<Inner>, returning the underlying reader/writer.

The buffer is written out before returning the reader/writer.

Errors

An Err will be returned if an error occurs while flushing the buffer.

Examples

use io_streams::BufDuplexer;
use std::net::TcpStream;

let mut buffer = BufDuplexer::new(TcpStream::connect("127.0.0.1:34254").unwrap());

// unwrap the TcpStream and flush the buffer
let stream = buffer.into_inner().unwrap();

Trait Implementations

impl<Inner: HalfDuplex + AsRawHandle> AsRawHandle for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex + AsRawHandleOrSocket> AsRawHandleOrSocket for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex + AsRawSocket> AsRawSocket for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex> BufRead for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex> Debug for BufDuplexer<Inner> where
    Inner: Debug
[src]

impl<Inner: HalfDuplex + OwnsRaw> OwnsRaw for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex> Read for BufDuplexer<Inner>[src]

impl<Inner: HalfDuplex> Write for BufDuplexer<Inner>[src]

Auto Trait Implementations

impl<Inner> RefUnwindSafe for BufDuplexer<Inner> where
    Inner: RefUnwindSafe

impl<Inner> Send for BufDuplexer<Inner> where
    Inner: Send

impl<Inner> Sync for BufDuplexer<Inner> where
    Inner: Sync

impl<Inner> Unpin for BufDuplexer<Inner> where
    Inner: Unpin

impl<Inner> UnwindSafe for BufDuplexer<Inner> where
    Inner: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> AsUnsafeFile for T where
    T: OwnsRaw + AsUnsafeHandle + AsRawHandle
[src]

impl<T> AsUnsafeHandle for T where
    T: OwnsRaw + AsRawHandleOrSocket
[src]

impl<T> AsUnsafeSocket for T where
    T: OwnsRaw + AsUnsafeHandle + AsRawSocket
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> SetTimes for T where
    T: AsUnsafeFile

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.