1use std::cell::RefCell;
6use std::rc::Rc;
7use std::sync::mpsc::{self, Receiver, Sender};
8use std::thread;
9
10type AsyncChannel<T> = (Sender<Result<T, String>>, Receiver<Result<T, String>>);
12
13#[derive(Clone)]
15pub enum Async<T: Clone> {
16 Loading,
18 Ready(T),
20 Error(String),
22}
23
24impl<T: Clone> Async<T> {
25 pub fn is_loading(&self) -> bool {
27 matches!(self, Async::Loading)
28 }
29
30 pub fn is_ready(&self) -> bool {
32 matches!(self, Async::Ready(_))
33 }
34
35 pub fn is_error(&self) -> bool {
37 matches!(self, Async::Error(_))
38 }
39
40 pub fn get(&self) -> Option<&T> {
42 match self {
43 Async::Ready(v) => Some(v),
44 _ => None,
45 }
46 }
47
48 pub fn unwrap_or(&self, default: T) -> T {
50 match self {
51 Async::Ready(v) => v.clone(),
52 _ => default,
53 }
54 }
55
56 pub fn unwrap_or_else(&self, f: impl FnOnce() -> T) -> T {
58 match self {
59 Async::Ready(v) => v.clone(),
60 _ => f(),
61 }
62 }
63}
64
65pub(crate) struct AsyncInner<T> {
67 result: Option<Result<T, String>>,
69 started: bool,
71 receiver: Option<Receiver<Result<T, String>>>,
73}
74
75pub struct AsyncHandle<T> {
77 inner: Rc<RefCell<AsyncInner<T>>>,
78}
79
80impl<T> Clone for AsyncHandle<T> {
81 fn clone(&self) -> Self {
82 Self {
83 inner: Rc::clone(&self.inner),
84 }
85 }
86}
87
88impl<T: Clone + Send + 'static> AsyncHandle<T> {
89 pub fn new() -> Self {
91 Self {
92 inner: Rc::new(RefCell::new(AsyncInner {
93 result: None,
94 started: false,
95 receiver: None,
96 })),
97 }
98 }
99
100 pub fn start<F>(&self, f: F)
102 where
103 F: FnOnce() -> Result<T, String> + Send + 'static,
104 {
105 let mut inner = self.inner.borrow_mut();
106 if inner.started {
107 return;
108 }
109
110 inner.started = true;
111
112 let (tx, rx): AsyncChannel<T> = mpsc::channel();
114 inner.receiver = Some(rx);
115
116 thread::spawn(move || {
118 let result = f();
119 let _ = tx.send(result);
120 });
121 }
122
123 pub fn poll(&self) -> Async<T>
125 where
126 T: Clone,
127 {
128 let mut inner = self.inner.borrow_mut();
129
130 if let Some(ref result) = inner.result {
132 return match result {
133 Ok(v) => Async::Ready(v.clone()),
134 Err(e) => Async::Error(e.clone()),
135 };
136 }
137
138 if let Some(ref receiver) = inner.receiver {
140 match receiver.try_recv() {
141 Ok(result) => {
142 let async_result = match &result {
143 Ok(v) => Async::Ready(v.clone()),
144 Err(e) => Async::Error(e.clone()),
145 };
146 inner.result = Some(result);
147 return async_result;
148 }
149 Err(mpsc::TryRecvError::Empty) => {
150 return Async::Loading;
152 }
153 Err(mpsc::TryRecvError::Disconnected) => {
154 let error = "Async operation failed: channel disconnected".to_string();
156 inner.result = Some(Err(error.clone()));
157 return Async::Error(error);
158 }
159 }
160 }
161
162 Async::Loading
163 }
164
165 #[allow(dead_code)]
167 pub fn reset(&self) {
168 let mut inner = self.inner.borrow_mut();
169 inner.result = None;
170 inner.started = false;
171 inner.receiver = None;
172 }
173}
174
175impl<T: Clone + Send + 'static> Default for AsyncHandle<T> {
176 fn default() -> Self {
177 Self::new()
178 }
179}