1use core::intrinsics;
2use core::mem;
3use core::ptr;
4
5/// This replaces the value behind the `v` unique reference by calling the
6/// relevant function.
7///
8/// If a panic occurs in the `change` closure, the entire process will be aborted.
9#[allow(dead_code)] // keep as illustration and for future use
10#[inline]
11pub fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
12 replace(v, |value: T| (change(value), ()))
13}
14
15/// This replaces the value behind the `v` unique reference by calling the
16/// relevant function, and returns a result obtained along the way.
17///
18/// If a panic occurs in the `change` closure, the entire process will be aborted.
19#[inline]
20pub fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
21 struct PanicGuard;
22 impl Drop for PanicGuard {
23 fn drop(&mut self) {
24 intrinsics::abort()
25 }
26 }
27 let guard: PanicGuard = PanicGuard;
28 let value: T = unsafe { ptr::read(src:v) };
29 let (new_value: T, ret: R) = change(value);
30 unsafe {
31 ptr::write(dst:v, src:new_value);
32 }
33 mem::forget(guard);
34 ret
35}
36