use crate::{
actors::queue::{
data_item::{FileDatum, RawDatum},
error::Error as QueueError,
messages::{Dequeue, Enqueue, GetLength},
Queue,
},
userscript_api::{
fs_api::path_obj::PathObj,
include::{LuaEither, LuaUserDataRef},
ApiObject,
},
};
use kameo::actor::WeakActorRef;
use mlua::{ExternalError, Lua, UserData, UserDataRef};
use std::path::PathBuf;
pub struct QueueApi(WeakActorRef<Queue>);
impl QueueApi {
#[must_use]
pub fn new(queue: WeakActorRef<Queue>) -> Self {
Self(queue)
}
}
impl UserData for QueueApi {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_async_method("add_raw", queue_add_raw);
methods.add_async_method("add_file", queue_add_file);
methods.add_async_method("dequeue", queue_dequeue);
methods.add_async_method("len", queue_len);
methods.add_async_meta_method("__len", queue_len);
}
}
impl ApiObject for QueueApi {
fn name(&self) -> &'static str {
"queue"
}
}
async fn queue_add_raw(
_: Lua,
this: UserDataRef<QueueApi>,
(name, content): (String, String),
) -> mlua::Result<()> {
if let Some(queue) = this.0.upgrade() {
let data_item: Box<RawDatum> = RawDatum::new(&name, content.as_bytes().to_vec());
if queue.ask(Enqueue::item(data_item)).await.is_err() {
Err(QueueError::SendError.into_lua_err())
} else {
Ok(())
}
} else {
Err(QueueError::NoGlobalQueue.into_lua_err())
}
}
async fn queue_add_file(
_: Lua,
this: UserDataRef<QueueApi>,
path: LuaEither<PathBuf, LuaUserDataRef<PathObj>>,
) -> mlua::Result<()> {
if let Some(queue) = this.0.upgrade() {
let path: PathBuf = match path {
LuaEither::Left(pb) => pb,
LuaEither::Right(po) => po.0.clone(),
};
let data_item: Box<FileDatum> = FileDatum::new(path);
if queue.ask(Enqueue::item(data_item)).await.is_err() {
Err(QueueError::SendError.into_lua_err())
} else {
Ok(())
}
} else {
Err(QueueError::NoGlobalQueue.into_lua_err())
}
}
async fn queue_dequeue(
_: Lua,
this: UserDataRef<QueueApi>,
(): (),
) -> mlua::Result<(String, Option<PathBuf>, impl mlua::IntoLua)> {
if let Some(queue) = this.0.upgrade() {
match queue.ask(Dequeue).await {
Ok((name, path, content)) => {
let content = mlua::String::wrap(content);
Ok((name, path, content))
}
Err(error) => Err(error.into_lua_err()),
}
} else {
Err(QueueError::NoGlobalQueue.into_lua_err())
}
}
async fn queue_len(_: Lua, this: UserDataRef<QueueApi>, (): ()) -> mlua::Result<usize> {
if let Some(queue) = this.0.upgrade() {
queue
.ask(GetLength)
.await
.map_err(mlua::ExternalError::into_lua_err)
} else {
Err(QueueError::NoGlobalQueue.into_lua_err())
}
}