Input/output for a simple Brainfuck interpreter The following code comes from a simple Brainfuck interpreter I'm working on to learn the Rust language. Error handling is omitted for simplicity. It is tested on rustc version 1.1.0-dev (af522079a 2015-05-14) (built 2015-05-14).

The code implements just the input and output routines for the interpreter. The read_cell method reads a single byte from the Read object input and stores it in the memory cell at pointer. write_cell writes the byte a the memory cell at pointer to the Write object output.

use std::io::Read;
use std::io::Write;

pub struct Machine&lt;In, Out&gt; {
    pub memory: Vec&lt;u8&gt;, 
    pub pointer: usize, 
    input: In, 
    output: Out,
}

impl&lt;In: Read, Out: Write&gt; Machine&lt;In, Out&gt; {
    pub fn new(input: In, output: Out) -&gt; Machine&lt;In, Out&gt; {
        Machine { 
            memory: vec![0; 2], 
            pointer: 0, 
            input: input, 
            output: output 
        }
    }

    pub fn read_cell(&amp;mut self) {
        self.input.read(&amp;mut self.memory[self.pointer..self.pointer+1]).unwrap();
    }

    pub fn write_cell(&amp;mut self) {
        self.output.write(&amp;self.memory[self.pointer..self.pointer+1]).unwrap();
    }
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_write_cell() {
        let input = "".as_bytes();
        let mut output = vec![];
        {
            let mut machine = Machine::new(input, &amp;mut output);
            machine.memory[machine.pointer] = 1;
            machine.write_cell();
        }
        assert_eq!(vec![1], output);
    }
}


There are two main points in the code that are concerning me:


I cannot find in the standard library API an obvious method to read or write a single byte. There is a better/clearer way to implement the read_cell and write_cell methods?
In the test function test_write_cell I had to declare machine inside a nested scope. If it is declared in the same scope of output I get this error at the assert_eq! line:

 cannot borrow `output` as immutable because it is also borrowed as mutable


Can I write the same test without having to nest scopes? Is so, how?


Any other comment, hint or advice will be very welcome!
a better/clearer way to implement the read_cell and write_cell methods?


What you have seems pretty good to me. Rust's IO methods rely on having a buffer to read into. In many cases, you might see a single byte read with something like

let mut buf = [0; 1]; 
reader.read(&amp;mut buf).unwrap();


In your case, you already have a buffer, so you might as well read directly into it.


  Can I write the same test without having to nest scopes?


Nope. Let's comment out the nested braces and look at the error messages:

error: cannot borrow `output` as immutable because it is also
       borrowed as mutable

match ( &amp; ( $ left ) , &amp; ( $ right ) ) {
                         ^~~~~~~~~~~
note: in expansion of assert_eq!


We are attempting to immutably borrow something that's already borrowed. The compiler is kind enough to show us where the borrow occurs:

note: previous borrow of `output` occurs here; the mutable borrow
      prevents subsequent moves, borrows, or modification of
      `output` until the borrow ends    

let mut machine = Machine::new(input, &amp;mut output);
                                           ^~~~~~


And where it ends:

note: previous borrow ends here

fn test_write_cell() {
...
}
^


When there is an outstanding mutable borrow, Rust only that borrow to exist. This removes whole classes of bugs around "spooky action at a distance" as well as potential data races. The extra braces provide a lifetime that the borrow can live during; once the block is exited, the borrow is no longer needed.

The only solution I know of is to use what I like to call an exploder. If you are familiar with constructors and destructors, then an exploder is like a destructor that returns values. There's a common pattern in the standard library with methods called into_inner. Here's how it could look for your code:

impl&lt;In: Read, Out: Write&gt; Machine&lt;In, Out&gt; {
    pub fn into_inner(self) -&gt; (In, Out) {
        (self.input, self.output)
    }
}

fn test_write_cell() {
    let input = "".as_bytes();
    let output = vec![];

    let mut machine = Machine::new(input, output);
    machine.memory[machine.pointer] = 1;
    machine.write_cell();

    let (_, output) = machine.into_inner();

    assert_eq!(vec![1], output);
}