From d405234d743009881ff89558f3e6abc63246e6e5 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Fri, 28 Jun 2024 16:53:52 -0500 Subject: [PATCH] expose ndb_note_json Fixes: https://github.com/damus-io/nostrdb-rs/issues/12 Changelog-Added: Add Note::json for json conversion --- nostrdb | 2 +- src/bindings.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++-- src/config.rs | 2 ++ src/error.rs | 2 ++ src/note.rs | 33 ++++++++++++++++++++++++++++----- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/nostrdb b/nostrdb index 3d485bf..5b45c3b 160000 --- a/nostrdb +++ b/nostrdb @@ -1 +1 @@ -Subproject commit 3d485bf88f6e86102802d5fa5aa5b131e7184ff7 +Subproject commit 5b45c3b6c13cf3ecf446e4a226ece349193c7ac3 diff --git a/src/bindings.rs b/src/bindings.rs index 675544a..d215d73 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -2663,6 +2663,8 @@ pub type ndb_id_fn = ::std::option::Option< arg2: *const ::std::os::raw::c_char, ) -> ndb_idres, >; +pub type ndb_sub_fn = + ::std::option::Option; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ndb_id_cb { @@ -3538,6 +3540,8 @@ pub struct ndb_config { pub mapsize: usize, pub filter_context: *mut ::std::os::raw::c_void, pub ingest_filter: ndb_ingest_filter_fn, + pub sub_cb_ctx: *mut ::std::os::raw::c_void, + pub sub_cb: ndb_sub_fn, } #[test] fn bindgen_test_layout_ndb_config() { @@ -3545,7 +3549,7 @@ fn bindgen_test_layout_ndb_config() { let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), - 32usize, + 48usize, concat!("Size of: ", stringify!(ndb_config)) ); assert_eq!( @@ -3603,6 +3607,26 @@ fn bindgen_test_layout_ndb_config() { stringify!(ingest_filter) ) ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sub_cb_ctx) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(ndb_config), + "::", + stringify!(sub_cb_ctx) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sub_cb) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(ndb_config), + "::", + stringify!(sub_cb) + ) + ); } #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -4794,6 +4818,13 @@ extern "C" { arg1: *mut ::std::os::raw::c_void, ); } +extern "C" { + pub fn ndb_config_set_subscription_callback( + config: *mut ndb_config, + fn_: ndb_sub_fn, + ctx: *mut ::std::os::raw::c_void, + ); +} extern "C" { pub fn ndb_calculate_id( note: *mut ndb_note, @@ -5097,7 +5128,10 @@ extern "C" { ) -> ::std::os::raw::c_int; } extern "C" { - pub fn ndb_unsubscribe(subid: ::std::os::raw::c_int) -> ::std::os::raw::c_int; + pub fn ndb_unsubscribe(arg1: *mut ndb, subid: u64) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn ndb_num_subscriptions(arg1: *mut ndb) -> ::std::os::raw::c_int; } extern "C" { pub fn ndb_text_search( @@ -5171,6 +5205,14 @@ extern "C" { extern "C" { pub fn ndb_str_len(str_: *mut ndb_str) -> ::std::os::raw::c_int; } +extern "C" { + #[doc = " write the note as json to a buffer"] + pub fn ndb_note_json( + arg1: *mut ndb_note, + buf: *mut ::std::os::raw::c_char, + buflen: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} extern "C" { pub fn ndb_tags_iterate_start(note: *mut ndb_note, iter: *mut ndb_iterator); } diff --git a/src/config.rs b/src/config.rs index 10c6904..6b5161c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,8 @@ impl Config { pub fn new() -> Self { let mut config = bindings::ndb_config { filter_context: std::ptr::null_mut(), + sub_cb: None, + sub_cb_ctx: std::ptr::null_mut(), ingest_filter: None, flags: 0, ingester_threads: 0, diff --git a/src/error.rs b/src/error.rs index 8e595e9..2c307a1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,7 @@ pub enum Error { NoteProcessFailed, TransactionFailed, SubscriptionError, + BufferOverflow, } impl fmt::Display for Error { @@ -21,6 +22,7 @@ impl fmt::Display for Error { Error::NoteProcessFailed => "Note process failed", Error::TransactionFailed => "Transaction failed", Error::SubscriptionError => "Subscription failed", + Error::BufferOverflow => "Buffer overflow", }; write!(f, "{}", s) } diff --git a/src/note.rs b/src/note.rs index 0aab387..bc1f9a9 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,6 +1,6 @@ -use crate::bindings; use crate::tags::Tags; use crate::transaction::Transaction; +use crate::{bindings, Error}; use ::std::os::raw::c_uchar; use std::hash::Hash; @@ -127,11 +127,30 @@ impl<'a> Note<'a> { } } - /* - pub fn json() -> String { - unsafe { bindings::ndb_note_json() } + pub fn json_with_bufsize(&self, bufsize: usize) -> Result { + let mut buf = Vec::with_capacity(bufsize); + unsafe { + let size = bindings::ndb_note_json( + self.as_ptr(), + buf.as_mut_ptr() as *mut ::std::os::raw::c_char, + bufsize as ::std::os::raw::c_int, + ) as usize; + + // Step 4: Check the return value for success + if size == 0 { + return Err(Error::BufferOverflow); // Handle the error appropriately + } + + buf.set_len(size); + + Ok(std::str::from_utf8_unchecked(&buf[..size - 1]).to_string()) + } + } + + pub fn json(&self) -> Result { + // 1mb buffer + self.json_with_bufsize(1024usize * 1024usize) } - */ fn content_size(&self) -> usize { unsafe { bindings::ndb_note_content_length(self.as_ptr()) as usize } @@ -506,5 +525,9 @@ mod tests { assert_eq!(tag.get_unchecked(1).variant().str().unwrap(), "something"); break; } + + let json = note.json().expect("note json"); + // the signature changes so 267 is everything up until the signature + assert_eq!(&json[..267], "{\"id\":\"fb165be22c7b2518b749aabb7140c73f0887fe84475c82785700663be85ba859\",\"pubkey\":\"6c540ed060bfc2b0c5b6f09cd3ebedf980ef7bc836d69582361d20f2ad124f23\",\"created_at\":42,\"kind\":1,\"tags\":[[\"comment\",\"this is a comment\"],[\"blah\",\"something\"]],\"content\":\"this is the content\""); } }