Hello everybody,
I have a struct, that keeps data that needs to be valid as long as the struct exists, and offers methods to add data to it. Because of the lifetime and mutability requirements, I get a cannot borrow
x as mutable more than once
error.
I understand why this happens, and I'm wondering what my best options are to overcome it. Currently, I believe, interior mutability via RefCell
or Mutex
is the way to go, but I'm curious what others think.
The not working code looks as follows (Playground):
use std::borrow::Cow;
use std::collections::HashMap;
/// HTML Input element
struct Input<'input> {
name: &'input str,
}
/// HTML form element
struct Form<'form> {
data: HashMap<&'form str, Cow<'form, str>>,
elements: Vec<Input<'form>>,
}
impl<'form> Form<'form> {
fn fill<F: FnOnce(&'form Input) -> Cow<'form, str>>(&'form mut self, with: F) {
let input = &self.elements[0];
let value = with(input);
self.data.insert(input.name, value.into());
}
}
fn main() {
let mut form = Form {data: HashMap::new(), elements: vec![Input {name: "foo"}]};
form.fill(|el| Cow::Borrowed(el.name));
form.fill(|el| Cow::Borrowed(el.name));
}
Error: cannot borrow
form as mutable more than once at a time
Using RefCell
fixes the problem (see this Playground).
Form
is part of an HTTP client I'm working on, and will be used in a multithreaded, async context. If I'm not mistaken, using RefCell
means, there could be no .await
until the form is submitted (which consumes the Form
).
Normally, there would not be a need to .await
something while "filling out" a form, but I can't be sure that this always will be the case.
Another option, therefore, would be, to use a Mutex
, instead of the RefCell
.
As far as I know, this would have more overhead than RefCell
, so I'd like to avoid it.
On the other hand, the overhead of Mutex
should be minuscule compared to the other stuff that is going on (HTTP requests, and parsing HTML). Besides that, if I'm not mistaken, there normally shouldn't be any contention for the Mutex
(currently, I give users mutable access to the Form
data, so in theory contention would be possible).
With that information, what do you think, would be the best approach here?