use super::legacy::{LegacyOperation, legacy};
use super::{Completion, c_string, receive};
use crate::channel::mpsc;
use emscripten_rs_sys as ffi;
use std::{
ffi::{CStr, c_char, c_void},
io,
};
unsafe extern "C" {
fn free(ptr: *mut c_void);
}
#[deprecated(note = "uses serialized legacy callbacks; use preload_data for in-memory assets")]
pub async fn preload(file: &str) -> io::Result<()> {
std::fs::metadata(file)?;
legacy(LegacyOperation::Preload(c_string(file)?)).await
}
struct PreloadData {
sender: Completion<String>,
data: Vec<u8>,
}
pub async fn preload_data(data: &[u8], suffix: &str) -> io::Result<String> {
unsafe extern "C" fn loaded(arg: *mut c_void, name: *const c_char) {
let state = unsafe { Box::from_raw(arg.cast::<PreloadData>()) };
let name_string = unsafe { CStr::from_ptr(name) }
.to_string_lossy()
.into_owned();
unsafe { free(name.cast_mut().cast()) };
let _ = state.sender.send(Ok(name_string));
}
unsafe extern "C" fn error(arg: *mut c_void) {
let state = unsafe { Box::from_raw(arg.cast::<PreloadData>()) };
let _ = state.sender.send(Err(io::Error::other("preload failed")));
}
let suffix = c_string(suffix)?;
let len = i32::try_from(data.len())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
let (sender, receiver) = mpsc::bounded(1);
let mut state = Box::new(PreloadData {
sender,
data: data.to_vec(),
});
let data_ptr = state.data.as_mut_ptr().cast();
let arg = Box::into_raw(state).cast();
unsafe {
ffi::emscripten_run_preload_plugins_data(
data_ptr,
len,
suffix.as_ptr(),
arg,
Some(loaded),
Some(error),
)
};
receive(receiver).await
}