use crate::{MaybeSend, MaybeSync, error::NetabaseError};
use strum::IntoEnumIterator;
pub mod subscription_tree;
pub use strum::{EnumIter, IntoStaticStr, VariantArray};
pub use subscription_tree::ModelHash;
pub trait Subscriptions: 'static + MaybeSend + MaybeSync {
type Subscriptions: IntoEnumIterator
+ Clone
+ Copy
+ std::fmt::Debug
+ std::fmt::Display
+ PartialEq
+ Eq
+ std::hash::Hash
+ MaybeSend
+ MaybeSync
+ 'static;
fn subscriptions() -> <Self::Subscriptions as IntoEnumIterator>::Iterator;
fn all_subscriptions() -> Vec<Self::Subscriptions> {
Self::subscriptions().collect()
}
fn topic_name(topic: Self::Subscriptions) -> String {
topic.to_string()
}
}
pub trait SubscriptionTree<S: Subscriptions>: 'static + MaybeSend + MaybeSync {
type Topic: Clone + Copy + std::fmt::Debug + PartialEq + Eq + std::hash::Hash;
fn topic(&self) -> Self::Topic;
fn put_item(&mut self, key: Vec<u8>, hash: ModelHash) -> Result<(), NetabaseError>;
fn remove_item(&mut self, key: &[u8]) -> Result<Option<ModelHash>, NetabaseError>;
fn get_all_hashes(&self) -> Result<Vec<ModelHash>, NetabaseError>;
fn merkle_root(&mut self) -> Result<Option<[u8; 32]>, NetabaseError>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn clear(&mut self) -> Result<(), NetabaseError>;
fn contains_key(&self, key: &[u8]) -> bool;
fn get_hash(&self, key: &[u8]) -> Option<&ModelHash>;
fn get_all_keys(&self) -> Vec<Vec<u8>>;
fn get_all_items(&self) -> Vec<(Vec<u8>, ModelHash)>;
fn rebuild_merkle_tree(&mut self) -> Result<(), NetabaseError>;
}
pub trait SubscriptionTreeIter: 'static + MaybeSend + MaybeSync {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
fn count(mut self) -> usize
where
Self: Sized,
{
let mut count = 0;
while self.next().is_some() {
count += 1;
}
count
}
fn collect_vec(mut self) -> Vec<Self::Item>
where
Self: Sized,
{
let mut items = Vec::new();
while let Some(item) = self.next() {
items.push(item);
}
items
}
}
pub trait OpenSubscriptionTree<S: Subscriptions>: 'static + MaybeSend + MaybeSync {
type TopicType: Clone + Copy + std::fmt::Debug + PartialEq + Eq + std::hash::Hash;
fn open_subscription_tree(&self, topic: Self::TopicType) -> Result<(), NetabaseError>;
}
pub trait SubscriptionManager<S: Subscriptions>: 'static + MaybeSend + MaybeSync {
type TopicType: Clone + Copy + std::fmt::Debug + PartialEq + Eq + std::hash::Hash;
fn subscribe_item<T>(
&mut self,
topic: Self::TopicType,
key: Vec<u8>,
data: &T,
) -> Result<(), NetabaseError>
where
T: AsRef<[u8]>;
fn unsubscribe_item(
&mut self,
topic: Self::TopicType,
key: &[u8],
) -> Result<Option<ModelHash>, NetabaseError>;
fn topic_merkle_root(
&mut self,
topic: Self::TopicType,
) -> Result<Option<[u8; 32]>, NetabaseError>;
fn stats(&self) -> SubscriptionStats;
}
#[derive(Debug, Clone)]
pub struct SubscriptionStats {
pub total_items: usize,
pub active_topics: usize,
}
impl SubscriptionStats {
pub fn new() -> Self {
Self {
total_items: 0,
active_topics: 0,
}
}
pub fn add_topic_count(&mut self, count: usize) {
self.total_items += count;
if count > 0 {
self.active_topics += 1;
}
}
}
impl Default for SubscriptionStats {
fn default() -> Self {
Self::new()
}
}
pub trait IntoModelHash {
fn into_model_hash(self) -> ModelHash;
}
impl<T: AsRef<[u8]>> IntoModelHash for T {
fn into_model_hash(self) -> ModelHash {
ModelHash::from_data(self)
}
}
pub trait SubscriptionStore<S: Subscriptions>: 'static + MaybeSend + MaybeSync {
type Manager: SubscriptionManager<S, TopicType = S::Subscriptions>;
fn subscription_manager(&self) -> Option<&Self::Manager>;
fn subscription_manager_mut(&mut self) -> Option<&mut Self::Manager>;
fn subscriptions_enabled(&self) -> bool {
self.subscription_manager().is_some()
}
fn auto_subscribe<T>(
&mut self,
topic: <S as Subscriptions>::Subscriptions,
key: Vec<u8>,
data: &T,
) -> Result<(), NetabaseError>
where
T: AsRef<[u8]>,
{
if let Some(manager) = self.subscription_manager_mut() {
manager.subscribe_item(topic, key, data)
} else {
Ok(()) }
}
fn auto_unsubscribe(
&mut self,
topic: <S as Subscriptions>::Subscriptions,
key: &[u8],
) -> Result<Option<ModelHash>, NetabaseError> {
if let Some(manager) = self.subscription_manager_mut() {
manager.unsubscribe_item(topic, key)
} else {
Ok(None) }
}
}
pub trait SubscriptionFilter<S: Subscriptions>: 'static + MaybeSend + MaybeSync {
fn should_include<T>(&self, topic: S::Subscriptions, key: &[u8], data: &T) -> bool
where
T: AsRef<[u8]>;
fn applicable_topics<T>(&self, key: &[u8], data: &T) -> Vec<S::Subscriptions>
where
T: AsRef<[u8]>;
}
pub struct DefaultSubscriptionFilter;
impl<S: Subscriptions> SubscriptionFilter<S> for DefaultSubscriptionFilter {
fn should_include<T>(&self, _topic: S::Subscriptions, _key: &[u8], _data: &T) -> bool
where
T: AsRef<[u8]>,
{
true
}
fn applicable_topics<T>(&self, _key: &[u8], _data: &T) -> Vec<S::Subscriptions>
where
T: AsRef<[u8]>,
{
S::all_subscriptions()
}
}