New to Lifetimes: borrowing and ownership

pub struct Memory<'a> {
path: PathBuf,
buffer: Bytes,
item: HashMap<&'a [u8], &'a [u8]>,
recent: HashMap<Bytes, Bytes>
}

impl<'a> Memory<'a> {
pub fn new(path: PathBuf) -> Result<Memory<'a>, MainError> {
let mut buffer = Vec::new();
let item = HashMap::new();
if path.exists() {
let mut file = match File::open(&path) {
Ok(f) => f,
Err(e) => {
panic!("Error at exists {}", e);
return Err(MainError::FileReadError(e.to_string()))
}
};
file.read_to_end(&mut buffer)
.map_err(|e| {
panic!("Got error: {}", e);
return MainError::FileReadError(e.to_string())
})?;
} else {
let _ = match File::create(&path) {
Ok(f) => f,
Err(e) => {
panic!("Error at not exists {}", e);
return Err(MainError::FileReadError(e.to_string()))
}
};
}
let recent: HashMap<Bytes, Bytes> = HashMap::new();
Ok(Memory {path, buffer: Bytes::from(buffer), item, recent })
}

pub fn load(&'a mut self) {
    for line in self.buffer.split(|b| *b == b'\n') {
        let mut line_data = line.split(|b| *b == b'\t');
        if let (Some(key), Some(value)) = (line_data.next(), line_data.next()) {
            self.item.insert(key, value);
        }
    }
}
async fn write_file(&'a mut self, value: Vec<u8>) {
    let mut file = OpenOptions::new().append(true).write(true).open(&self.path).await.unwrap();
    let _ = file.write(&value).await;
    self.load();
}

}
I want to be able to perform fast searching of data using keys, which is why I created a field item, which is a hashmap in the memory struct. I just want this field to hold references to data in the buffer field so that I don't have to create copies of it.
My only issue is when I create a memory and then call load to load the bytes in the buffer into item field, I get an error when I then use it in the Arc::mutex::().
As you would see in the code below.
let path = PathBuf::from("src/files/_data.bin");

let mut memory = match Memory::new(path) {
    Ok(m) => m,
    Err(e) => {
        eprintln!("{}", e);
        return
    }
};
memory.load();
let resource = Arc::new(Mutex::new(memory)); 

If there another way I can go about this. I am new to rust and still trying to understand rust better.

The problem you are facing is known as self-referential structs, and one of the most common pitfalls for newcomers to Rust.

The best advice I can give you is not to use references when you have just started learning Rust. Copying values is ok.

1 Like

Please read the pinned formatting post.

You can edit your OP to follow the formatting to make the code much easier to read.

fn main() {
    println!("Look, my code looks nice and highlighted!");
}

Besides that, don’t use references in structs. References are for temporary views into data stored somewhere else. In a lot of OOP languages, you can own something “by reference”. Those “references” are not the same as &/&mut, they’re more like Box or Arc.
Don’t be afraid to Clone data to make your code simpler.

When you do use a &T, think about what owns the T. It must be something that lives longer than the reference.

As a solution for your actual problem, just use Vec<u8> as your HashMap keys and values. A struct can’t hold a & to data within itself.

3 Likes

Thank you

Really appreciate and I would try using code formatting next time.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.