ferroui_base/utilities/
synchronous_completion_async_result.rs1use std::cell::RefCell;
2use std::rc::Rc;
3
4#[derive(Clone)]
7pub struct SynchronousCompletionAsyncResult<T: Clone> {
8 state: State<T>,
9}
10
11#[derive(Clone)]
12enum State<T: Clone> {
13 Result(T),
14 Source(SynchronousCompletionAsyncResultSource<T>),
15}
16
17impl<T: Clone + 'static> SynchronousCompletionAsyncResult<T> {
18 pub fn new(result: T) -> Self {
20 Self { state: State::Result(result) }
21 }
22
23 pub fn is_completed(&self) -> bool {
24 match &self.state {
25 State::Result(_) => true,
26 State::Source(source) => source.is_completed(),
27 }
28 }
29
30 pub fn get_result(&self) -> T {
32 match &self.state {
33 State::Result(result) => result.clone(),
34 State::Source(source) => source.result(),
35 }
36 }
37
38 pub fn on_completed(&self, continuation: impl FnOnce() + 'static) {
41 match &self.state {
42 State::Result(_) => continuation(),
43 State::Source(source) => source.on_completed(Box::new(continuation)),
44 }
45 }
46}
47
48struct SourceInner<T> {
49 result: Option<T>,
50 continuations: Vec<Box<dyn FnOnce()>>,
51}
52
53pub struct SynchronousCompletionAsyncResultSource<T> {
55 inner: Rc<RefCell<SourceInner<T>>>,
56}
57
58impl<T> Clone for SynchronousCompletionAsyncResultSource<T> {
59 fn clone(&self) -> Self {
60 Self { inner: self.inner.clone() }
61 }
62}
63
64impl<T: Clone + 'static> Default for SynchronousCompletionAsyncResultSource<T> {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl<T: Clone + 'static> SynchronousCompletionAsyncResultSource<T> {
71 pub fn new() -> Self {
72 Self { inner: Rc::new(RefCell::new(SourceInner { result: None, continuations: Vec::new() })) }
73 }
74
75 pub fn async_result(&self) -> SynchronousCompletionAsyncResult<T> {
77 SynchronousCompletionAsyncResult { state: State::Source(self.clone()) }
78 }
79
80 pub(crate) fn is_completed(&self) -> bool {
81 self.inner.borrow().result.is_some()
82 }
83
84 pub(crate) fn result(&self) -> T {
85 self.inner.borrow().result.clone().expect("Asynchronous operation is not yet completed")
86 }
87
88 pub(crate) fn on_completed(&self, continuation: Box<dyn FnOnce()>) {
89 self.inner.borrow_mut().continuations.push(continuation);
90 }
91
92 pub fn set_result(&self, result: T) {
95 let continuations = {
96 let mut inner = self.inner.borrow_mut();
97 if inner.result.is_some() {
98 panic!("Asynchronous operation is already completed");
99 }
100 inner.result = Some(result);
101 std::mem::take(&mut inner.continuations)
102 };
103 for continuation in continuations {
104 continuation();
105 }
106 }
107
108 pub fn try_set_result(&self, result: T) {
110 if self.is_completed() {
111 return;
112 }
113 self.set_result(result);
114 }
115}