use super::{c_string, complete, completion, failed, loaded_bytes, receive, succeeded};
use emscripten_functions_sys::emscripten as ffi;
use std::{
ffi::{CString, c_void},
io,
};
#[derive(Clone, Debug)]
pub struct Idb {
name: CString,
}
impl Idb {
pub fn new(name: &str) -> io::Result<Self> {
Ok(Self {
name: c_string(name)?,
})
}
pub async fn load(&self, key: &str) -> io::Result<Vec<u8>> {
let key = c_string(key)?;
let (arg, receiver) = completion::<Vec<u8>>();
unsafe {
ffi::emscripten_idb_async_load(
self.name.as_ptr(),
key.as_ptr(),
arg,
Some(loaded_bytes),
Some(failed::<Vec<u8>>),
);
}
receive(receiver).await
}
pub async fn store(&self, key: &str, data: &[u8]) -> io::Result<()> {
let key = c_string(key)?;
let len = i32::try_from(data.len())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
let (arg, receiver) = completion::<()>();
unsafe {
ffi::emscripten_idb_async_store(
self.name.as_ptr(),
key.as_ptr(),
data.as_ptr().cast_mut().cast(),
len,
arg,
Some(succeeded),
Some(failed::<()>),
);
}
receive(receiver).await
}
pub async fn delete(&self, key: &str) -> io::Result<()> {
let key = c_string(key)?;
let (arg, receiver) = completion::<()>();
unsafe {
ffi::emscripten_idb_async_delete(
self.name.as_ptr(),
key.as_ptr(),
arg,
Some(succeeded),
Some(failed::<()>),
);
}
receive(receiver).await
}
pub async fn exists(&self, key: &str) -> io::Result<bool> {
unsafe extern "C" fn exists(arg: *mut c_void, value: i32) {
unsafe { complete(arg, Ok(value != 0)) };
}
let key = c_string(key)?;
let (arg, receiver) = completion::<bool>();
unsafe {
ffi::emscripten_idb_async_exists(
self.name.as_ptr(),
key.as_ptr(),
arg,
Some(exists),
Some(failed::<bool>),
);
}
receive(receiver).await
}
pub async fn clear(&self) -> io::Result<()> {
let (arg, receiver) = completion::<()>();
unsafe {
ffi::emscripten_idb_async_clear(
self.name.as_ptr(),
arg,
Some(succeeded),
Some(failed::<()>),
)
};
receive(receiver).await
}
}