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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! `async_dropper` provides two ad-hoc implementations of asynchronous `drop` behavior (`AsyncDrop`).
//!
//! - `async_dropper::AsyncDropper` is a wrapper struct (suggested on [StackOverflow by paholg](https://stackoverflow.com/a/75584109))
//! - `async_dropper::AsyncDrop` is a `derive` macro which generates code that enables async drop functionality to run during a regular `drop`. That code requires `T: Default + PartialEq + Eq`.
//!
//! Here is a quick example of the shorter `async_dropper::AsyncDropper`:
//!
//! ```ignore
//! // NOTE: you must have the 'simple' feature enabled to use this code!
//!
//! /// This object will be async-dropped (which must be wrapped in AsyncDropper)
//! #[derive(Default)]
//! struct AsyncThing(String);
//!
//! #[async_trait]
//! impl AsyncDrop for AsyncThing {
//! async fn async_drop(&mut self) {
//! tokio::time::sleep(Duration::from_secs(2)).await; // fake work
//! Ok(())
//! }
//! }
//!
//! #[your_async_runtime_of_choice::main] // i.e. tokio::main or async_std::main
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! drop(AsyncDropper::new(AsyncThing(String::from("test"))));
//! Ok(())
//! }
//! ```
//!
//! Note that `AsyncThing` must be wrapped in `async_dropper::AsyncDropper`.
//!
//! For `async_dropper::AsyncDrop`, the simplest example looks like this:
//!
//! ```ignore
//! // NOTE: you must have the 'derive' feature enabled to use this code!
//!
//! use async_dropper::AsyncDrop;
//!
//! // Your struct (named field structs and tuple structs both work)
//! #[derive(Debug, Default, PartialEq, Eq, AsyncDrop)]
//! struct AsyncThing(String);
//!
//! /// How it drops, asynchrounously
//! #[async_trait]
//! impl AsyncDrop for AsyncThing {
//! async fn async_drop(&mut self) -> Result<(), AsyncDropError> {
//! tokio::time::sleep(Duration::from_secs(2)).await; // fake work
//! Ok(())
//! }
//! }
//!
//! #[your_async_runtime_of_choice::main] // i.e. tokio::main or async_std::main
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! drop(AsyncThing(String::from("test")));
//! Ok(())
//! }
//! ```
//!
//! The `async_dropper::AsyncDrop` is interesting because it attempts to automatically (if somewhat painfully) determine
//! whether an object should have the defined asynchronous drop behavior performed by checking whether it is equal
//! to `Self::default()`.
//!
//! **Said differently, async drop behavior is skipped if an instance of `T` is exactly equal to a `T::default()`**.
//!
//! For convenience, a `reset(&mut self)` function that sets any T to T::default() is automatically derived, but it can be overriden via `AsyncDrop#reset()`.
//!
//! If `T` is *not* exactly equal to `T::default()`, the assumption is that `T` must still be holding things that require asynchronous dropping behavior, and as such that behavior will be performed.
//!
//! **If `reset(&mut self)` does not return `T` to a state where it is equal to `T::default()`, `drop` will panic**
/// Re-export #[derive(AsyncDrop)]
extern crate async_dropper_derive;
pub use AsyncDrop;
pub use ;
compile_error!;
compile_error!;
/// What to do when a drop fails
/// Types that can reset themselves to T::default()
/// The operative trait that enables AsyncDrop functionality.
/// Normally, implementing only async_drop(&mut self) and reset(&mut self) is necessary.