nostrdb-rs

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

tags.rs (6650B)


      1 use crate::{bindings, NdbStr, Note};
      2 
      3 #[derive(Debug, Copy, Clone)]
      4 pub struct Tag<'a> {
      5     ptr: *mut bindings::ndb_tag,
      6     note: &'a Note<'a>,
      7 }
      8 
      9 impl<'a> Tag<'a> {
     10     pub(crate) fn new(ptr: *mut bindings::ndb_tag, note: &'a Note<'a>) -> Self {
     11         Tag { ptr, note }
     12     }
     13 
     14     pub fn count(&self) -> u16 {
     15         unsafe { bindings::ndb_tag_count(self.as_ptr()) }
     16     }
     17 
     18     pub fn get(&self, ind: u16) -> Option<NdbStr<'a>> {
     19         if ind >= self.count() {
     20             return None;
     21         }
     22         let nstr = unsafe {
     23             bindings::ndb_tag_str(
     24                 self.note().as_ptr(),
     25                 self.as_ptr(),
     26                 ind as ::std::os::raw::c_int,
     27             )
     28         };
     29         Some(NdbStr::new(nstr, self.note))
     30     }
     31 
     32     pub fn note(&self) -> &'a Note<'a> {
     33         self.note
     34     }
     35 
     36     pub fn as_ptr(&self) -> *mut bindings::ndb_tag {
     37         self.ptr
     38     }
     39 }
     40 
     41 #[derive(Debug, Copy, Clone)]
     42 pub struct Tags<'a> {
     43     ptr: *mut bindings::ndb_tags,
     44     note: &'a Note<'a>,
     45 }
     46 
     47 impl<'a> Tags<'a> {
     48     pub(crate) fn new(ptr: *mut bindings::ndb_tags, note: &'a Note<'a>) -> Self {
     49         Tags { ptr, note }
     50     }
     51 
     52     pub fn count(&self) -> u16 {
     53         unsafe { bindings::ndb_tags_count(self.as_ptr()) }
     54     }
     55 
     56     pub fn iter(&self) -> TagsIter<'a> {
     57         TagsIter::new(self.note)
     58     }
     59 
     60     pub fn note(&self) -> &'a Note<'a> {
     61         self.note
     62     }
     63 
     64     pub fn as_ptr(&self) -> *mut bindings::ndb_tags {
     65         self.ptr
     66     }
     67 }
     68 
     69 #[derive(Debug, Copy, Clone)]
     70 pub struct TagsIter<'a> {
     71     iter: bindings::ndb_iterator,
     72     note: &'a Note<'a>,
     73 }
     74 
     75 impl<'a> TagsIter<'a> {
     76     pub fn new(note: &'a Note<'a>) -> Self {
     77         let iter = bindings::ndb_iterator {
     78             note: std::ptr::null_mut(),
     79             tag: std::ptr::null_mut(),
     80             index: 0,
     81         };
     82         let mut iter = TagsIter { note, iter };
     83         unsafe {
     84             bindings::ndb_tags_iterate_start(note.as_ptr(), &mut iter.iter);
     85         };
     86         iter
     87     }
     88 
     89     pub fn tag(&self) -> Option<Tag<'a>> {
     90         let tag_ptr = unsafe { *self.as_ptr() }.tag;
     91         if tag_ptr.is_null() {
     92             None
     93         } else {
     94             Some(Tag::new(tag_ptr, self.note()))
     95         }
     96     }
     97 
     98     pub fn note(&self) -> &'a Note<'a> {
     99         self.note
    100     }
    101 
    102     pub fn as_ptr(&self) -> *const bindings::ndb_iterator {
    103         &self.iter
    104     }
    105 
    106     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_iterator {
    107         &mut self.iter
    108     }
    109 }
    110 
    111 #[derive(Debug, Copy, Clone)]
    112 pub struct TagIter<'a> {
    113     tag: Tag<'a>,
    114     index: u16,
    115 }
    116 
    117 impl<'a> TagIter<'a> {
    118     pub fn new(tag: Tag<'a>) -> Self {
    119         let index = 0;
    120         TagIter { tag, index }
    121     }
    122 
    123     pub fn done(&self) -> bool {
    124         self.index >= self.tag.count()
    125     }
    126 }
    127 
    128 impl<'a> Iterator for TagIter<'a> {
    129     type Item = NdbStr<'a>;
    130 
    131     fn next(&mut self) -> Option<Self::Item> {
    132         let tag = self.tag.get(self.index);
    133         if tag.is_some() {
    134             self.index += 1;
    135             tag
    136         } else {
    137             None
    138         }
    139     }
    140 }
    141 
    142 impl<'a> Iterator for TagsIter<'a> {
    143     type Item = Tag<'a>;
    144 
    145     fn next(&mut self) -> Option<Self::Item> {
    146         unsafe {
    147             bindings::ndb_tags_iterate_next(self.as_mut_ptr());
    148         };
    149         self.tag()
    150     }
    151 }
    152 
    153 #[cfg(test)]
    154 mod tests {
    155     use super::*;
    156     use crate::config::Config;
    157     use crate::test_util;
    158     use crate::{Filter, Ndb, NdbStrVariant, Transaction};
    159 
    160     #[tokio::test]
    161     async fn tag_iter_works() {
    162         let db = "target/testdbs/tag_iter_works";
    163         test_util::cleanup_db(&db);
    164 
    165         {
    166             let ndb = Ndb::new(db, &Config::new()).expect("ndb");
    167             let sub = ndb
    168                 .subscribe(vec![Filter::new()
    169                     .ids(vec![[
    170                         0xc5, 0xd9, 0x8c, 0xbf, 0x4b, 0xcd, 0x81, 0x1e, 0x28, 0x66, 0x77, 0x0c,
    171                         0x3d, 0x38, 0x0c, 0x02, 0x84, 0xce, 0x1d, 0xaf, 0x3a, 0xe9, 0x98, 0x3d,
    172                         0x22, 0x56, 0x5c, 0xb0, 0x66, 0xcf, 0x2a, 0x19,
    173                     ]])
    174                     .build()])
    175                 .expect("sub");
    176             let waiter = ndb.wait_for_notes(&sub, 1);
    177             ndb.process_event(r#"["EVENT","s",{"id": "c5d98cbf4bcd811e2866770c3d380c0284ce1daf3ae9983d22565cb066cf2a19","pubkey": "083727b7a6051673f399102dc48c229c0ec08186ecd7e54ad0e9116d38429c4f","created_at": 1712517119,"kind": 1,"tags": [["e","b9e548b4aa30fa4ce9edf552adaf458385716704994fbaa9e0aa0042a5a5e01e"],["p","140ee9ff21da6e6671f750a0a747c5a3487ee8835159c7ca863e867a1c537b4f"],["hi","3"]],"content": "hi","sig": "1eed792e4db69c2bde2f5be33a383ef8b17c6afd1411598d0c4618fbdf4dbcb9689354276a74614511907a45eec234e0786733e8a6fbb312e6abf153f15fd437"}]"#).expect("process ok");
    178             let res = waiter.await.expect("await ok");
    179             assert_eq!(res.len(), 1);
    180             let note_key = res[0];
    181             let txn = Transaction::new(&ndb).expect("txn");
    182             let note = ndb.get_note_by_key(&txn, note_key).expect("note");
    183             let tags = note.tags();
    184             assert_eq!(tags.count(), 3);
    185 
    186             let mut tags_iter = tags.iter();
    187 
    188             let t0 = tags_iter.next().expect("t0");
    189             let t0_e0 = t0.get(0).expect("e tag ok");
    190             let t0_e1 = t0.get(1).expect("e id ok");
    191             assert_eq!(t0_e0.variant(), NdbStrVariant::Str("e"));
    192             assert_eq!(
    193                 t0_e1.variant(),
    194                 NdbStrVariant::Id(&[
    195                     0xb9, 0xe5, 0x48, 0xb4, 0xaa, 0x30, 0xfa, 0x4c, 0xe9, 0xed, 0xf5, 0x52, 0xad,
    196                     0xaf, 0x45, 0x83, 0x85, 0x71, 0x67, 0x04, 0x99, 0x4f, 0xba, 0xa9, 0xe0, 0xaa,
    197                     0x00, 0x42, 0xa5, 0xa5, 0xe0, 0x1e
    198                 ])
    199             );
    200 
    201             let t1 = tags_iter.next().expect("t1");
    202             let t1_e0 = t1.get(0).expect("p tag ok");
    203             let t1_e1 = t1.get(1).expect("p id ok");
    204             assert_eq!(t1_e0.variant(), NdbStrVariant::Str("p"));
    205             assert_eq!(
    206                 t1_e1.variant(),
    207                 NdbStrVariant::Id(&[
    208                     0x14, 0x0e, 0xe9, 0xff, 0x21, 0xda, 0x6e, 0x66, 0x71, 0xf7, 0x50, 0xa0, 0xa7,
    209                     0x47, 0xc5, 0xa3, 0x48, 0x7e, 0xe8, 0x83, 0x51, 0x59, 0xc7, 0xca, 0x86, 0x3e,
    210                     0x86, 0x7a, 0x1c, 0x53, 0x7b, 0x4f
    211                 ])
    212             );
    213 
    214             let t2 = tags_iter.next().expect("t2");
    215             let t2_e0 = t2.get(0).expect("hi tag ok");
    216             let t2_e1 = t2.get(1).expect("hi value ok");
    217             assert_eq!(t2_e0.variant(), NdbStrVariant::Str("hi"));
    218             assert_eq!(t2_e1.variant(), NdbStrVariant::Str("3"));
    219         }
    220     }
    221 }