use std::sync::Arc;
use auto_impl::auto_impl;
use super::byte_range::{ByteRange, ByteRangeIterator};
use super::{
Bytes, MaybeBytes, MaybeBytesIterator, MaybeSend, MaybeSync, OffsetBytesIterator, StorageError,
StoreKey, StoreKeys, StoreKeysPrefixes, StorePrefix, StorePrefixes,
};
#[auto_impl(Arc)]
pub trait ReadableStorageTraits: MaybeSend + MaybeSync {
fn get(&self, key: &StoreKey) -> Result<MaybeBytes, StorageError> {
self.get_partial(key, ByteRange::FromStart(0, None))
}
fn get_partial_many<'a>(
&'a self,
key: &StoreKey,
byte_ranges: ByteRangeIterator<'a>,
) -> Result<MaybeBytesIterator<'a>, StorageError>;
fn get_partial(
&self,
key: &StoreKey,
byte_range: ByteRange,
) -> Result<MaybeBytes, StorageError> {
let mut bytes = self.get_partial_many(key, Box::new([byte_range].into_iter()))?;
if let Some(bytes) = &mut bytes {
let output = bytes.next().expect("one byte range")?;
debug_assert!(bytes.next().is_none());
Ok(Some(output))
} else {
Ok(None)
}
}
fn size_key(&self, key: &StoreKey) -> Result<Option<u64>, StorageError>;
fn supports_get_partial(&self) -> bool;
}
#[auto_impl(Arc)]
pub trait ListableStorageTraits: MaybeSend + MaybeSync {
fn list(&self) -> Result<StoreKeys, StorageError>;
fn list_prefix(&self, prefix: &StorePrefix) -> Result<StoreKeys, StorageError>;
fn list_dir(&self, prefix: &StorePrefix) -> Result<StoreKeysPrefixes, StorageError>;
fn size_prefix(&self, prefix: &StorePrefix) -> Result<u64, StorageError>;
fn size(&self) -> Result<u64, StorageError> {
self.size_prefix(&StorePrefix::root())
}
}
pub fn store_set_partial_many<T: ReadableWritableStorageTraits>(
store: &T,
key: &StoreKey,
offset_values: OffsetBytesIterator,
) -> Result<(), StorageError> {
let bytes_out = store.get(key)?.unwrap_or_default();
let mut bytes_out: bytes::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.freeze())
}
#[auto_impl(Arc)]
pub trait AtomicRenameStorageTraits: MaybeSend + MaybeSync {
fn rename(&self, source: &StoreKey, destination: &StoreKey) -> Result<(), StorageError>;
}
#[auto_impl(Arc)]
pub trait WritableStorageTraits: MaybeSend + MaybeSync {
fn set(&self, key: &StoreKey, value: Bytes) -> Result<(), StorageError>;
fn set_partial(&self, key: &StoreKey, offset: u64, value: Bytes) -> Result<(), StorageError> {
self.set_partial_many(key, Box::new([(offset, value)].into_iter()))
}
fn set_partial_many(
&self,
key: &StoreKey,
offset_values: OffsetBytesIterator,
) -> Result<(), StorageError>;
fn erase(&self, key: &StoreKey) -> Result<(), StorageError>;
fn erase_many(&self, keys: &[StoreKey]) -> Result<(), StorageError> {
keys.iter().try_for_each(|key| self.erase(key))?;
Ok(())
}
fn erase_prefix(&self, prefix: &StorePrefix) -> Result<(), StorageError>;
fn supports_set_partial(&self) -> bool;
}
pub trait ReadableWritableStorageTraits: ReadableStorageTraits + WritableStorageTraits {
fn readable(self: Arc<Self>) -> Arc<dyn ReadableStorageTraits>;
fn writable(self: Arc<Self>) -> Arc<dyn WritableStorageTraits>;
}
impl<T> ReadableWritableStorageTraits for T
where
T: ReadableStorageTraits + WritableStorageTraits + 'static,
{
fn readable(self: Arc<Self>) -> Arc<dyn ReadableStorageTraits> {
self.clone()
}
fn writable(self: Arc<Self>) -> Arc<dyn WritableStorageTraits> {
self.clone()
}
}
pub trait ReadableListableStorageTraits: ReadableStorageTraits + ListableStorageTraits {
fn readable(self: Arc<Self>) -> Arc<dyn ReadableStorageTraits>;
fn listable(self: Arc<Self>) -> Arc<dyn ListableStorageTraits>;
}
impl<T> ReadableListableStorageTraits for T
where
T: ReadableStorageTraits + ListableStorageTraits + 'static,
{
fn readable(self: Arc<Self>) -> Arc<dyn ReadableStorageTraits> {
self.clone()
}
fn listable(self: Arc<Self>) -> Arc<dyn ListableStorageTraits> {
self.clone()
}
}
pub trait ReadableWritableListableStorageTraits:
ReadableWritableStorageTraits + ListableStorageTraits
{
fn readable_writable(self: Arc<Self>) -> Arc<dyn ReadableWritableStorageTraits>;
fn readable_listable(self: Arc<Self>) -> Arc<dyn ReadableListableStorageTraits>;
fn listable(self: Arc<Self>) -> Arc<dyn ListableStorageTraits>;
}
impl<T> ReadableWritableListableStorageTraits for T
where
T: ReadableWritableStorageTraits + ListableStorageTraits + 'static,
{
fn readable_writable(self: Arc<Self>) -> Arc<dyn ReadableWritableStorageTraits> {
self.clone()
}
fn readable_listable(self: Arc<Self>) -> Arc<dyn ReadableListableStorageTraits> {
self.clone()
}
fn listable(self: Arc<Self>) -> Arc<dyn ListableStorageTraits> {
self.clone()
}
}
pub fn discover_children<TStorage: ?Sized + ReadableStorageTraits + ListableStorageTraits>(
storage: &Arc<TStorage>,
prefix: &StorePrefix,
) -> Result<StorePrefixes, StorageError> {
let children: Result<Vec<_>, _> = storage
.list_dir(prefix)?
.prefixes()
.iter()
.filter(|v| !v.as_str().starts_with("__"))
.map(|v| StorePrefix::new(v.as_str()))
.collect();
Ok(children?)
}