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?