use alloc::string::String;
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::ops::RangeBounds;
use crate::TableDefinition;
use crate::types::{Key, Value};
pub struct OwnedKv<T: Value + 'static> {
data: Vec<u8>,
_type: PhantomData<T>,
}
impl<T: Value + 'static> OwnedKv<T> {
pub fn new(data: Vec<u8>) -> Self {
Self {
data,
_type: PhantomData,
}
}
pub fn value(&self) -> T::SelfType<'_> {
T::from_bytes(&self.data)
}
pub fn raw_bytes(&self) -> &[u8] {
&self.data
}
pub fn into_bytes(self) -> Vec<u8> {
self.data
}
}
impl<T: Value + 'static> core::fmt::Debug for OwnedKv<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("OwnedKv")
.field("len", &self.data.len())
.finish()
}
}
pub trait WriteTable<K: Key + 'static, V: Value + 'static> {
type RangeIter<'a>: Iterator<Item = crate::Result<(OwnedKv<K>, OwnedKv<V>)>>
where
Self: 'a;
fn st_get(&self, key: &K::SelfType<'_>) -> crate::Result<Option<OwnedKv<V>>>;
fn st_insert(
&mut self,
key: &K::SelfType<'_>,
value: &V::SelfType<'_>,
) -> crate::Result<Option<OwnedKv<V>>>;
fn st_remove(&mut self, key: &K::SelfType<'_>) -> crate::Result<Option<OwnedKv<V>>>;
fn st_range<'a>(
&'a self,
start: Option<&K::SelfType<'_>>,
end: Option<&K::SelfType<'_>>,
start_inclusive: bool,
end_inclusive: bool,
) -> crate::Result<Self::RangeIter<'a>>;
fn st_drain_all(&mut self) -> crate::Result<u64>;
}
pub trait ReadTable<K: Key + 'static, V: Value + 'static> {
type RangeIter<'a>: Iterator<Item = crate::Result<(OwnedKv<K>, OwnedKv<V>)>>
where
Self: 'a;
fn st_get(&self, key: &K::SelfType<'_>) -> crate::Result<Option<OwnedKv<V>>>;
fn st_range<'a>(
&'a self,
start: Option<&K::SelfType<'_>>,
end: Option<&K::SelfType<'_>>,
start_inclusive: bool,
end_inclusive: bool,
) -> crate::Result<Self::RangeIter<'a>>;
}
pub trait StorageWrite {
type Table<'txn, K: Key + 'static, V: Value + 'static>: WriteTable<K, V>
where
Self: 'txn;
fn open_storage_table<K: Key + 'static, V: Value + 'static>(
&self,
definition: TableDefinition<K, V>,
) -> crate::Result<Self::Table<'_, K, V>>;
}
pub trait StorageRead {
type Table<'txn, K: Key + 'static, V: Value + 'static>: ReadTable<K, V>
where
Self: 'txn;
fn open_storage_table<K: Key + 'static, V: Value + 'static>(
&self,
definition: TableDefinition<K, V>,
) -> crate::Result<Self::Table<'_, K, V>>;
}
pub fn range_to_bounds<K: Key + 'static>(
range: &impl RangeBounds<Vec<u8>>,
) -> (Option<Vec<u8>>, Option<Vec<u8>>, bool, bool) {
use core::ops::Bound;
let start = match range.start_bound() {
Bound::Included(k) => (Some(k.clone()), true),
Bound::Excluded(k) => (Some(k.clone()), false),
Bound::Unbounded => (None, true),
};
let end = match range.end_bound() {
Bound::Included(k) => (Some(k.clone()), true),
Bound::Excluded(k) => (Some(k.clone()), false),
Bound::Unbounded => (None, true),
};
(start.0, end.0, start.1, end.1)
}
pub fn key_to_bytes<K: Key + 'static>(key: &K::SelfType<'_>) -> Vec<u8> {
K::as_bytes(key).as_ref().to_vec()
}
pub struct TypedRange {
pub start: Option<Vec<u8>>,
pub end: Option<Vec<u8>>,
pub start_inclusive: bool,
pub end_inclusive: bool,
}
impl TypedRange {
pub fn from_byte_bounds(range: &impl RangeBounds<Vec<u8>>) -> Self {
let (start, end, si, ei) = range_to_bounds::<()>(range);
Self {
start,
end,
start_inclusive: si,
end_inclusive: ei,
}
}
pub fn from_key_pair<K: Key + 'static>(
start: Option<&K::SelfType<'_>>,
end: Option<&K::SelfType<'_>>,
start_inclusive: bool,
end_inclusive: bool,
) -> Self {
Self {
start: start.map(|k| key_to_bytes::<K>(k)),
end: end.map(|k| key_to_bytes::<K>(k)),
start_inclusive,
end_inclusive,
}
}
}
#[derive(Debug, Clone)]
pub struct DynTableName(pub String);
impl DynTableName {
pub fn new(name: impl Into<String>) -> Self {
Self(name.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}