use super::{Completion, receive};
use crate::channel::mpsc;
use emscripten_rs_sys as ffi;
use std::{
cell::RefCell,
ffi::{CString, c_char},
io,
};
static LEGACY_LOCK: futures::lock::Mutex<()> = futures::lock::Mutex::new(());
thread_local! {
static LEGACY_REQUEST: RefCell<Option<LegacyRequest>> = const { RefCell::new(None) };
}
pub(super) enum LegacyOperation {
Download(CString, CString),
LoadScript(CString),
Preload(CString),
}
struct LegacyRequest {
_operation: LegacyOperation,
sender: Completion<()>,
_guard: futures::lock::MutexGuard<'static, ()>,
}
fn legacy_complete(result: io::Result<()>) {
let request = LEGACY_REQUEST.with(|slot| slot.borrow_mut().take().unwrap());
let _ = request.sender.send(result);
}
unsafe extern "C" fn legacy_success() {
legacy_complete(Ok(()));
}
unsafe extern "C" fn legacy_error() {
legacy_complete(Err(io::Error::other("Emscripten operation failed")));
}
unsafe extern "C" fn legacy_file_success(_: *const c_char) {
legacy_complete(Ok(()));
}
unsafe extern "C" fn legacy_file_error(_: *const c_char) {
legacy_complete(Err(io::Error::other("file operation failed")));
}
pub(super) async fn legacy(operation: LegacyOperation) -> io::Result<()> {
let guard = LEGACY_LOCK.lock().await;
let (sender, receiver) = mpsc::bounded(1);
let (kind, first, second) = match &operation {
LegacyOperation::Download(url, file) => (0, url.as_ptr(), file.as_ptr()),
LegacyOperation::LoadScript(url) => (1, url.as_ptr(), std::ptr::null()),
LegacyOperation::Preload(file) => (2, file.as_ptr(), std::ptr::null()),
};
LEGACY_REQUEST.with(|slot| {
*slot.borrow_mut() = Some(LegacyRequest {
_operation: operation,
sender,
_guard: guard,
});
});
unsafe {
match kind {
0 => ffi::emscripten_async_wget(
first,
second,
Some(legacy_file_success),
Some(legacy_file_error),
),
1 => ffi::emscripten_async_load_script(first, Some(legacy_success), Some(legacy_error)),
_ => {
if ffi::emscripten_run_preload_plugins(
first,
Some(legacy_file_success),
Some(legacy_file_error),
) != 0
{
legacy_complete(Err(io::Error::new(
io::ErrorKind::NotFound,
"preload file not found",
)));
}
}
}
}
receive(receiver).await
}