I recently switched to rust for a project and I am having a hard time with mutable and unmutable objects.
I am having a problem where I need to pass a mutable object to a function inside the implementation function of one of my traits. The error I am getting is the following:
error[E0596]: cannot borrow `self.volume_name` as mutable, as it is behind a `&` reference
--> src/main.rs:107:40
|
94 | fn load_info(&self, name: &str) {
| ----- help: consider changing this to be a mutable reference: `&mut self`
...
107 | seek_read(&mut opened_file, 3, &mut self.volume_name).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
I dont know how to fix this error, since it seems that every fix I try another error pops up. I tried creating a new object and setting the new one to self, but that didnt work either, as self inside this function is a reference, and if I set the addresses the same once I leave the context it will be gone so I get another error! Remember, i am coming from C.
Base code:
pub trait Filesystem {
fn load_info(&self, name: &str);
}
pub struct Fat16 {
pub volume_name: [u8; 8],
}
impl Default for Fat16 {
fn default() -> Fat16 {
Fat16 {
volume_name: [0; 8],
}
}
}
impl Filesystem for Fat16 {
fn load_info(&self, name: &str) {
//I assume the file is a Fat16 volume, the checks are done before
let mut opened_file = match File::open(&name) {
Err(why) => panic!("couldn't open {}: {}", name, why),
Ok(opened_file) => opened_file,
};
// ------------------------ VOLUME NAME ------------------------
// Volume name starts at 3
seek_read(&mut opened_file, 3, &self.volume_name).unwrap();
match str::from_utf8(&self.volume_name) {
Ok(v) => println!("Volume Name: {}", v),
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
};
/*more code*/
Seek read function:
pub fn seek_read(mut reader: impl Read + Seek, offset: u64, buf: &mut [u8]) -> io::Result<()> {
reader.seek(SeekFrom::Start(offset))?;
reader.read_exact(buf)?;
Ok(())
}
self
is a&
reference, so the data it refers to cannot be borrowed as mutable
Presumably load_info
is going to load information into the Filesystem object. If you want to mutate attributes of self, it needs to be mutable.
pub trait Filesystem {
fn load_info(&mut self, name: &str);
^^^^
}
impl Filesystem for Fat16 {
fn load_info(&mut self, name: &str) {
^^^^
let mut opened_file = match File::open(&name) {
Err(why) => panic!("couldn't open {}: {}", name, why),
Ok(opened_file) => opened_file,
};
seek_read(&mut opened_file, 3, &mut self.volume_name).unwrap();
^^^^
match std::str::from_utf8(&self.volume_name) {
Ok(v) => println!("Volume Name: {}", v),
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
};
}
}