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
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use tokio::sync::oneshot;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DropBearRecvError {
SenderDropped,
}
pub struct DropBearHandle<T>(oneshot::Receiver<T>);
impl<T> Future for DropBearHandle<T> {
type Output = Result<T, DropBearRecvError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match oneshot::Receiver::poll(Pin::new(&mut self.0), cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(Ok(x)) => Poll::Ready(Ok(x)),
Poll::Ready(Err(_e)) => Poll::Ready(Err(DropBearRecvError::SenderDropped)),
}
}
}
pub struct DropBear<T> {
inner: Option<(T, oneshot::Sender<T>)>,
}
impl<T> DropBear<T> {
pub fn new(item: T) -> (Self, DropBearHandle<T>) {
let (send, recv) = oneshot::channel();
(
Self {
inner: Some((item, send)),
},
DropBearHandle(recv),
)
}
pub fn into_inner(mut self) -> T {
match std::mem::replace(&mut self.inner, None) {
None => unreachable!("into_inner called multiple times (?) or after drop?"),
Some((val, _sender)) => val,
}
}
}
impl<T> Drop for DropBear<T> {
fn drop(&mut self) {
match std::mem::replace(&mut self.inner, None) {
None => {
}
Some((val, sender)) => match sender.send(val) {
Ok(()) => {}
Err(_val) => {
}
},
}
}
}
impl<T> std::ops::Deref for DropBear<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match &self.inner {
None => unreachable!("DropBear dereferenced after drop?"),
Some((x, _sender)) => x,
}
}
}
impl<T> std::ops::DerefMut for DropBear<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match &mut self.inner {
None => unreachable!("DropBear dereferenced after drop?"),
Some((x, _sender)) => x,
}
}
}
impl<T> std::convert::AsRef<T> for DropBear<T> {
fn as_ref(&self) -> &T {
&*self
}
}
impl<T> std::convert::AsMut<T> for DropBear<T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for DropBear<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.as_ref(), f)
}
}
impl<T: std::fmt::Display> std::fmt::Display for DropBear<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.as_ref(), f)
}
}
impl<T: std::cmp::PartialEq> std::cmp::PartialEq for DropBear<T> {
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(other.as_ref())
}
}
impl<T: std::cmp::Eq + std::cmp::PartialEq> std::cmp::Eq for DropBear<T> {}
impl<T: std::cmp::PartialOrd> std::cmp::PartialOrd for DropBear<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}
impl<T: std::cmp::Ord + std::cmp::PartialOrd> std::cmp::Ord for DropBear<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_ref().cmp(other.as_ref())
}
}