Reputation: 4482
I read a file given as an argument, but when I try to pass it to handle_client
in a task at the bottom so that it can be written to the tcp stream when someone connects I get error: capture of moved value: html
... what am I missing?
fn get_file_string(path_str: &String) -> String{
let path = Path::new(path_str.as_bytes());
let file = File::open(&path);
let mut reader = BufferedReader::new(file);
reader.read_to_string().unwrap()
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:8001");
let mut acceptor = listener.listen();
let ref file_to_host = os::args()[1];
let html = get_file_string(file_to_host).clone();
fn handle_client(mut stream: TcpStream, html: String) {
let write = stream.write_str(html.as_slice());
}
for stream in acceptor.incoming() {
match stream {
Err(e) => { println!("{}", e) }
Ok(stream) => spawn(proc() {
handle_client(stream,html)
})
}
}
}
Upvotes: 1
Views: 1462
Reputation: 90882
html
is a String
. Just like everything in Rust, a String
is owned in exactly one place (if it satisfied Copy
, it would be able to just duplicate it implicitly, but as it involves a heap allocation it’s definitely not). At present, you’re passing html
to the handle_client
function by value; therefore, when you call handle_client(stream, html)
, both stream
and html
are moved into that function and are no longer accessible. In the case of stream
, that doesn’t matter as it’s a variable from inside the loop, but html
comes from outside the loop; if it let you do it, it would take it the first time and work fine, but then it would be freed; second time through the loop, you would have an invalid String
being passed through.
The solution in this case, seeing as you’re passing it through spawn
and so can’t pass a reference (the slice, &str
) is to clone the value so that that value can be moved into the proc
and into the handle_client
call:
Ok(stream) => {
let html = html.clone();
spawn(proc() {
handle_client(stream, html)
})
}
Upvotes: 6