Hello,
I write Rust code since three years, but I have some issues with some code architecture. I'm writing a graphic user interface with egui crate.
There is some information about my context :
- I have a JSON which represent expected interface to draw (like html)
- egui input text take a mutable string as parameter (which is modified when input text modified)
So, I have a struct containing the expected interface representation and hashmap of string values to give to egui text inputs. Example:
struct Interface {
values: HashMap<String, String>,
inputs: Vec<String>,
}
impl Interface {
fn new() -> Self {
// These values are determines from the expected interface representation
let mut values = HashMap::new();
values.insert("foo".to_string(), "FOO".to_string());
values.insert("bar".to_string(), "BAR".to_string());
values.insert("baz".to_string(), "BAZ".to_string());
let inputs = vec!["foo".to_string(), "bar".to_string(), "baz".to_string()];
Self { values, inputs }
}
fn draw(&mut self, ui: &mut egui::Ui) {
// To draw the text inpit, I have to iterate over them
for input_name in self.inputs.iter() {
// In my real code I have multiple type of thigs to draw (text input, label, image, buttons, checkbox, etc.)
// So I use methods. BUT "cannot borrow `*self` as mutable because it is also borrowed as immutable"
self.draw_input(ui, input_name)
}
}
fn draw_input(&mut self, ui: &mut egui::Ui, name: &str) {
let value = self.values.get_mut(name).unwrap();
ui.add(egui::TextEdit::singleline(value));
}
}
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:25:13
|
24 | for input_name in self.inputs.iter() {
| ------------------
| |
| immutable borrow occurs here
| immutable borrow later used here
25 | self.draw_input(ui, input_name)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
Call to self.draw_input(ui, input_name)
produce error because I already have self.inputs.iter()
.
I can replace my "sub method" by direct usage of struc attribute like this :
// self.draw_input(ui, input_name)
let value = self.values.get_mut(input_name).unwrap();
ui.add(egui::TextEdit::singleline(value));
But in my real code, I have multiple cases and draw
method will be huge.
How can I deal with that ?
Thanks !