diff --git a/Cargo.lock b/Cargo.lock index 95d418cd0..5962c0890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2846,6 +2846,7 @@ dependencies = [ "flatbuffers", "lru", "nostr", + "rustversion", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index d92dbf869..d32cd28ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ nostr-relay-builder = { version = "0.42", path = "./crates/nostr-relay-builder", nostr-relay-pool = { version = "0.42", path = "./crates/nostr-relay-pool", default-features = false } nostr-sdk = { version = "0.42", path = "./crates/nostr-sdk", default-features = false } reqwest = { version = "0.12", default-features = false } +rustversion = "1.0" serde = { version = "1.0", default-features = false } serde_json = { version = "1.0", default-features = false } tempfile = "3.19" diff --git a/crates/nostr-database/Cargo.toml b/crates/nostr-database/Cargo.toml index fbaf0a348..a232ed256 100644 --- a/crates/nostr-database/Cargo.toml +++ b/crates/nostr-database/Cargo.toml @@ -19,6 +19,7 @@ flatbuf = ["dep:flatbuffers"] flatbuffers = { version = "23.5", optional = true } lru.workspace = true nostr = { workspace = true, features = ["std"] } +rustversion.workspace = true tokio = { workspace = true, features = ["sync"] } [dev-dependencies] diff --git a/crates/nostr-database/src/lib.rs b/crates/nostr-database/src/lib.rs index b72a2561a..2940b3806 100644 --- a/crates/nostr-database/src/lib.rs +++ b/crates/nostr-database/src/lib.rs @@ -193,6 +193,43 @@ pub trait NostrDatabase: Any + Debug + Send + Sync { fn wipe(&self) -> BoxedFuture>; } +#[rustversion::since(1.86)] +impl dyn NostrDatabase { + /// Upcast to [`Any`]. + #[inline] + fn as_any(&self) -> &dyn Any { + self + } + + /// Upcast to [`Any`]. + #[inline] + fn as_any_arc(self: Arc) -> Arc { + self + } + + /// Downcast [`NostrDatabase`] to a concrete type reference. + /// + /// **Requires rustc >= 1.86!** + #[inline] + pub fn downcast_ref(&self) -> Option<&T> + where + T: NostrDatabase, + { + self.as_any().downcast_ref() + } + + /// Downcast [`NostrDatabase`] to a concrete type. + /// + /// **Requires rustc >= 1.86!** + #[inline] + pub fn downcast(self: Arc) -> Option> + where + T: NostrDatabase, + { + self.as_any_arc().downcast().ok() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/nostr-sdk/examples/lmdb.rs b/crates/nostr-sdk/examples/lmdb.rs index 1fd937fa6..431856e24 100644 --- a/crates/nostr-sdk/examples/lmdb.rs +++ b/crates/nostr-sdk/examples/lmdb.rs @@ -58,5 +58,10 @@ async fn main() -> Result<()> { let events = client.database().query(filter).await?; println!("Events: {events:?}"); + // Database downcasting to access to specific APIs + if let Some(_lmdb) = client.database().downcast_ref::() { + // Access specific APIs here + } + Ok(()) } diff --git a/crates/nostr-sdk/examples/nostrdb.rs b/crates/nostr-sdk/examples/nostrdb.rs index e938740d1..2c6446020 100644 --- a/crates/nostr-sdk/examples/nostrdb.rs +++ b/crates/nostr-sdk/examples/nostrdb.rs @@ -35,5 +35,10 @@ async fn main() -> Result<()> { let events = client.database().query(filter).await?; println!("Events: {events:?}"); + // Database downcasting to access to specific APIs + if let Some(ndb) = client.database().downcast_ref::() { + println!("Subscription counts: {}", ndb.subscription_count()); + } + Ok(()) }