bevy_scriptum/src/promise.rs
GolDNenex f9e872e111
Update bevy 0.15 (#36)
* Update bevy 0.15

* Removed unused import "AsyncReadExt"

* Update README.md

* Update lib.rs

* Update README.md

* Fix cargo test by not running examples that never end in lib.rs

* get rid of warnings

* update version references

* dont run examples

* deny warnings

* remove obsolete runners

---------

Co-authored-by: Jarosław Konik <konikjar@gmail.com>
2025-04-15 21:27:08 +02:00

81 lines
2.5 KiB
Rust

use std::sync::{Arc, Mutex};
use crate::{Runtime, ScriptingError};
/// A struct that represents a function that will get called when the Promise is resolved.
pub(crate) struct PromiseCallback<C: Send, V: Send> {
callback: V,
following_promise: Arc<Mutex<PromiseInner<C, V>>>,
}
/// Internal representation of a Promise.
pub(crate) struct PromiseInner<C: Send, V: Send> {
pub(crate) callbacks: Vec<PromiseCallback<C, V>>,
#[allow(deprecated)]
pub(crate) context: C,
}
/// A struct that represents a Promise.
#[derive(Clone)]
pub struct Promise<C: Send, V: Send> {
pub(crate) inner: Arc<Mutex<PromiseInner<C, V>>>,
}
impl<C: Send, V: Send + Clone> PromiseInner<C, V> {
/// Resolve the Promise. This will call all the callbacks that were added to the Promise.
fn resolve<R>(&mut self, runtime: &mut R, val: R::Value) -> Result<(), ScriptingError>
where
R: Runtime<Value = V, CallContext = C>,
{
for callback in &self.callbacks {
let next_val =
runtime.call_fn_from_value(&callback.callback, &self.context, vec![val.clone()])?;
callback
.following_promise
.lock()
.expect("Failed to lock promise mutex")
.resolve(runtime, next_val)?;
}
Ok(())
}
}
impl<C: Clone + Send + 'static, V: Send + Clone> Promise<C, V> {
/// Acquire [Mutex] for writing the promise and resolve it. Call will be forwarded to [PromiseInner::resolve].
pub(crate) fn resolve<R>(
&mut self,
runtime: &mut R,
val: R::Value,
) -> Result<(), ScriptingError>
where
R: Runtime<Value = V, CallContext = C>,
{
if let Ok(mut inner) = self.inner.lock() {
inner.resolve(runtime, val)?;
}
Ok(())
}
/// Register a callback that will be called when the [Promise] is resolved.
#[cfg(any(feature = "rhai", feature = "lua"))]
pub(crate) fn then(&mut self, callback: V) -> Self {
let mut inner = self
.inner
.lock()
.expect("Failed to lock inner promise mutex");
let following_inner = Arc::new(Mutex::new(PromiseInner {
callbacks: vec![],
context: inner.context.clone(),
}));
inner.callbacks.push(PromiseCallback {
following_promise: following_inner.clone(),
callback,
});
Promise {
inner: following_inner,
}
}
}