rune_alloc/btree/
mem.rs

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
36
37
38
39
40
use core::mem;

use crate::ptr;

/// This replaces the value behind the `v` unique reference by calling the
/// relevant function.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[allow(dead_code)] // keep as illustration and for future use
#[inline]
pub(crate) fn take_mut<T, E>(v: &mut T, change: impl FnOnce(T) -> Result<T, E>) -> Result<(), E> {
    replace(v, |value| Ok((change(value)?, ())))
}

/// This replaces the value behind the `v` unique reference by calling the
/// relevant function, and returns a result obtained along the way.
///
/// If a panic occurs in the `change` closure, the entire process will be aborted.
#[inline]
pub(crate) fn replace<T, R, E>(
    v: &mut T,
    change: impl FnOnce(T) -> Result<(T, R), E>,
) -> Result<R, E> {
    struct PanicGuard;

    impl Drop for PanicGuard {
        fn drop(&mut self) {
            crate::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);
    Ok(ret)
}