nostrdb-rs

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

commit d405234d743009881ff89558f3e6abc63246e6e5
parent 963576d681859942ebc87f50fdf3a1155f46fe9a
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 28 Jun 2024 16:53:52 -0500

expose ndb_note_json

Fixes: https://github.com/damus-io/nostrdb-rs/issues/12
Changelog-Added: Add Note::json for json conversion

Diffstat:
Msrc/bindings.rs | 46++++++++++++++++++++++++++++++++++++++++++++--
Msrc/config.rs | 2++
Msrc/error.rs | 2++
Msrc/note.rs | 33++++++++++++++++++++++++++++-----
4 files changed, 76 insertions(+), 7 deletions(-)

diff --git 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<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void, subid: u64)>; #[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::<ndb_config>(), - 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)] @@ -4795,6 +4819,13 @@ extern "C" { ); } 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, buf: *mut ::std::os::raw::c_uchar, @@ -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( @@ -5172,6 +5206,14 @@ 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); } extern "C" { diff --git 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 @@ -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 @@ -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<String, Error> { + 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<String, Error> { + // 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\""); } }