use std::{
future::Future,
ops::Deref,
path::Path,
pin::Pin,
task::{Context, Poll},
};
use futures::task::noop_waker_ref;
use crate::{env::Std, raw, PageIter, Result, TableOptions};
#[derive(Clone, Debug)]
pub struct Table(raw::Table<Std>);
impl Table {
pub fn open<P: AsRef<Path>>(path: P, options: TableOptions) -> Result<Self> {
let table = poll(raw::Table::open(Std, path, options))?;
Ok(Self(table))
}
pub fn close(self) -> Result<(), Self> {
poll(self.0.close()).map_err(Self)
}
pub fn pin(&self) -> Guard<'_> {
Guard(self.0.pin())
}
pub fn get(&self, key: &[u8], lsn: u64) -> Result<Option<Vec<u8>>> {
poll(self.0.get(key, lsn))
}
pub fn put(&self, key: &[u8], lsn: u64, value: &[u8]) -> Result<()> {
poll(self.0.put(key, lsn, value))
}
pub fn delete(&self, key: &[u8], lsn: u64) -> Result<()> {
poll(self.0.delete(key, lsn))
}
}
impl Deref for Table {
type Target = raw::Table<Std>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct Guard<'a>(raw::Guard<'a, Std>);
impl<'a> Guard<'a> {
pub fn get(&self, key: &[u8], lsn: u64) -> Result<Option<&[u8]>> {
poll(self.0.get(key, lsn))
}
pub fn pages(&self) -> Pages<'_, 'a> {
Pages(self.0.pages())
}
}
impl<'a> Deref for Guard<'a> {
type Target = raw::Guard<'a, Std>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct Pages<'a, 't>(raw::Pages<'a, 't, Std>);
impl<'a, 't> Pages<'a, 't> {
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Result<Option<PageIter<'_>>> {
poll(self.0.next())
}
}
impl<'a, 't> Deref for Pages<'a, 't> {
type Target = raw::Pages<'a, 't, Std>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn poll<F: Future>(mut future: F) -> F::Output {
let cx = &mut Context::from_waker(noop_waker_ref());
loop {
let fut = unsafe { Pin::new_unchecked(&mut future) };
match fut.poll(cx) {
Poll::Ready(output) => return output,
Poll::Pending => std::hint::spin_loop(),
}
}
}