#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
#![warn(clippy::large_futures)]
#![cfg_attr(bench, feature(test))]
#![allow(clippy::mutable_key_type)]
#[cfg(bench)]
extern crate test;
use std::any::Any;
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::Arc;
pub use nostr;
use nostr::prelude::*;
mod collections;
pub mod error;
pub mod ext;
#[cfg(feature = "flatbuf")]
pub mod flatbuffers;
pub mod prelude;
pub mod profile;
pub use self::collections::events::Events;
use self::error::Error;
#[cfg(feature = "flatbuf")]
pub use self::flatbuffers::{FlatBufferBuilder, FlatBufferDecode, FlatBufferEncode};
pub use self::profile::Profile;
pub type RelaysMap = HashMap<RelayUrl, Option<RelayMetadata>>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Backend {
Memory,
LMDB,
SQLite,
Postgres,
MySql,
RocksDB,
IndexedDB,
MongoDB,
Redis,
Cassandra,
Custom(String),
}
impl Backend {
#[inline]
pub fn custom<T>(name: T) -> Self
where
T: Into<String>,
{
Self::Custom(name.into())
}
}
#[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) -> Backend;
fn features(&self) -> Features;
fn save_event<'a>(
&'a self,
event: &'a Event,
) -> BoxedFuture<'a, Result<SaveEventStatus, Error>>;
fn check_id<'a>(
&'a self,
event_id: &'a EventId,
) -> BoxedFuture<'a, Result<DatabaseEventStatus, Error>>;
fn event_by_id<'a>(
&'a self,
event_id: &'a EventId,
) -> BoxedFuture<'a, Result<Option<Event>, Error>>;
fn count(&self, filter: Filter) -> BoxedFuture<'_, Result<usize, Error>>;
fn query(&self, filter: Filter) -> BoxedFuture<'_, Result<Events, Error>>;
fn negentropy_items(
&self,
filter: Filter,
) -> BoxedFuture<'_, Result<Vec<(EventId, Timestamp)>, Error>> {
Box::pin(async move {
let events: Events = self.query(filter).await?;
Ok(events.into_iter().map(|e| (e.id, e.created_at)).collect())
})
}
fn delete(&self, filter: Filter) -> BoxedFuture<'_, Result<(), Error>>;
fn wipe(&self) -> BoxedFuture<'_, Result<(), Error>>;
}