use super::expression::Expression;
use super::ids::{IdAllocator, ImportId};
use super::message::Message;
use super::evaluator::ExpressionEvaluator;
use super::tables::{ExportTable, ImportTable, Value};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct RpcSession {
pub allocator: Arc<IdAllocator>,
pub imports: Arc<ImportTable>,
pub exports: Arc<ExportTable>,
pub evaluator: Arc<Mutex<ExpressionEvaluator>>,
}
impl Default for RpcSession {
fn default() -> Self {
Self::new()
}
}
impl RpcSession {
pub fn new() -> Self {
let allocator = Arc::new(IdAllocator::new());
let imports = Arc::new(ImportTable::new(allocator.clone()));
let exports = Arc::new(ExportTable::new(allocator.clone()));
let evaluator = Arc::new(Mutex::new(ExpressionEvaluator::new(
imports.clone(),
exports.clone(),
)));
Self {
allocator,
imports,
exports,
evaluator,
}
}
pub async fn handle_message(&self, msg: Message) -> Result<(), SessionError> {
match msg {
Message::Push(expr) => {
let _import_id = self.imports.allocate_local();
let _ = self.evaluator.lock().await.evaluate(expr).await?;
Ok(())
}
Message::Pull(_import_id) => {
Ok(())
}
Message::Resolve(export_id, expr) => {
let value = self.evaluator.lock().await.evaluate(expr).await?;
self.exports.resolve(export_id, value).await?;
Ok(())
}
Message::Reject(export_id, expr) => {
let error = self.evaluator.lock().await.evaluate(expr).await?;
self.exports.reject(export_id, error).await?;
Ok(())
}
Message::Release(import_id, refcount) => {
self.imports.release(import_id, refcount)?;
Ok(())
}
Message::Abort(expr) => {
let _ = self.evaluator.lock().await.evaluate(expr).await?;
Ok(())
}
}
}
pub async fn push(&self, _expr: Expression) -> ImportId {
self.imports.allocate_local()
}
pub async fn pull(&self, _import_id: ImportId) -> Result<Value, SessionError> {
Err(SessionError::NotImplemented)
}
}
#[derive(Debug, thiserror::Error)]
pub enum SessionError {
#[error("Feature not yet implemented")]
NotImplemented,
#[error("Evaluator error: {0}")]
EvaluatorError(#[from] super::evaluator::EvaluatorError),
#[error("Table error: {0}")]
TableError(#[from] super::tables::TableError),
#[error("Transport error")]
TransportError,
}