make eval copy

This commit is contained in:
Evan Almloff committed 2024-02-02 14:47:59 -06:00
1 parent 894a79d3df
commit a789d6a64e
13 files changed
+191 -107

No files matched your search

+26 -12
View File
@@ -1,26 +1,32 @@
#![allow(clippy::await_holding_refcell_ref)]
use async_trait::async_trait;
use dioxus_core::prelude::*;
use std::future::{Future, IntoFuture};
use generational_box::GenerationalBox;
use std::future::{poll_fn, Future, IntoFuture};
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll};
/// A struct that implements EvalProvider is sent through [`ScopeState`]'s provide_context function
/// so that [`use_eval`] can provide a platform agnostic interface for evaluating JavaScript code.
pub trait EvalProvider {
fn new_evaluator(&self, js: String) -> Result<Box<dyn Evaluator>, EvalError>;
fn new_evaluator(&self, js: String) -> Result<GenerationalBox<Box<dyn Evaluator>>, EvalError>;
}
/// The platform's evaluator.
#[async_trait(?Send)]
pub trait Evaluator {
/// Sends a message to the evaluated JavaScript.
fn send(&self, data: serde_json::Value) -> Result<(), EvalError>;
/// Receive any queued messages from the evaluated JavaScript.
async fn recv(&mut self) -> Result<serde_json::Value, EvalError>;
fn poll_recv(
&mut self,
context: &mut Context<'_>,
) -> Poll<Result<serde_json::Value, EvalError>>;
/// Gets the return value of the JavaScript
async fn join(&self) -> Result<serde_json::Value, EvalError>;
fn poll_join(
&mut self,
context: &mut Context<'_>,
) -> Poll<Result<serde_json::Value, EvalError>>;
}
type EvalCreator = Rc<dyn Fn(&str) -> Result<UseEval, EvalError>>;
@@ -54,28 +60,36 @@ pub fn eval(script: &str) -> Result<UseEval, EvalError> {
/// A wrapper around the target platform's evaluator.
pub struct UseEval {
evaluator: Box<dyn Evaluator + 'static>,
evaluator: GenerationalBox<Box<dyn Evaluator>>,
}
impl UseEval {
/// Creates a new UseEval
pub fn new(evaluator: Box<dyn Evaluator + 'static>) -> Self {
pub fn new(evaluator: GenerationalBox<Box<dyn Evaluator + 'static>>) -> Self {
Self { evaluator }
}
/// Sends a [`serde_json::Value`] to the evaluated JavaScript.
pub fn send(&self, data: serde_json::Value) -> Result<(), EvalError> {
self.evaluator.send(data)
self.evaluator.read().send(data)
}
/// Gets an UnboundedReceiver to receive messages from the evaluated JavaScript.
pub async fn recv(&mut self) -> Result<serde_json::Value, EvalError> {
self.evaluator.recv().await
poll_fn(|cx| match self.evaluator.try_write() {
Ok(mut evaluator) => evaluator.poll_recv(cx),
Err(_) => Poll::Ready(Err(EvalError::Finished)),
})
.await
}
/// Gets the return value of the evaluated JavaScript.
pub async fn join(self) -> Result<serde_json::Value, EvalError> {
self.evaluator.join().await
poll_fn(|cx| match self.evaluator.try_write() {
Ok(mut evaluator) => evaluator.poll_join(cx),
Err(_) => Poll::Ready(Err(EvalError::Finished)),
})
.await
}
}
@@ -92,7 +106,7 @@ impl IntoFuture for UseEval {
#[derive(Debug)]
pub enum EvalError {
/// The platform does not support evaluating JavaScript.
Unspported,
Unsupported,
/// The provided JavaScript has already been ran.
Finished,