nostrdb-rs

nostrdb in rust!
git clone git://jb55.com/nostrdb-rs
Log | Files | Refs | Submodules | README | LICENSE

commit 36c3b8a3df7df8ff9c6fdcd341c6a6221bc00241
parent df37b006bfbcc9bfa10fda81bdae25a3a8a9c344
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 17 Dec 2023 14:20:04 -0800

ndb: add get_profile_by_pubkey

This allows us to fetch flatbuffer profile records from the database

Diffstat:
Msrc/lib.rs | 16++++++++--------
Msrc/ndb.rs | 37++++++++++++++++++++++++++++++++-----
Asrc/profile.rs | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -8,19 +8,19 @@ mod bindings; #[allow(non_snake_case)] mod ndb_profile; -pub type Profile<'a> = ndb_profile::NdbProfile<'a>; - -pub mod config; -pub mod error; -pub mod ndb; -pub mod note; -pub mod result; -pub mod transaction; +mod config; +mod error; +mod ndb; +mod note; +mod profile; +mod result; +mod transaction; pub use config::Config; pub use error::Error; pub use ndb::Ndb; pub use note::Note; +pub use profile::ProfileRecord; pub use result::Result; pub use transaction::Transaction; diff --git a/src/ndb.rs b/src/ndb.rs @@ -3,11 +3,7 @@ use std::ffi::CString; use std::ptr; use crate::bindings; -use crate::config::Config; -use crate::error::Error; -use crate::note::Note; -use crate::result::Result; -use crate::transaction::Transaction; +use crate::{Config, Error, Note, ProfileRecord, Result, Transaction}; use std::fs; use std::path::Path; use std::sync::Arc; @@ -82,6 +78,37 @@ impl Ndb { Ok(()) } + pub fn get_profile_by_pubkey<'a>( + &self, + transaction: &'a mut Transaction, + id: &[u8; 32], + ) -> Result<ProfileRecord<'a>> { + let mut len: usize = 0; + let mut primkey: u64 = 0; + + let profile_record_ptr = unsafe { + bindings::ndb_get_profile_by_pubkey( + transaction.as_mut_ptr(), + id.as_ptr(), + &mut len, + &mut primkey, + ) + }; + + if profile_record_ptr.is_null() { + // Handle null pointer (e.g., note not found or error occurred) + return Err(Error::NotFound); + } + + // Convert the raw pointer to a Note instance + Ok(ProfileRecord::new( + profile_record_ptr, + len, + primkey, + transaction, + )) + } + /// Get a note from the database. Takes a [Transaction] and a 32-byte [Note] Id pub fn get_note_by_id<'a>( &self, diff --git a/src/profile.rs b/src/profile.rs @@ -0,0 +1,67 @@ +use crate::ndb_profile::{root_as_ndb_profile_record_unchecked, NdbProfileRecord}; +use crate::Transaction; + +pub struct ProfileRecord<'a> { + record: NdbProfileRecord<'a>, + primary_key: u64, + transaction: &'a Transaction, +} + +impl<'a> ProfileRecord<'a> { + pub(crate) fn new( + ptr: *mut ::std::os::raw::c_void, + len: usize, + primary_key: u64, + transaction: &'a Transaction, + ) -> ProfileRecord<'a> { + let record = unsafe { + let bytes = std::slice::from_raw_parts(ptr as *const u8, len); + root_as_ndb_profile_record_unchecked(bytes) + }; + ProfileRecord { + record, + transaction, + primary_key, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn profile_record_words() { + use crate::config::Config; + use crate::error::Error; + use crate::ndb::Ndb; + use crate::test_util; + + let db = "target/testdbs/profile_record_works"; + + { + let cfg = Config::new(); + let ndb = Ndb::new(&db, &cfg).unwrap(); + let _ = ndb.process_event(r#"["EVENT","nostril-query",{"content":"{\"nip05\":\"_@jb55.com\",\"website\":\"https://damus.io\",\"name\":\"jb55\",\"about\":\"I made damus, npubs and zaps. banned by apple & the ccp. my notes are not for sale.\",\"lud16\":\"jb55@sendsats.lol\",\"banner\":\"https://nostr.build/i/3d6f22d45d95ecc2c19b1acdec57aa15f2dba9c423b536e26fc62707c125f557.jpg\",\"display_name\":\"Will\",\"picture\":\"https://cdn.jb55.com/img/red-me.jpg\"}","created_at":1700855305,"id":"cad04d11f7fa9c36d57400baca198582dfeb94fa138366c4469e58da9ed60051","kind":0,"pubkey":"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245","sig":"7a15e379ff27318460172b4a1d55a13e064c5007d05d5a188e7f60e244a9ed08996cb7676058b88c7a91ae9488f8edc719bc966cb5bf1eb99be44cdb745f915f","tags":[]}]"#); + } + + // Initialize ndb + { + let cfg = Config::new(); + let ndb = Ndb::new(&db, &cfg).expect("db open"); + let mut txn = Transaction::new(&ndb).expect("new txn"); + + let pk = + hex::decode("32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245") + .expect("hex decode"); + let pr = ndb + .get_profile_by_pubkey(&mut txn, &pk.try_into().expect("bytes")) + .expect("profile record"); + + let profile = pr.record.profile().unwrap(); + assert_eq!(Some("jb55"), profile.name()); + } + + test_util::cleanup_db(db); + } +}