1#![deny(
3 dead_code,
4 arithmetic_overflow,
5 invalid_type_param_default,
6 missing_fragment_specifier,
7 mutable_transmutes,
8 no_mangle_const_items,
9 overflowing_literals,
10 patterns_in_fns_without_body,
11 pub_use_of_private_extern_crate,
12 unknown_crate_types,
13 order_dependent_trait_objects,
14 illegal_floating_point_literal_pattern,
15 improper_ctypes,
16 late_bound_lifetime_arguments,
17 non_camel_case_types,
18 non_shorthand_field_patterns,
19 non_snake_case,
20 non_upper_case_globals,
21 no_mangle_generic_items,
22 private_in_public,
23 stable_features,
24 type_alias_bounds,
25 tyvar_behind_raw_pointer,
26 unconditional_recursion,
27 unused_comparisons,
28 unreachable_pub,
29 anonymous_parameters,
30 missing_copy_implementations,
31 missing_debug_implementations,
32 missing_docs,
33 trivial_casts,
34 trivial_numeric_casts,
35 unused_import_braces,
36 unused_qualifications,
37 clippy::all
38)]
39#![forbid(
40 unsafe_code,
41 rustdoc::broken_intra_doc_links,
42 unaligned_references,
43 while_true,
44 bare_trait_objects
45)]
46
47pub trait FutureType<V> {
49 fn on_drop() -> V;
51
52 fn complete(self, result: V);
54}
55
56#[derive(Debug)]
59pub struct Promise<T, V>
60where
61 T: FutureType<V>,
62{
63 inner: Option<T>,
64 _v: std::marker::PhantomData<V>,
65}
66
67impl<T, V> Promise<T, V>
68where
69 T: FutureType<V>,
70{
71 fn new(inner: T) -> Self {
73 Self {
74 inner: Some(inner),
75 _v: Default::default(),
76 }
77 }
78
79 pub fn complete(mut self, result: V) {
81 if let Some(x) = self.inner.take() {
82 x.complete(result);
83 }
84 }
85}
86
87pub fn wrap<T, V>(callback: T) -> Promise<T, V>
89where
90 T: FutureType<V>,
91{
92 Promise::new(callback)
93}
94
95impl<T, V> Drop for Promise<T, V>
96where
97 T: FutureType<V>,
98{
99 fn drop(&mut self) {
100 if let Some(cb) = self.inner.take() {
101 cb.complete(T::on_drop());
102 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 struct Borrowed<'a> {
111 vec: &'a mut Vec<Result<u32, &'static str>>,
112 }
113
114 impl<'a> FutureType<Result<u32, &'static str>> for Borrowed<'a> {
115 fn on_drop() -> Result<u32, &'static str> {
116 Err("dropped")
117 }
118
119 fn complete(self, result: Result<u32, &'static str>) {
120 self.vec.push(result);
121 }
122 }
123
124 #[test]
125 fn completes_on_drop() {
126 let mut output = Vec::new();
127 let _ = wrap(Borrowed { vec: &mut output });
128 assert_eq!(output.as_slice(), [Err("dropped")]);
129 }
130
131 #[test]
132 fn only_completes_once_on_success() {
133 let mut output = Vec::new();
134 let promise = wrap(Borrowed { vec: &mut output });
135 promise.complete(Ok(42));
136 assert_eq!(output.as_slice(), [Ok(42)]);
137 }
138
139 #[test]
140 fn only_completes_once_on_failure() {
141 let mut output = Vec::new();
142 let promise = wrap(Borrowed { vec: &mut output });
143 promise.complete(Err("fail"));
144 assert_eq!(output.as_slice(), [Err("fail")]);
145 }
146}