(Following "cannot move out of borrowed content" when replacing a struct field)
I have a third-party API where one struct have a method that consumes the instance and returns a new instance; I want to wrap this API in my own wrapper and abstract away the detail that the struct is consumed in the operation.
This example explains what I'm trying to achieve:
// Third-party API
struct Item {
x: u32,
}
impl Item {
pub fn increment(self, amount: u32) -> Self {
Item { x: self.x + amount }
}
}
// My API
struct Container {
item: Item,
}
impl Container {
pub fn increment_item(&mut self, amount: u32) {
// This line causes "cannot move out of borrowed content" but this is exactly what I want to do
self.item = self.item.increment(amount);
}
}
While now I understand the error I'm wondering how can I implement this without taking ownership of self
inside Container::increment_item
.
Proposed solutions:
Item::increment
to take &mut self
instead of self
: I can't, Item::increment
comes from a crate.mem::replace
(from here): Unfortunately constructing an Item
instance it's not that easy, and to be honest I don't completely understand how the mem::replace
solutions works.Container::increment_item
to take self
instead of &mut self
: I don't want to consume the Container
instance in the process, I'm trying to design my wrapper to be as ergonomic as possible and abstract away completely the fact that Item
must be consumed when changing it.Some ideas on how to do it? Or am I trying an impossible design in Rust?
The simplest way is to use an Option
:
take
to take ownership of the item,Some(...)
.If a panic occurs while the Option
is empty, this is perfectly safe. No double-destruction occurs, and the container can even remain usable if you so desire.
Or in code:
// Third-party API
struct Item {
x: u32,
}
impl Item {
pub fn increment(self, amount: u32) -> Self {
Item { x: self.x + amount }
}
}
// My API
struct Container {
item: Option<Item>,
}
impl Container {
pub fn increment_item(&mut self, amount: u32) {
let item = self.item.take().unwrap();
self.item = Some(self.item.increment(amount));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With