#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
#![warn(clippy::large_futures)]
#![cfg_attr(bench, feature(test))]
#[cfg(bench)]
extern crate test;
use std::any::Any;
use std::collections::BTreeSet;
use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use nostr::event::{Event, EventId};
use nostr::filter::Filter;
use nostr::types::Timestamp;
pub mod error;
pub mod prelude;
use self::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Features {
pub persistent: bool,
pub event_expiration: bool,
pub full_text_search: bool,
pub request_to_vanish: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DatabaseEventStatus {
Saved,
Deleted,
NotExistent,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RejectedReason {
Ephemeral,
Duplicate,
Deleted,
Expired,
Replaced,
InvalidDelete,
Vanished,
Other,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SaveEventStatus {
Success,
Rejected(RejectedReason),
}
impl SaveEventStatus {
#[inline]
pub fn is_success(&self) -> bool {
matches!(self, Self::Success)
}
}
#[doc(hidden)]
pub trait IntoNostrDatabase {
fn into_nostr_database(self) -> Arc<dyn NostrDatabase>;
}
impl IntoNostrDatabase for Arc<dyn NostrDatabase> {
fn into_nostr_database(self) -> Arc<dyn NostrDatabase> {
self
}
}
impl<T> IntoNostrDatabase for T
where
T: NostrDatabase + Sized + 'static,
{
fn into_nostr_database(self) -> Arc<dyn NostrDatabase> {
Arc::new(self)
}
}
impl<T> IntoNostrDatabase for Arc<T>
where
T: NostrDatabase + 'static,
{
fn into_nostr_database(self) -> Arc<dyn NostrDatabase> {
self
}
}
pub trait NostrDatabase: Any + Debug + Send + Sync {
fn backend(&self) -> &'static str;
fn features(&self) -> Features;
fn save_event<'a>(
&'a self,
event: &'a Event,
) -> Pin<Box<dyn Future<Output = Result<SaveEventStatus, Error>> + Send + 'a>>;
fn check_id<'a>(
&'a self,
event_id: &'a EventId,
) -> Pin<Box<dyn Future<Output = Result<DatabaseEventStatus, Error>> + Send + 'a>>;
fn event_by_id<'a>(
&'a self,
event_id: &'a EventId,
) -> Pin<Box<dyn Future<Output = Result<Option<Event>, Error>> + Send + 'a>>;
fn count(
&self,
filter: Filter,
) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + '_>>;
fn query(
&self,
filter: Filter,
) -> Pin<Box<dyn Future<Output = Result<BTreeSet<Event>, Error>> + Send + '_>>;
#[allow(clippy::type_complexity)]
fn negentropy_items(
&self,
filter: Filter,
) -> Pin<Box<dyn Future<Output = Result<Vec<(EventId, Timestamp)>, Error>> + Send + '_>> {
Box::pin(async move {
let events: BTreeSet<Event> = self.query(filter).await?;
Ok(events.into_iter().map(|e| (e.id, e.created_at)).collect())
})
}
fn delete(
&self,
filter: Filter,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>;
fn wipe(&self) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + '_>>;
}