use std::fmt::Debug;
use std::sync::Arc;
use futures::Stream;
use neptune_locks::tokio::AtomicRw;
use serde::de::DeserializeOwned;
use serde::Serialize;
use super::super::storage_vec::traits::*;
use super::super::storage_vec::Index;
use super::dbtvec_private::DbtVecPrivate;
use super::traits::*;
use super::PendingWrites;
use super::SimpleRustyReader;
#[derive(Debug)]
pub struct DbtVec<V> {
inner: DbtVecPrivate<V>,
}
impl<V> DbtVec<V>
where
V: Clone + Serialize + DeserializeOwned,
{
#[inline]
pub(super) async fn new(
pending_writes: AtomicRw<PendingWrites>,
reader: Arc<SimpleRustyReader>,
key_prefix: u8,
name: &str,
) -> Self {
let vec = DbtVecPrivate::<V>::new(pending_writes, reader, key_prefix, name).await;
Self { inner: vec }
}
#[inline]
pub async fn delete_cache(&mut self) {
self.inner.delete_cache().await;
}
}
#[async_trait::async_trait]
impl<V> StorageVecBase<V> for DbtVec<V>
where
V: Clone + Debug,
V: Serialize + DeserializeOwned + Send + Sync,
{
#[inline]
async fn is_empty(&self) -> bool {
self.inner.is_empty().await
}
#[inline]
async fn len(&self) -> Index {
self.inner.len().await
}
#[inline]
async fn get(&self, index: Index) -> V {
self.inner.get(index).await
}
#[inline]
async fn get_many(&self, indices: &[Index]) -> Vec<V> {
self.inner.get_many(indices).await
}
#[inline]
async fn get_all(&self) -> Vec<V> {
self.inner.get_all().await
}
#[inline]
async fn set(&mut self, index: Index, value: V) {
self.inner.set(index, value).await;
}
#[inline]
async fn set_many(&mut self, key_vals: impl IntoIterator<Item = (Index, V)> + Send) {
self.inner
.set_many(key_vals.into_iter().collect::<Vec<_>>())
.await;
}
#[inline]
async fn pop(&mut self) -> Option<V> {
self.inner.pop().await
}
#[inline]
async fn push(&mut self, value: V) {
self.inner.push(value).await;
}
#[inline]
async fn clear(&mut self) {
self.inner.clear().await;
}
}
#[async_trait::async_trait]
impl<V> DbTable for DbtVec<V>
where
V: Clone,
V: Serialize + DeserializeOwned + Send + Sync,
{
#[inline]
async fn restore_or_new(&mut self) {
if let Some(length) = self
.inner
.reader
.get(DbtVecPrivate::<V>::get_length_key(self.inner.key_prefix))
.await
{
self.inner.current_length = Some(length.into_any());
} else {
self.inner.current_length = Some(0);
}
}
}
impl<T: Debug + Serialize + DeserializeOwned + Clone + Send + Sync + 'static> StorageVecStream<T>
for DbtVec<T>
{
async fn stream<'a>(&'a self) -> impl Stream<Item = (Index, T)> + 'a
where
T: 'a,
{
self.stream_many(0..self.len().await)
}
async fn stream_values<'a>(&'a self) -> impl Stream<Item = T> + 'a
where
T: 'a,
{
self.stream_many_values(0..self.len().await)
}
}
impl<T: Debug + Serialize + DeserializeOwned + Clone + Send + Sync + 'static> StorageVec<T>
for DbtVec<T>
{
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use futures::FutureExt;
use macro_rules_attr::apply;
use super::super::SimpleRustyStorage;
use super::*;
use crate::test_utils::shared_tokio_runtime;
use crate::NeptuneLevelDb;
pub async fn mk_test_vec_u64() -> DbtVec<u64> {
let db = NeptuneLevelDb::open_new_test_database(true, None, None, None)
.await
.unwrap();
let mut rusty_storage = SimpleRustyStorage::new(db);
rusty_storage.schema.new_vec::<u64>("test-vector").await
}
#[apply(shared_tokio_runtime)]
async fn correct_length_after_clear_and_persist() {
let db = NeptuneLevelDb::open_new_test_database(true, None, None, None)
.await
.unwrap();
let mut rusty_storage = SimpleRustyStorage::new(db);
let mut vec = rusty_storage.schema.new_vec::<u64>("test-vector").await;
vec.push(32).await;
vec.clear().await;
assert_eq!(0, vec.len().await);
rusty_storage.persist().await;
assert_eq!(0, vec.len().await);
}
#[apply(shared_tokio_runtime)]
async fn correct_length_after_clear_push_and_persist() {
let db = NeptuneLevelDb::open_new_test_database(true, None, None, None)
.await
.unwrap();
let mut rusty_storage = SimpleRustyStorage::new(db);
let mut vec = rusty_storage.schema.new_vec::<u64>("test-vector").await;
vec.push(32).await;
vec.push(33).await;
vec.push(34).await;
vec.clear().await;
vec.push(33).await;
vec.push(34).await;
assert_eq!(2, vec.len().await);
rusty_storage.persist().await;
assert_eq!(2, vec.len().await);
}
#[apply(shared_tokio_runtime)]
async fn panic_on_out_of_bounds_get_and_set() {
let db = NeptuneLevelDb::open_new_test_database(true, None, None, None)
.await
.unwrap();
let mut rusty_storage = SimpleRustyStorage::new(db);
let mut vec = rusty_storage.schema.new_vec::<u64>("test-vector").await;
let empty_list_out_of_bounds = std::panic::AssertUnwindSafe(async {
vec.get(0).await;
})
.catch_unwind()
.await;
assert!(empty_list_out_of_bounds.is_err());
vec.push(44).await;
rusty_storage.persist().await;
assert_eq!(1, vec.inner.persisted_length().await.unwrap());
assert_eq!(1, vec.len().await);
vec.pop().await.unwrap();
assert_eq!(1, vec.inner.persisted_length().await.unwrap());
assert_eq!(0, vec.len().await);
let get_empty_list_unpersisted = std::panic::AssertUnwindSafe(async {
vec.get(0).await;
})
.catch_unwind()
.await;
assert!(
get_empty_list_unpersisted.is_err(),
"get must panic, also when pop is not persisted."
);
let set_empty_list_unpersisted = std::panic::AssertUnwindSafe(async {
vec.set(0, 123).await;
})
.catch_unwind()
.await;
assert!(
set_empty_list_unpersisted.is_err(),
"set must panic, also when pop is not persisted."
);
}
pub mod streams {
use macro_rules_attr::apply;
use super::super::super::super::storage_vec::traits::tests::streams as stream_tests;
use super::*;
use crate::test_utils::shared_tokio_runtime;
#[apply(shared_tokio_runtime)]
pub async fn stream() {
stream_tests::stream(mk_test_vec_u64().await).await
}
#[apply(shared_tokio_runtime)]
pub async fn stream_many() {
stream_tests::stream_many(mk_test_vec_u64().await).await
}
}
}