1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use core::intrinsics;
use core::mem;
use core::ptr;

/// 这将通过调用相关函数来替换 `v` 唯一引用后面的值。
///
///
/// 如果 `change` 闭包中出现 panic,则整个进程将被中止。
#[allow(dead_code)] // 作为插图保存,以备将来使用
#[inline]
pub fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
    replace(v, |value| (change(value), ()))
}

/// 这将通过调用相关函数来替换 `v` 唯一引用后面的值,并返回沿途获得的结果。
///
///
/// 如果 `change` 闭包中出现 panic,则整个进程将被中止。
#[inline]
pub fn replace<T, R>(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R {
    struct PanicGuard;
    impl Drop for PanicGuard {
        fn drop(&mut self) {
            intrinsics::abort()
        }
    }
    let guard = PanicGuard;
    let value = unsafe { ptr::read(v) };
    let (new_value, ret) = change(value);
    unsafe {
        ptr::write(v, new_value);
    }
    mem::forget(guard);
    ret
}