use std::sync::Arc;
use auto_impl::auto_impl;
use bytes::BytesMut;
use futures::StreamExt;
use super::byte_range::ByteRangeIterator;
use super::{
MaybeSend, MaybeSync, StorageError, StoreKey, StoreKeys, StoreKeysPrefixes, StorePrefix,
StorePrefixes,
};
use crate::byte_range::ByteRange;
use crate::{AsyncMaybeBytesIterator, Bytes, MaybeBytes, OffsetBytesIterator};
#[cfg_attr(
all(feature = "async", not(target_arch = "wasm32")),
async_trait::async_trait
)]
#[cfg_attr(all(feature = "async", target_arch = "wasm32"), async_trait::async_trait(?Send))]
#[auto_impl(Arc)]
pub trait AsyncReadableStorageTraits: MaybeSend + MaybeSync {
async fn get(&self, key: &StoreKey) -> Result<MaybeBytes, StorageError> {
self.get_partial(key, ByteRange::FromStart(0, None)).await
}
async fn get_partial_many<'a>(
&'a self,
key: &StoreKey,
byte_ranges: ByteRangeIterator<'a>,
) -> Result<AsyncMaybeBytesIterator<'a>, StorageError>;
async fn get_partial<'a>(
&'a self,
key: &StoreKey,
byte_range: ByteRange,
) -> Result<MaybeBytes, StorageError> {
let mut result = self
.get_partial_many(key, Box::new([byte_range].into_iter()))
.await?;
if let Some(result) = &mut result {
let bytes = result.next().await.expect("one byte range")?;
debug_assert!(result.next().await.is_none());
Ok(Some(bytes))
} else {
Ok(None)
}
}
async fn size_key(&self, key: &StoreKey) -> Result<Option<u64>, StorageError>;
fn supports_get_partial(&self) -> bool;
}
#[cfg_attr(
all(feature = "async", not(target_arch = "wasm32")),
async_trait::async_trait
)]
#[cfg_attr(all(feature = "async", target_arch = "wasm32"), async_trait::async_trait(?Send))]
#[auto_impl(Arc)]
pub trait AsyncListableStorageTraits: MaybeSend + MaybeSync {
async fn list(&self) -> Result<StoreKeys, StorageError>;
async fn list_prefix(&self, prefix: &StorePrefix) -> Result<StoreKeys, StorageError>;
async fn list_dir(&self, prefix: &StorePrefix) -> Result<StoreKeysPrefixes, StorageError>;
async fn size_prefix(&self, prefix: &StorePrefix) -> Result<u64, StorageError>;
async fn size(&self) -> Result<u64, StorageError> {
self.size_prefix(&StorePrefix::root()).await
}
}
pub async fn async_store_set_partial_many<T: AsyncReadableWritableStorageTraits>(
store: &T,
key: &StoreKey,
offset_values: OffsetBytesIterator<'_>,
) -> Result<(), StorageError> {
let bytes_out = store.get(key).await?.unwrap_or_default();
let mut bytes_out: BytesMut = bytes_out.into();
for (offset, value) in offset_values {
let offset = usize::try_from(offset).unwrap();
if bytes_out.len() < offset + value.len() {
bytes_out.resize(offset + value.len(), 0);
}
bytes_out[offset..offset + value.len()].copy_from_slice(&value);
}
store.set(key, bytes_out.into()).await
}
#[cfg_attr(
all(feature = "async", not(target_arch = "wasm32")),
async_trait::async_trait
)]
#[cfg_attr(all(feature = "async", target_arch = "wasm32"), async_trait::async_trait(?Send))]
#[auto_impl(Arc)]
pub trait AsyncWritableStorageTraits: MaybeSend + MaybeSync {
async fn set(&self, key: &StoreKey, value: Bytes) -> Result<(), StorageError>;
async fn set_partial(
&self,
key: &StoreKey,
offset: u64,
value: Bytes,
) -> Result<(), StorageError> {
self.set_partial_many(key, Box::new([(offset, value)].into_iter()))
.await
}
async fn set_partial_many<'a>(
&'a self,
key: &StoreKey,
offset_values: OffsetBytesIterator<'a>,
) -> Result<(), StorageError>;
async fn erase(&self, key: &StoreKey) -> Result<(), StorageError>;
async fn erase_many(&self, keys: &[StoreKey]) -> Result<(), StorageError> {
let futures_erase = keys.iter().map(|key| self.erase(key));
futures::future::join_all(futures_erase)
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?;
Ok(())
}
async fn erase_prefix(&self, prefix: &StorePrefix) -> Result<(), StorageError>;
fn supports_set_partial(&self) -> bool;
}
#[cfg_attr(
all(feature = "async", not(target_arch = "wasm32")),
async_trait::async_trait
)]
#[cfg_attr(all(feature = "async", target_arch = "wasm32"), async_trait::async_trait(?Send))]
pub trait AsyncReadableWritableStorageTraits:
AsyncReadableStorageTraits + AsyncWritableStorageTraits
{
fn readable(self: Arc<Self>) -> Arc<dyn AsyncReadableStorageTraits>;
fn writable(self: Arc<Self>) -> Arc<dyn AsyncWritableStorageTraits>;
}
impl<T> AsyncReadableWritableStorageTraits for T
where
T: AsyncReadableStorageTraits + AsyncWritableStorageTraits + 'static,
{
fn readable(self: Arc<Self>) -> Arc<dyn AsyncReadableStorageTraits> {
self.clone()
}
fn writable(self: Arc<Self>) -> Arc<dyn AsyncWritableStorageTraits> {
self.clone()
}
}
pub trait AsyncReadableListableStorageTraits:
AsyncReadableStorageTraits + AsyncListableStorageTraits
{
fn readable(self: Arc<Self>) -> Arc<dyn AsyncReadableStorageTraits>;
fn listable(self: Arc<Self>) -> Arc<dyn AsyncListableStorageTraits>;
}
impl<T> AsyncReadableListableStorageTraits for T
where
T: AsyncReadableStorageTraits + AsyncListableStorageTraits + 'static,
{
fn readable(self: Arc<Self>) -> Arc<dyn AsyncReadableStorageTraits> {
self.clone()
}
fn listable(self: Arc<Self>) -> Arc<dyn AsyncListableStorageTraits> {
self.clone()
}
}
pub trait AsyncReadableWritableListableStorageTraits:
AsyncReadableWritableStorageTraits + AsyncListableStorageTraits
{
fn readable_writable(self: Arc<Self>) -> Arc<dyn AsyncReadableWritableStorageTraits>;
fn readable_listable(self: Arc<Self>) -> Arc<dyn AsyncReadableListableStorageTraits>;
fn listable(self: Arc<Self>) -> Arc<dyn AsyncListableStorageTraits>;
}
impl<T> AsyncReadableWritableListableStorageTraits for T
where
T: AsyncReadableWritableStorageTraits + AsyncListableStorageTraits + 'static,
{
fn readable_writable(self: Arc<Self>) -> Arc<dyn AsyncReadableWritableStorageTraits> {
self.clone()
}
fn readable_listable(self: Arc<Self>) -> Arc<dyn AsyncReadableListableStorageTraits> {
self.clone()
}
fn listable(self: Arc<Self>) -> Arc<dyn AsyncListableStorageTraits> {
self.clone()
}
}
pub async fn async_discover_children<
TStorage: ?Sized + AsyncReadableStorageTraits + AsyncListableStorageTraits,
>(
storage: &Arc<TStorage>,
prefix: &StorePrefix,
) -> Result<StorePrefixes, StorageError> {
let children: Result<Vec<_>, _> = storage
.list_dir(prefix)
.await?
.prefixes()
.iter()
.filter(|v| !v.as_str().starts_with("__"))
.map(|v| StorePrefix::new(v.as_str()))
.collect();
Ok(children?)
}