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
use std::mem;
use std::process;
#[inline]
pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
struct Bomb;
impl Drop for Bomb {
fn drop(&mut self) {
process::abort();
}
}
let bomb = Bomb;
let t = f();
mem::forget(bomb);
t
}
#[doc(hidden)]
#[macro_export]
macro_rules! extension_trait {
(
#[doc = $doc:tt]
pub trait $name:ident {
$($body_base:tt)*
}
pub trait $ext:ident: $base:path {
$($body_ext:tt)*
}
$($imp:item)*
) => {
#[allow(dead_code)]
mod owned {
#[doc(hidden)]
pub struct ImplFuture<T>(std::marker::PhantomData<T>);
}
#[allow(dead_code)]
mod borrowed {
#[doc(hidden)]
pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>);
}
#[cfg(feature = "docs")]
#[doc = $doc]
pub trait $name {
extension_trait!(@doc () $($body_base)* $($body_ext)*);
}
#[cfg(not(feature = "docs"))]
pub use $base as $name;
pub trait $ext: $base {
extension_trait!(@ext () $($body_ext)*);
}
impl<T: $base + ?Sized> $ext for T {}
$(#[cfg(feature = "docs")] $imp)*
};
(@doc ($($head:tt)*) -> impl Future<Output = $out:ty> [$f:ty] $($tail:tt)*) => {
extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*);
};
(@ext ($($head:tt)*) -> impl Future<Output = $out:ty> $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => {
extension_trait!(@ext ($($head)* -> $f) $($tail)*);
};
(@doc ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*);
};
(@ext ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
extension_trait!(@ext ($($head)* -> $f) $($tail)*);
};
(@doc ($($head:tt)*) $token:tt $($tail:tt)*) => {
extension_trait!(@doc ($($head)* $token) $($tail)*);
};
(@ext ($($head:tt)*) $token:tt $($tail:tt)*) => {
extension_trait!(@ext ($($head)* $token) $($tail)*);
};
(@doc ($($head:tt)*)) => { $($head)* };
(@ext ($($head:tt)*)) => { $($head)* };
}
pub use crate::extension_trait;