use std::hash::Hash;
use armour_core::{Fuid, GetRefs, Id64, IdBrand};
use crate::armour::collection::Collection;
use crate::key::Key;
use crate::{
Codec, CollectionMeta, DbResult, TypedMap, TypedTree, TypedWriteHook, ZeroMap, ZeroTree,
};
pub trait IndexTarget: SchemaCollection {
fn put_entry(&self, k: &Self::K, v: &Self::V) -> DbResult<()>;
fn delete_entry(&self, k: &Self::K) -> DbResult<()>;
}
pub trait BrandedKey: Key {
const BRAND: &'static str;
fn from_id(id: u64) -> Self;
fn id_value(&self) -> u64;
}
impl<H: IdBrand> BrandedKey for Fuid<H>
where
Fuid<H>: Key,
{
const BRAND: &'static str = H::BRAND;
fn from_id(id: u64) -> Self {
Fuid::from_be_bytes(id.to_be_bytes())
}
fn id_value(&self) -> u64 {
self.get()
}
}
impl<T: IdBrand> BrandedKey for Id64<T>
where
Id64<T>: Key,
{
const BRAND: &'static str = T::BRAND;
fn from_id(id: u64) -> Self {
Id64::from_be_bytes(id.to_be_bytes())
}
fn id_value(&self) -> u64 {
self.get()
}
}
pub trait SchemaCollection: Collection + Send + Sync + 'static {
type K: Key + GetRefs + 'static;
type V: CollectionMeta + GetRefs + 'static;
fn scan(&self, f: &mut dyn FnMut(&Self::K, &Self::V));
fn contains_key(&self, key: &Self::K) -> bool;
fn with_value(&self, key: &Self::K, f: &mut dyn FnMut(&Self::V)) -> bool;
}
impl<T, C, H> SchemaCollection for TypedTree<T::SelfId, T, C, H>
where
T: CollectionMeta + GetRefs + Clone + Send + Sync + 'static,
T::SelfId: Key + GetRefs + Ord + Send + Sync + 'static,
C: Codec<T> + Default + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
type K = T::SelfId;
type V = T;
fn scan(&self, f: &mut dyn FnMut(&Self::K, &Self::V)) {
for (k, v) in self.iter() {
f(&k, v);
}
}
fn contains_key(&self, key: &Self::K) -> bool {
self.get(key).is_some()
}
fn with_value(&self, key: &Self::K, f: &mut dyn FnMut(&Self::V)) -> bool {
match self.get(key) {
Some(v) => {
f(&*v);
true
}
None => false,
}
}
}
impl<T, C, H> IndexTarget for TypedTree<T::SelfId, T, C, H>
where
T: CollectionMeta + GetRefs + Clone + Send + Sync + 'static,
T::SelfId: Key + GetRefs + Ord + Send + Sync + 'static,
C: Codec<T> + Default + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
fn put_entry(&self, k: &Self::K, v: &Self::V) -> DbResult<()> {
self.put(k, v.clone()).map(drop)
}
fn delete_entry(&self, k: &Self::K) -> DbResult<()> {
self.delete(k).map(drop)
}
}
impl<T, C, H> SchemaCollection for TypedMap<T::SelfId, T, C, H>
where
T: CollectionMeta + GetRefs + Clone + Send + Sync + 'static,
T::SelfId: Key + GetRefs + Hash + Eq + Send + Sync + 'static,
C: Codec<T> + Default + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
type K = T::SelfId;
type V = T;
fn scan(&self, f: &mut dyn FnMut(&Self::K, &Self::V)) {
self.for_each(|k, v| f(k, v));
}
fn contains_key(&self, key: &Self::K) -> bool {
self.contains(key)
}
fn with_value(&self, key: &Self::K, f: &mut dyn FnMut(&Self::V)) -> bool {
match self.get(key) {
Some(v) => {
f(&*v);
true
}
None => false,
}
}
}
impl<T, C, H> IndexTarget for TypedMap<T::SelfId, T, C, H>
where
T: CollectionMeta + GetRefs + Clone + Send + Sync + 'static,
T::SelfId: Key + GetRefs + Hash + Eq + Send + Sync + 'static,
C: Codec<T> + Default + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
fn put_entry(&self, k: &Self::K, v: &Self::V) -> DbResult<()> {
self.put(k, v.clone()).map(drop)
}
fn delete_entry(&self, k: &Self::K) -> DbResult<()> {
self.delete(k).map(drop)
}
}
macro_rules! zero_tree_schema_impls {
($dur:ty) => {
impl<T, const V: usize, H> SchemaCollection for ZeroTree<T::SelfId, V, T, H, $dur>
where
T: CollectionMeta
+ GetRefs
+ Copy
+ zerocopy::IntoBytes
+ zerocopy::FromBytes
+ zerocopy::Immutable
+ Send
+ Sync
+ 'static,
T::SelfId: Key + GetRefs + Ord + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
type K = T::SelfId;
type V = T;
fn scan(&self, f: &mut dyn FnMut(&Self::K, &Self::V)) {
for (k, v) in self.iter() {
f(&k, &v);
}
}
fn contains_key(&self, key: &Self::K) -> bool {
self.contains(key)
}
fn with_value(&self, key: &Self::K, f: &mut dyn FnMut(&Self::V)) -> bool {
match self.get(key) {
Some(v) => {
f(&v);
true
}
None => false,
}
}
}
impl<T, const V: usize, H> IndexTarget for ZeroTree<T::SelfId, V, T, H, $dur>
where
T: CollectionMeta
+ GetRefs
+ Copy
+ zerocopy::IntoBytes
+ zerocopy::FromBytes
+ zerocopy::Immutable
+ Send
+ Sync
+ 'static,
T::SelfId: Key + GetRefs + Ord + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
fn put_entry(&self, k: &Self::K, v: &Self::V) -> DbResult<()> {
self.put(k, v).map(drop)
}
fn delete_entry(&self, k: &Self::K) -> DbResult<()> {
self.delete(k).map(drop)
}
}
};
}
zero_tree_schema_impls!(crate::durability::Bitcask);
zero_tree_schema_impls!(crate::durability::Fixed);
macro_rules! zero_map_schema_impls {
($dur:ty) => {
impl<T, const V: usize, H> SchemaCollection for ZeroMap<T::SelfId, V, T, H, $dur>
where
T: CollectionMeta
+ GetRefs
+ Copy
+ zerocopy::IntoBytes
+ zerocopy::FromBytes
+ zerocopy::Immutable
+ Send
+ Sync
+ 'static,
T::SelfId: Key + GetRefs + Hash + Eq + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
type K = T::SelfId;
type V = T;
fn scan(&self, f: &mut dyn FnMut(&Self::K, &Self::V)) {
self.for_each(|k, v| f(k, v));
}
fn contains_key(&self, key: &Self::K) -> bool {
self.contains(key)
}
fn with_value(&self, key: &Self::K, f: &mut dyn FnMut(&Self::V)) -> bool {
match self.get(key) {
Some(v) => {
f(&v);
true
}
None => false,
}
}
}
impl<T, const V: usize, H> IndexTarget for ZeroMap<T::SelfId, V, T, H, $dur>
where
T: CollectionMeta
+ GetRefs
+ Copy
+ zerocopy::IntoBytes
+ zerocopy::FromBytes
+ zerocopy::Immutable
+ Send
+ Sync
+ 'static,
T::SelfId: Key + GetRefs + Hash + Eq + Send + Sync + 'static,
H: TypedWriteHook<T::SelfId, T> + 'static,
{
fn put_entry(&self, k: &Self::K, v: &Self::V) -> DbResult<()> {
self.put(k, v).map(drop)
}
fn delete_entry(&self, k: &Self::K) -> DbResult<()> {
self.delete(k).map(drop)
}
}
};
}
zero_map_schema_impls!(crate::durability::Bitcask);
zero_map_schema_impls!(crate::durability::Fixed);