How to idiomatically / efficiently pipe data from Read+Seek to Write?

You are looking for io::copy:

use std::io::{self, prelude::*, SeekFrom};

pub fn assemble<I, O>(mut input: I, mut output: O) -> Result<(), io::Error>
where
    I: Read + Seek,
    O: Write,
{
    // first seek and output "hello"
    input.seek(SeekFrom::Start(5))?;
    io::copy(&mut input.by_ref().take(5), &mut output)?;

    // then output "world"
    input.seek(SeekFrom::Start(0))?;
    io::copy(&mut input.take(5), &mut output)?;

    Ok(())
}

If you look at the implementation of io::copy, you can see that it’s similar to your code. However, it takes care to handle more error cases:

  1. write does not always write everything you ask it to!
  2. An “interrupted” write isn’t usually fatal.

It also uses a larger buffer size but still stack-allocates it.

Leave a Comment