Add `defer_with_data_by` helper function
This commit is contained in:
parent
13ab54f55d
commit
ab44df311b
38
src/lib.rs
38
src/lib.rs
|
@ -15,11 +15,31 @@
|
|||
//!
|
||||
//! assert_eq!(s.into_inner(), "Hello, World");
|
||||
//! ```
|
||||
//!
|
||||
//! Of course, it sucks to need to resort to runtime borrow checking. Thankfully, the example can be rewritten like so:
|
||||
//! ```
|
||||
//! use drop_guard::defer_with_data_by;
|
||||
//!
|
||||
//! let mut s = String::new();
|
||||
//! {
|
||||
//! let mut s = defer_with_data_by(|s| s.push_str("World"), &mut s);
|
||||
//! let mut s = defer_with_data_by(|s| s.push_str(", "), &mut s);
|
||||
//! s.push_str("Hello");
|
||||
//! }
|
||||
//!
|
||||
//! assert_eq!(s, "Hello, World");
|
||||
//! ```
|
||||
//!
|
||||
//! But, what's going on here? Well, [`DropGuard`] holds on to two values: a [`DropFn`], and an
|
||||
//! optional `data`. When we just call `defer`, `data` will be a `()`, but when we call
|
||||
//! `defer_with_data_by` instead, it will be the second argument. [`DropGuard`] derefences to that data value, enabling you to keep using that
|
||||
//! data while it's guarded!
|
||||
|
||||
pub(crate) mod macros;
|
||||
|
||||
pub mod ext;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
@ -33,6 +53,14 @@ pub const fn defer_with_data<F: DropFn>(f: F, d: F::Data) -> DropGuard<F> {
|
|||
DropGuard::with_data(f, d)
|
||||
}
|
||||
|
||||
/// Defers execution of the provided [`DropFn`], with data `d`, until the returned [`DropGuard`] is dropped.
|
||||
pub const fn defer_with_data_by<D, F>(f: F, d: D) -> DropGuard<FnOnceDropFn<F, D>>
|
||||
where
|
||||
F: FnOnce(D) -> (),
|
||||
{
|
||||
defer_with_data(FnOnceDropFn(f, PhantomData), d)
|
||||
}
|
||||
|
||||
pub trait DropFn {
|
||||
// TODO: Use a default of `()` once the associated_type_defaults (rust-lang/rust#29661) feature lands
|
||||
type Data;
|
||||
|
@ -101,3 +129,13 @@ impl<F: DropFn> DerefMut for DropGuard<F> {
|
|||
&mut self.1
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnOnceDropFn<F: FnOnce(D) -> (), D>(F, PhantomData<fn(D) -> ()>);
|
||||
|
||||
impl<F: FnOnce(D) -> (), D> DropFn for FnOnceDropFn<F, D> {
|
||||
type Data = D;
|
||||
|
||||
fn on_drop(self, data: Self::Data) {
|
||||
self.0(data)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue