2
votes

This code looks like it would work fine to me, but the rust borrow checker doesn't like it:

extern crate rustbox;

use std::error::Error;
use std::default::Default;

use rustbox::{Color, RustBox};
use rustbox::Key;

use std::fs::File;
use std::env;
use std::io::BufReader;
use std::io::BufRead;

fn display_screenful(rb: &RustBox, fr: BufReader<&'static File>, offset: usize) {
    for (rline, idx) in fr.lines().zip(0..).skip(offset).take(rb.height()) {
        match rline {
            Ok(line) => (*rb).print(0, idx, rustbox::RB_NORMAL, Color::White, Color::Black, &line),
            Err(_)   => (*rb).print(0, idx, rustbox::RB_NORMAL, Color::White, Color::Black, "")
        }
    }
}

fn main() {
    let rustbox = match RustBox::init(Default::default()) {
        Ok(v) => v,
        Err(e) => panic!(e),
    };

    let path = env::args().nth(1).unwrap();
    let file = match File::open(&path) {
        Ok(file) => file,
        Err(e)   => panic!(e)
    };
    let file_reader = BufReader::new(&file);

    display_screenful(&rustbox, file_reader, 0);
    rustbox.present();

    loop {
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Some(Key::Char('q')) => { break; }
                    Some(Key::Char(' ')) => {
                        display_screenful(&rustbox, file_reader, rustbox.height());
                        rustbox.present();
                    }
                    _ => { }
                }
            },
            Err(e) => panic!("{}", e.description()),
            _ => { }
        }
    }
}

I guess I could not use a separate function, and use two for loop parts, instead, but that isn't idiomatic Rust, nor is it good coding practice. In fact, I've tried that, but it just tells me that I'm using a moved value. Here are some errors that I'm getting:

   Compiling rusted v0.1.0 (file:///Users/christopherdumas/rusted)
src/main.rs:34:39: 34:43 error: `file` does not live long enough
src/main.rs:34     let file_reader = BufReader::new(&file);
                                                     ^~~~
note: reference must be valid for the static lifetime...
src/main.rs:33:7: 55:2 note: ...but borrowed value is only valid for the block suffix following statement 2 at 33:6
src/main.rs:33     };
src/main.rs:34     let file_reader = BufReader::new(&file);
src/main.rs:35
src/main.rs:36     display_screenful(&rustbox, file_reader, 0);
src/main.rs:37     rustbox.present();
src/main.rs:38
               ...
src/main.rs:45:53: 45:64 error: use of moved value: `file_reader` [E0382]
src/main.rs:45                         display_screenful(&rustbox, file_reader, rustbox.height());
                                                                   ^~~~~~~~~~~
src/main.rs:45:53: 45:64 help: run `rustc --explain E0382` to see a detailed explanation
src/main.rs:36:33: 36:44 note: `file_reader` moved here because it has type `std::io::buffered::BufReader<&'static std::fs::File>`, which is non-copyable
src/main.rs:36     display_screenful(&rustbox, file_reader, 0);
                                               ^~~~~~~~~~~
error: aborting due to 2 previous errors
Could not compile `rusted`.

To learn more, run the command again with --verbose.
1
I can't verify this at the moment but I think the problem is the static in BufReader<&'static File>. You're asking the compiler to guarantee that the reference will be valid for the lifetime of the program, which is not true in this case, and therefore the compiler tells you that your file object doesn't live long enough.A.B.

1 Answers

4
votes

Firstly, you shouldn't ask for a BufReader<&'static File>. You can't provide one. Ask instead for a BufReader<&'a File> for some lifetime 'a.

fn display_screenful<'a>(rb: &RustBox, fr: BufReader<&'a File>, offset: usize)

or, for short,

fn display_screenful(rb: &RustBox, fr: BufReader<&File>, offset: usize)

That's not enough either - you then end up moving file_reader into the function. You should borrow instead:

fn display_screenful(rb: &RustBox, fr: &mut BufReader<&File>, offset: usize)

and then it compiles.