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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::ptr;
use std::mem::ManuallyDrop;
use std::cell::Cell;

pub use drop_take_derive::*;

/// Take ownership of members of a type during `Drop::drop` instead of only having a `&mut` to them.
///
/// This trait can be derived, but doing so does not implement the trait; rather,
/// it implements [`Drop`] and compels you to implement `DropTake`.
///
/// Your `DropTake` implementation receives a tuple of all values marked `#[drop_take]`,
/// with their value extracted from the container by [`Take`].
///
/// If you need access to other non-`#[drop_take]` values, either also `#[drop_take]` them,
/// or use [`Take::take`] (or the functions it is a wrapper for) directly in `Drop::drop`.
///
/// # Example
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// use drop_take::DropTake;
///
/// struct Peach;
/// struct Banana;
/// struct Melon;
///
/// #[derive(DropTake)]
/// struct FruitBox {
///     #[drop_take]
///     peach: ManuallyDrop<Peach>,
///     melon: Melon,
///     #[drop_take]
///     banana: ManuallyDrop<Banana>,
/// }
///
/// impl DropTake for FruitBox {
///     type Values = (Peach, Banana);
///     fn drop_take((peach, banana): Self::Values) {
///         // use `peach` and `banana` by value
///         // they're dropped at the end of scope
///     }
/// }
/// ```
pub trait DropTake {
    type Values;

    fn drop_take(_: Self::Values);
}

/// Types that can be taken from during [`DropTake`]-powered deconstructing.
pub trait Take {
    type Value;

    /// Take the contained value out of this container.
    /// `slot` must not be used after calling this method, except to drop it.
    /// Dropping `slot` after calling this method must be safe and not drop the taken value.
    unsafe fn take(slot: &mut Self) -> Self::Value;
}

/// [`Cell::take`]
impl<T: Default> Take for Cell<T> {
    type Value = T;
    unsafe fn take(slot: &mut Self) -> T {
        Cell::take(slot)
    }
}

/// [`Option::take`]
impl<T> Take for Option<T> {
    type Value = Option<T>;
    unsafe fn take(slot: &mut Self) -> Option<T> {
        Option::take(slot)
    }
}

/// [`ManuallyDrop::take`](https://internals.rust-lang.org/t/mini-rfc-manuallydrop-take/8679)
impl<T> Take for ManuallyDrop<T> {
    type Value = T;
    unsafe fn take(slot: &mut Self) -> T {
        ManuallyDrop::into_inner(ptr::read(slot))
    }
}

// Should we implement `Take` for ptr types (`ptr::read`)?
// Are there other types that implement `Take` semantics?