New to Rust, I am having some issues when using RefCell. I need to retrieve some data from an API. To avoid making too many requests, I have a structure with an hashmap serving as a cache.
I was thinking RefCell would be the solution to my problem but the data doesn’t seem to live after my populate method. I have made a simplified version below to illustrate.
use std::{cell::RefCell, collections::HashMap};
struct Database {
my_map: RefCell<HashMap<String, usize>>,
}
impl Database {
fn search(&self, key: &str) {
if self.my_map.borrow().is_empty() {
populate(RefCell::clone(&self.my_map));
}
if let Some(value) = self.my_map.borrow().get(key) {
println!("Key: {}, Value {}", key, value);
} else {
println!("{} not found", key);
}
}
}
fn populate(map: RefCell<HashMap<String, usize>>) {
println!("Populating my_map");
map.borrow_mut().insert("a".to_string(), 1);
map.borrow_mut().insert("b".to_string(), 2);
map.borrow_mut().insert("c".to_string(), 3);
println!("The map has {} elements after populate", map.borrow().len());
}
fn main() {
let db = Database {
my_map: RefCell::new(HashMap::new()),
};
db.search("a");
db.search("b");
println!("The end: the map has {} elements", db.my_map.borrow().len());
}
$ cargo run
Populating my_map
The map has 3 elements after populate
a not found
Populating my_map
The map has 3 elements after populate
b not found
The end: the map has 0 elements
This creates a completely new RefCell that has nothing to do with self.my_map, the clone being completely separate from the original value. You probably wanted to wrap the RefCell in an Rc (a reference counted smart pointer type that allows shared ownership) and clone that, creating two pointers to the same RefCell. That'd be the classic single threaded interior mutablilty setup in Rust.