To my knowledge you cannot get the new value using the DerefMut trait. You can get the old value. To do what you seem to want one would conventionally use getter and setter methods instead of Deref and DerefMut.
struct DerefMutExample {
value: i32
}
// Getter and setter
impl DerefMutExample {
fn value(&self) -> &i32 {
&self.value
}
fn set_value(&mut self, new_value: i32) {
self.value = new_value;
updated(&self.value);
}
}
// Deref and DerefMut
impl std::ops::Deref for DerefMutExample {
type Target = i32;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl std::ops::DerefMut for DerefMutExample {
fn deref_mut(&mut self) -> &mut Self::Target {
possibly_updated(&self.value);
&mut self.value
}
}
fn possibly_updated(value: &i32) {
println!("Mutable access, previous value was {}", value);
}
fn updated(value: &i32) {
println!("Updated, new value is {}", value);
}
fn main() {
let mut evar = DerefMutExample { value: 1 };
*evar = 2;
// Output: "Mutable access, previous value was 1"
let mut evar = DerefMutExample { value: 1 };
evar.set_value(2);
// Output: "Updated, new value is 2"
}
No, deref_mut happens before the update. There's no way to hook in to the actual write, at least not when going through DerefMut. You can define a set method instead though.
But if you give out a &mut i32 reference, there is no “hook” that lets you run arbitrary code when someone writes to it. And this can't be changed because unsafe code relies on it.
Another option is to return an RAII guard with a Drop implementation instead of &mut _. This isn't possible with DerefMut on the main structure, but could look something like this: