I'm just trying to figure out how ownership works in Rust, I just have an example file helper as :
pub struct FileHelper {
pub reader:Option<BufReader<File>>
}
impl FileHelper {
pub fn new() -> Self {
FileHelper{ reader: None }
}
pub fn open_read(&mut self, file:&str) {
let file_stream:File = File::open(file).expect("FAIL");
self.reader = Some(BufReader::new(file_stream));
}
pub fn get_reader(&self) -> Option<&BufReader<File>> {
match &self.reader {
Some(reader) => { return Some(reader); }
None => { return None; }
}
}
}
All it does it separate the creation of a BufReader
and the retrieval of the same BufReader
. I'm using it as :
let mut file_helper:FileHelper = FileHelper::new();
file_helper.open_read("/tmp/someFile.txt");
match file_helper.get_reader() {
Some(reader) => {
for read_line in reader.lines() { println!("{:?}", read_line.unwrap()); }
},
None => {}
}
It seems to be able to get the reference to the BufReader
but I'm unable to interact with the reader.lines()
because it gives the error :
move occurs because `*reader` has type `std::io::BufReader<std::fs::File>`, which does not implement the `Copy` trait
So I'm guessing the reader.lines()
is trying to take ownership? I don't really understand how the ownership and referencing is working here but was wondering if there's a way to still use the reader.lines()
on a referenced BufReader
?
BufRead is implemented for impl<B: BufRead + ?Sized> BufRead for &mut B. But you are returning a shared reference to underling reader. Method BufRead::lines consumes self
. Since you provided &BufReader
compiler tries to dereference it and take BufRead
which is impossible since it is behind a shared reference and is not Copy
.
Solution is very simple. Just return exclusive/mutable reference to the buf reader.
use std::io::{BufReader, BufRead};
use std::fs::File;
pub struct FileHelper {
pub reader: Option<BufReader<File>>
}
impl FileHelper {
pub fn new() -> Self {
FileHelper {reader: None }
}
pub fn open_read(&mut self, file: &str) {
let file_stream: File = File::open(file).expect("FAIL");
self.reader = Some(BufReader::new(file_stream));
}
pub fn get_reader(&mut self) -> Option<&mut BufReader<File>> {
self.reader.as_mut()
}
}
fn main() {
let mut file_helper: FileHelper = FileHelper::new();
file_helper.open_read("/tmp/someFile.txt");
if let Some(reader) = file_helper.get_reader() {
for read_line in reader.lines() {
println!("{:?}", read_line.unwrap());
}
}
}