nostrdb-rs

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

filter.rs (43692B)


      1 use crate::{bindings, Error, FilterError, Note, Result};
      2 use std::ffi::CString;
      3 use std::fmt;
      4 use std::os::raw::c_char;
      5 use std::os::raw::c_void;
      6 use std::ptr::null_mut;
      7 use std::sync::Arc;
      8 use tracing::debug;
      9 
     10 pub struct FilterBuilder {
     11     pub data: bindings::ndb_filter,
     12     pub custom_ctx: Option<*mut c_void>,
     13 }
     14 
     15 pub struct Filter {
     16     pub data: bindings::ndb_filter,
     17     pub custom_ctx: Option<Arc<*mut c_void>>,
     18 }
     19 
     20 fn filter_fmt<'a, F>(filter: F, f: &mut fmt::Formatter<'_>) -> fmt::Result
     21 where
     22     F: IntoIterator<Item = FilterField<'a>>,
     23 {
     24     let mut dfmt = f.debug_struct("Filter");
     25     let mut fmt = &mut dfmt;
     26 
     27     for field in filter {
     28         fmt = match field {
     29             FilterField::Search(ref search) => fmt.field("search", search),
     30             FilterField::Ids(ref ids) => fmt.field("ids", ids),
     31             FilterField::Authors(ref authors) => fmt.field("authors", authors),
     32             FilterField::Kinds(ref kinds) => fmt.field("kinds", kinds),
     33             FilterField::Tags(ref chr, _tags) => fmt.field("tags", chr),
     34             FilterField::Since(ref n) => fmt.field("since", n),
     35             FilterField::Until(ref n) => fmt.field("until", n),
     36             FilterField::Limit(ref n) => fmt.field("limit", n),
     37             FilterField::Relays(ref n) => fmt.field("relays", n),
     38             FilterField::Custom(ref n) => fmt.field("custom", n),
     39         }
     40     }
     41 
     42     fmt.finish()
     43 }
     44 
     45 impl fmt::Debug for Filter {
     46     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     47         filter_fmt(self, f)
     48     }
     49 }
     50 
     51 impl fmt::Debug for FilterBuilder {
     52     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     53         filter_fmt(self, f)
     54     }
     55 }
     56 
     57 impl Clone for Filter {
     58     fn clone(&self) -> Self {
     59         // Default inits...
     60         //let mut new_filter: bindings::ndb_filter = Default::default();
     61         let null = null_mut();
     62         let mut new_filter = bindings::ndb_filter {
     63             finalized: 0,
     64             elem_buf: bindings::cursor {
     65                 start: null,
     66                 p: null,
     67                 end: null,
     68             },
     69             data_buf: bindings::cursor {
     70                 start: null,
     71                 p: null,
     72                 end: null,
     73             },
     74             num_elements: 0,
     75             current: -1,
     76             elements: [0; 10],
     77         };
     78 
     79         debug!("cloning filter");
     80         unsafe {
     81             bindings::ndb_filter_clone(
     82                 new_filter.as_mut_ptr(),
     83                 self.as_ptr() as *mut bindings::ndb_filter,
     84             );
     85         };
     86         Filter {
     87             data: new_filter,
     88             custom_ctx: self.custom_ctx.clone(),
     89         }
     90     }
     91 }
     92 
     93 impl bindings::ndb_filter {
     94     fn as_ptr(&self) -> *const bindings::ndb_filter {
     95         self as *const bindings::ndb_filter
     96     }
     97 
     98     fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
     99         self as *mut bindings::ndb_filter
    100     }
    101 
    102     fn as_ref(&self) -> &bindings::ndb_filter {
    103         self
    104     }
    105 
    106     pub fn mut_iter(&self) -> MutFilterIter<'_> {
    107         MutFilterIter::new(self.as_ref())
    108     }
    109 
    110     pub fn field(&self, index: i32) -> Option<FilterField<'_>> {
    111         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
    112 
    113         if ptr.is_null() {
    114             return None;
    115         }
    116 
    117         Some(FilterElements::new(self, ptr).field())
    118     }
    119 
    120     pub fn field_mut(&self, index: i32) -> Option<MutFilterField<'_>> {
    121         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
    122 
    123         if ptr.is_null() {
    124             return None;
    125         }
    126 
    127         FilterElements::new(self, ptr).field_mut()
    128     }
    129 
    130     pub fn elements(&self, index: i32) -> Option<FilterElements<'_>> {
    131         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
    132 
    133         if ptr.is_null() {
    134             return None;
    135         }
    136 
    137         Some(FilterElements::new(self, ptr))
    138     }
    139 }
    140 
    141 impl bindings::ndb_filter {
    142     fn new(pages: i32) -> Self {
    143         let null = null_mut();
    144         let mut filter_data = bindings::ndb_filter {
    145             finalized: 0,
    146             elem_buf: bindings::cursor {
    147                 start: null,
    148                 p: null,
    149                 end: null,
    150             },
    151             data_buf: bindings::cursor {
    152                 start: null,
    153                 p: null,
    154                 end: null,
    155             },
    156             num_elements: 0,
    157             current: -1,
    158             elements: [0; 10],
    159         };
    160 
    161         unsafe {
    162             bindings::ndb_filter_init_with(filter_data.as_mut_ptr(), pages);
    163         };
    164 
    165         filter_data
    166     }
    167 }
    168 
    169 impl Filter {
    170     pub fn new_with_capacity(pages: i32) -> FilterBuilder {
    171         FilterBuilder {
    172             data: bindings::ndb_filter::new(pages),
    173             custom_ctx: None,
    174         }
    175     }
    176 
    177     #[allow(clippy::new_ret_no_self)]
    178     pub fn new() -> FilterBuilder {
    179         Self::new_with_capacity(256)
    180     }
    181 
    182     pub fn copy_from<'a, I>(filter: I) -> FilterBuilder
    183     where
    184         I: IntoIterator<Item = FilterField<'a>>,
    185     {
    186         let mut builder = Filter::new();
    187         for field in filter {
    188             match field {
    189                 FilterField::Custom(_n) => {
    190                     // TODO: copy custom filters
    191                 }
    192                 FilterField::Relays(relays) => builder = builder.relays(relays),
    193                 FilterField::Search(search) => {
    194                     builder = builder.search(search);
    195                 }
    196                 FilterField::Ids(ids) => {
    197                     builder = builder.ids(ids);
    198                 }
    199                 FilterField::Authors(authors) => builder = builder.authors(authors),
    200                 FilterField::Kinds(kinds) => builder = builder.kinds(kinds),
    201                 FilterField::Tags(chr, tags) => {
    202                     builder.start_tags_field(chr).unwrap();
    203                     for field in tags {
    204                         match field {
    205                             FilterElement::Id(id) => builder.add_id_element(id).unwrap(),
    206                             FilterElement::Str(str_) => builder.add_str_element(str_).unwrap(),
    207                             FilterElement::Int(int) => builder.add_int_element(int).unwrap(),
    208                             FilterElement::Custom => {
    209                                 todo!("copy filters with custom filters");
    210                             }
    211                         }
    212                     }
    213                     builder.end_field();
    214                 }
    215                 FilterField::Since(n) => builder = builder.since(n),
    216                 FilterField::Until(n) => builder = builder.until(n),
    217                 FilterField::Limit(n) => builder = builder.limit(n),
    218             }
    219         }
    220         builder
    221     }
    222 
    223     pub fn from_json(json: &str) -> Result<Self> {
    224         Self::from_json_with_bufsize(json, 1024usize * 1024usize)
    225     }
    226 
    227     pub fn from_json_with_bufsize(json: &str, bufsize: usize) -> Result<Self> {
    228         let mut buf = Vec::with_capacity(bufsize);
    229         let mut filter = Filter::new();
    230         unsafe {
    231             let json_cstr = CString::new(json).expect("string to cstring conversion failed");
    232             let size = bindings::ndb_filter_from_json(
    233                 json_cstr.as_ptr(),
    234                 json.len() as i32,
    235                 filter.as_mut_ptr(),
    236                 buf.as_mut_ptr(),
    237                 bufsize as ::std::os::raw::c_int,
    238             ) as usize;
    239 
    240             // Step 4: Check the return value for success
    241             if size == 0 {
    242                 return Err(Error::BufferOverflow); // Handle the error appropriately
    243             }
    244 
    245             Ok(Filter {
    246                 data: filter.data,
    247                 custom_ctx: None,
    248             })
    249         }
    250     }
    251 
    252     pub fn to_ref(&self) -> &bindings::ndb_filter {
    253         &self.data
    254     }
    255 
    256     pub fn mut_iter(&self) -> MutFilterIter<'_> {
    257         self.data.mut_iter()
    258     }
    259 
    260     pub fn matches(&self, note: &Note) -> bool {
    261         unsafe {
    262             bindings::ndb_filter_matches(self.as_ptr() as *mut bindings::ndb_filter, note.as_ptr())
    263                 != 0
    264         }
    265     }
    266 
    267     pub fn num_elements(&self) -> i32 {
    268         unsafe { &*(self.as_ptr()) }.num_elements
    269     }
    270 
    271     pub fn limit_mut(self, limit: u64) -> Self {
    272         for field in self.mut_iter() {
    273             if let MutFilterField::Limit(val) = field {
    274                 *val = limit;
    275                 return self;
    276             }
    277         }
    278 
    279         Filter::copy_from(&self).limit(limit).build()
    280     }
    281 
    282     pub fn until_mut(self, until: u64) -> Self {
    283         for field in self.mut_iter() {
    284             if let MutFilterField::Until(val) = field {
    285                 *val = until;
    286                 return self;
    287             }
    288         }
    289 
    290         Filter::copy_from(&self).until(until).build()
    291     }
    292 
    293     pub fn since(&self) -> Option<u64> {
    294         for field in self {
    295             if let FilterField::Since(since) = field {
    296                 return Some(since);
    297             }
    298         }
    299 
    300         None
    301     }
    302 
    303     pub fn limit(&self) -> Option<u64> {
    304         for field in self {
    305             if let FilterField::Limit(limit) = field {
    306                 return Some(limit);
    307             }
    308         }
    309 
    310         None
    311     }
    312 
    313     pub fn until(&self) -> Option<u64> {
    314         for field in self {
    315             if let FilterField::Until(until) = field {
    316                 return Some(until);
    317             }
    318         }
    319 
    320         None
    321     }
    322 
    323     pub fn since_mut(self, since: u64) -> Self {
    324         for field in self.mut_iter() {
    325             if let MutFilterField::Since(val) = field {
    326                 *val = since;
    327                 return self;
    328             }
    329         }
    330 
    331         Filter::copy_from(&self).since(since).build()
    332     }
    333 
    334     pub fn as_ptr(&self) -> *const bindings::ndb_filter {
    335         self.data.as_ptr()
    336     }
    337 
    338     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
    339         self.data.as_mut_ptr()
    340     }
    341 
    342     pub fn json_with_bufsize(&self, bufsize: usize) -> Result<String> {
    343         let mut buf = Vec::with_capacity(bufsize);
    344         unsafe {
    345             let size = bindings::ndb_filter_json(
    346                 self.as_ptr(),
    347                 buf.as_mut_ptr() as *mut ::std::os::raw::c_char,
    348                 bufsize as ::std::os::raw::c_int,
    349             ) as usize;
    350 
    351             // Step 4: Check the return value for success
    352             if size == 0 {
    353                 return Err(Error::BufferOverflow); // Handle the error appropriately
    354             }
    355 
    356             buf.set_len(size);
    357 
    358             Ok(std::str::from_utf8_unchecked(&buf[..size - 1]).to_string())
    359         }
    360     }
    361 
    362     pub fn json(&self) -> Result<String> {
    363         // 1mb buffer
    364         self.json_with_bufsize(1024usize * 1024usize)
    365     }
    366 }
    367 
    368 impl Default for FilterBuilder {
    369     fn default() -> Self {
    370         FilterBuilder {
    371             data: bindings::ndb_filter::new(256),
    372             custom_ctx: None,
    373         }
    374     }
    375 }
    376 
    377 impl FilterBuilder {
    378     pub fn new() -> FilterBuilder {
    379         Self::default()
    380     }
    381 
    382     pub fn to_ref(&self) -> &bindings::ndb_filter {
    383         &self.data
    384     }
    385 
    386     pub fn mut_iter(&self) -> MutFilterIter<'_> {
    387         self.data.mut_iter()
    388     }
    389 
    390     pub fn as_ptr(&self) -> *const bindings::ndb_filter {
    391         self.data.as_ptr()
    392     }
    393 
    394     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
    395         self.data.as_mut_ptr()
    396     }
    397 
    398     pub fn add_int_element(&mut self, i: u64) -> Result<()> {
    399         let res = unsafe { bindings::ndb_filter_add_int_element(self.as_mut_ptr(), i) };
    400         if res == 0 {
    401             return Err(FilterError::already_exists());
    402         }
    403 
    404         Ok(())
    405     }
    406 
    407     pub fn add_str_element(&mut self, s: &str) -> Result<()> {
    408         let c_str = CString::new(s).expect("string to cstring conversion failed");
    409         let r = unsafe { bindings::ndb_filter_add_str_element(self.as_mut_ptr(), c_str.as_ptr()) };
    410 
    411         if r == 0 {
    412             return Err(FilterError::already_exists());
    413         }
    414 
    415         Ok(())
    416     }
    417 
    418     /// Set a callback to add custom filtering logic to the query
    419     pub fn add_custom_filter_element<F>(&mut self, closure: F) -> Result<()>
    420     where
    421         F: FnMut(Note<'_>) -> bool,
    422     {
    423         // Box the closure to ensure it has a stable address.
    424         let boxed_closure: Box<dyn FnMut(Note<'_>) -> bool> = Box::new(closure);
    425 
    426         // Convert it to a raw pointer to store in sub_cb_ctx.
    427         // FIXME: THIS LEAKS! we need some way to clean this up after the filter
    428         // is destroyed.
    429         let ctx_ptr = Box::into_raw(Box::new(boxed_closure)) as *mut ::std::os::raw::c_void;
    430         self.custom_ctx = Some(ctx_ptr);
    431 
    432         let r = unsafe {
    433             bindings::ndb_filter_add_custom_filter_element(
    434                 self.as_mut_ptr(),
    435                 Some(custom_filter_trampoline),
    436                 ctx_ptr,
    437             )
    438         };
    439 
    440         if r == 0 {
    441             return Err(FilterError::already_exists());
    442         }
    443 
    444         Ok(())
    445     }
    446 
    447     pub fn add_id_element(&mut self, id: &[u8; 32]) -> Result<()> {
    448         let ptr: *const ::std::os::raw::c_uchar = id.as_ptr() as *const ::std::os::raw::c_uchar;
    449         let r = unsafe { bindings::ndb_filter_add_id_element(self.as_mut_ptr(), ptr) };
    450 
    451         if r == 0 {
    452             return Err(FilterError::already_exists());
    453         }
    454 
    455         Ok(())
    456     }
    457 
    458     pub fn start_field(&mut self, field: bindings::ndb_filter_fieldtype) -> Result<()> {
    459         let r = unsafe { bindings::ndb_filter_start_field(self.as_mut_ptr(), field) };
    460 
    461         if r == 0 {
    462             return Err(FilterError::already_started());
    463         }
    464 
    465         Ok(())
    466     }
    467 
    468     pub fn start_tags_field(&mut self, tag: char) -> Result<()> {
    469         let r =
    470             unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
    471         if r == 0 {
    472             return Err(FilterError::already_started());
    473         }
    474         Ok(())
    475     }
    476 
    477     pub fn start_kinds_field(&mut self) -> Result<()> {
    478         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_KINDS)
    479     }
    480 
    481     pub fn start_authors_field(&mut self) -> Result<()> {
    482         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_AUTHORS)
    483     }
    484 
    485     pub fn start_since_field(&mut self) -> Result<()> {
    486         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_SINCE)
    487     }
    488 
    489     pub fn start_custom_field(&mut self) -> Result<()> {
    490         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_CUSTOM)
    491     }
    492 
    493     pub fn start_until_field(&mut self) -> Result<()> {
    494         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_UNTIL)
    495     }
    496 
    497     pub fn start_limit_field(&mut self) -> Result<()> {
    498         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_LIMIT)
    499     }
    500 
    501     pub fn start_ids_field(&mut self) -> Result<()> {
    502         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_IDS)
    503     }
    504 
    505     pub fn start_search_field(&mut self) -> Result<()> {
    506         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_SEARCH)
    507     }
    508 
    509     pub fn start_relays_field(&mut self) -> Result<()> {
    510         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_RELAYS)
    511     }
    512 
    513     #[allow(dead_code)]
    514     pub fn start_events_field(&mut self) -> Result<()> {
    515         self.start_tags_field('e')
    516     }
    517 
    518     pub fn start_pubkeys_field(&mut self) -> Result<()> {
    519         self.start_tags_field('p')
    520     }
    521 
    522     pub fn start_tag_field(&mut self, tag: char) -> Result<()> {
    523         let r =
    524             unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
    525         if r == 0 {
    526             return Err(FilterError::FieldAlreadyStarted.into());
    527         }
    528         Ok(())
    529     }
    530 
    531     pub fn end_field(&mut self) {
    532         unsafe {
    533             bindings::ndb_filter_end_field(self.as_mut_ptr());
    534         };
    535     }
    536 
    537     pub fn events<'a, I>(mut self, events: I) -> Self
    538     where
    539         I: IntoIterator<Item = &'a [u8; 32]>,
    540     {
    541         self.start_tag_field('e').unwrap();
    542         for id in events {
    543             self.add_id_element(id).unwrap();
    544         }
    545         self.end_field();
    546         self
    547     }
    548 
    549     pub fn event(mut self, id: &[u8; 32]) -> Self {
    550         self.start_tag_field('e').unwrap();
    551         self.add_id_element(id).unwrap();
    552         self.end_field();
    553         self
    554     }
    555 
    556     pub fn relays<'a, I>(mut self, relays: I) -> Self
    557     where
    558         I: IntoIterator<Item = &'a str>,
    559     {
    560         self.start_relays_field().unwrap();
    561         for relay in relays {
    562             self.add_str_element(relay).unwrap();
    563         }
    564         self.end_field();
    565         self
    566     }
    567 
    568     pub fn search(mut self, search: &str) -> Self {
    569         self.start_search_field().unwrap();
    570         self.add_str_element(search).unwrap();
    571         self.end_field();
    572         self
    573     }
    574 
    575     pub fn ids<'a, I>(mut self, ids: I) -> Self
    576     where
    577         I: IntoIterator<Item = &'a [u8; 32]>,
    578     {
    579         self.start_ids_field().unwrap();
    580         for id in ids {
    581             self.add_id_element(id).unwrap();
    582         }
    583         self.end_field();
    584         self
    585     }
    586 
    587     pub fn pubkeys<'a, I>(mut self, pubkeys: I) -> Self
    588     where
    589         I: IntoIterator<Item = &'a [u8; 32]>,
    590     {
    591         self.start_tag_field('p').unwrap();
    592         for pk in pubkeys {
    593             self.add_id_element(pk).unwrap();
    594         }
    595         self.end_field();
    596         self
    597     }
    598 
    599     pub fn authors<'a, I>(mut self, authors: I) -> Self
    600     where
    601         I: IntoIterator<Item = &'a [u8; 32]>,
    602     {
    603         self.start_authors_field().unwrap();
    604         for author in authors {
    605             self.add_id_element(author).unwrap();
    606         }
    607         self.end_field();
    608         self
    609     }
    610 
    611     pub fn kinds<I>(mut self, kinds: I) -> Self
    612     where
    613         I: IntoIterator<Item = u64>,
    614     {
    615         self.start_kinds_field().unwrap();
    616         for kind in kinds {
    617             self.add_int_element(kind).unwrap();
    618         }
    619         self.end_field();
    620         self
    621     }
    622 
    623     pub fn pubkey<'a, I>(mut self, pubkeys: I) -> Self
    624     where
    625         I: IntoIterator<Item = &'a [u8; 32]>,
    626     {
    627         self.start_pubkeys_field().unwrap();
    628         for pubkey in pubkeys {
    629             self.add_id_element(pubkey).unwrap();
    630         }
    631         self.end_field();
    632         self
    633     }
    634 
    635     pub fn tags<'a, I>(mut self, tags: I, tag: char) -> Self
    636     where
    637         I: IntoIterator<Item = &'a str>,
    638     {
    639         self.start_tag_field(tag).unwrap();
    640         for tag in tags {
    641             self.add_str_element(tag).unwrap();
    642         }
    643         self.end_field();
    644         self
    645     }
    646 
    647     pub fn custom<F>(mut self, filter: F) -> Self
    648     where
    649         F: FnMut(Note<'_>) -> bool,
    650     {
    651         self.start_custom_field().unwrap();
    652         self.add_custom_filter_element(filter).unwrap();
    653         self.end_field();
    654         self
    655     }
    656 
    657     pub fn since(mut self, since: u64) -> Self {
    658         for field in self.mut_iter() {
    659             if let MutFilterField::Since(val) = field {
    660                 *val = since;
    661                 return self;
    662             }
    663         }
    664 
    665         self.start_since_field().unwrap();
    666         self.add_int_element(since).unwrap();
    667         self.end_field();
    668         self
    669     }
    670 
    671     pub fn until(mut self, until: u64) -> Self {
    672         for field in self.mut_iter() {
    673             if let MutFilterField::Until(val) = field {
    674                 *val = until;
    675                 return self;
    676             }
    677         }
    678 
    679         self.start_until_field().unwrap();
    680         self.add_int_element(until).unwrap();
    681         self.end_field();
    682         self
    683     }
    684 
    685     pub fn limit(mut self, limit: u64) -> Self {
    686         for field in self.mut_iter() {
    687             if let MutFilterField::Limit(val) = field {
    688                 *val = limit;
    689                 return self;
    690             }
    691         }
    692 
    693         self.start_limit_field().unwrap();
    694         self.add_int_element(limit).unwrap();
    695         self.end_field();
    696         self
    697     }
    698 
    699     pub fn build(&mut self) -> Filter {
    700         unsafe {
    701             bindings::ndb_filter_end(self.as_mut_ptr());
    702         };
    703 
    704         let custom_ctx = self.custom_ctx.map(Arc::new);
    705 
    706         Filter {
    707             data: self.data,
    708             custom_ctx,
    709         }
    710     }
    711 }
    712 
    713 impl Drop for Filter {
    714     fn drop(&mut self) {
    715         debug!("dropping filter {:?}", self);
    716         unsafe { bindings::ndb_filter_destroy(self.as_mut_ptr()) };
    717 
    718         if let Some(ptr_arc) = &self.custom_ctx {
    719             // Only drop the actual Box if this is the last Arc
    720             let count = Arc::strong_count(ptr_arc);
    721             if count == 1 {
    722                 let raw = **ptr_arc as *mut Box<dyn FnMut(Note) -> bool>;
    723                 tracing::trace!("dropping custom filter closure context");
    724                 unsafe {
    725                     drop(Box::from_raw(raw));
    726                 }
    727             } else {
    728                 tracing::trace!("NOT dropping custom filter closure context, {count} instances");
    729             }
    730         }
    731     }
    732 }
    733 
    734 impl Drop for FilterBuilder {
    735     fn drop(&mut self) {
    736         debug!("dropping filter builder");
    737     }
    738 }
    739 
    740 #[derive(Debug, Copy, Clone)]
    741 pub struct MutFilterIter<'a> {
    742     filter: &'a bindings::ndb_filter,
    743     index: i32,
    744 }
    745 
    746 impl<'a> MutFilterIter<'a> {
    747     pub(crate) fn new(filter: &'a bindings::ndb_filter) -> Self {
    748         let index = 0;
    749         MutFilterIter { filter, index }
    750     }
    751 
    752     pub fn done(&self) -> bool {
    753         self.index >= self.filter.num_elements
    754     }
    755 }
    756 
    757 #[derive(Debug, Copy, Clone)]
    758 pub struct FilterIter<'a> {
    759     filter: &'a bindings::ndb_filter,
    760     index: i32,
    761 }
    762 
    763 /// Filter element: `authors`, `limit`, etc
    764 #[derive(Copy, Clone, Debug)]
    765 pub struct FilterElements<'a> {
    766     filter: &'a bindings::ndb_filter,
    767     elements: *mut bindings::ndb_filter_elements,
    768 }
    769 
    770 #[derive(Copy, Clone, Debug)]
    771 pub struct FilterIdElements<'a> {
    772     filter: &'a bindings::ndb_filter,
    773     elements: *mut bindings::ndb_filter_elements,
    774 }
    775 
    776 #[derive(Copy, Clone, Debug)]
    777 pub struct FilterStrElements<'a> {
    778     filter: &'a bindings::ndb_filter,
    779     elements: *mut bindings::ndb_filter_elements,
    780 }
    781 
    782 #[derive(Copy, Clone, Debug)]
    783 pub struct FilterIntElements<'a> {
    784     _filter: &'a bindings::ndb_filter,
    785     elements: *mut bindings::ndb_filter_elements,
    786 }
    787 
    788 pub struct FilterIdElemIter<'a> {
    789     ids: FilterIdElements<'a>,
    790     index: i32,
    791 }
    792 
    793 pub struct FilterStrElemIter<'a> {
    794     strs: FilterStrElements<'a>,
    795     index: i32,
    796 }
    797 
    798 pub struct FilterIntElemIter<'a> {
    799     ints: FilterIntElements<'a>,
    800     index: i32,
    801 }
    802 
    803 impl<'a> FilterIdElemIter<'a> {
    804     pub(crate) fn new(ids: FilterIdElements<'a>) -> Self {
    805         let index = 0;
    806         Self { ids, index }
    807     }
    808 
    809     pub fn done(&self) -> bool {
    810         self.index >= self.ids.count()
    811     }
    812 }
    813 
    814 impl<'a> FilterStrElemIter<'a> {
    815     pub(crate) fn new(strs: FilterStrElements<'a>) -> Self {
    816         let index = 0;
    817         Self { strs, index }
    818     }
    819 
    820     pub fn done(&self) -> bool {
    821         self.index >= self.strs.count()
    822     }
    823 }
    824 
    825 impl<'a> FilterIntElemIter<'a> {
    826     pub(crate) fn new(ints: FilterIntElements<'a>) -> Self {
    827         let index = 0;
    828         Self { ints, index }
    829     }
    830 
    831     pub fn done(&self) -> bool {
    832         self.index >= self.ints.count()
    833     }
    834 }
    835 
    836 impl<'a> FilterIdElements<'a> {
    837     pub(crate) fn new(
    838         filter: &'a bindings::ndb_filter,
    839         elements: *mut bindings::ndb_filter_elements,
    840     ) -> Self {
    841         Self { filter, elements }
    842     }
    843 
    844     pub fn count(&self) -> i32 {
    845         unsafe { &*self.elements }.count
    846     }
    847 
    848     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    849     fn elemtype(&self) -> FieldElemType {
    850         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    851             .expect("expected valid filter element type")
    852     }
    853 
    854     pub fn get(self, index: i32) -> Option<&'a [u8; 32]> {
    855         assert!(self.elemtype() == FieldElemType::Id);
    856 
    857         let id = unsafe {
    858             bindings::ndb_filter_get_id_element(self.filter.as_ptr(), self.elements, index)
    859                 as *const [u8; 32]
    860         };
    861 
    862         if id.is_null() {
    863             return None;
    864         }
    865 
    866         Some(unsafe { &*id })
    867     }
    868 }
    869 
    870 impl<'a> FilterStrElements<'a> {
    871     pub(crate) fn new(
    872         filter: &'a bindings::ndb_filter,
    873         elements: *mut bindings::ndb_filter_elements,
    874     ) -> Self {
    875         Self { filter, elements }
    876     }
    877 
    878     pub fn count(&self) -> i32 {
    879         unsafe { &*self.elements }.count
    880     }
    881 
    882     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    883     fn elemtype(&self) -> FieldElemType {
    884         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    885             .expect("expected valid filter element type")
    886     }
    887 
    888     pub fn get(self, index: i32) -> Option<&'a str> {
    889         assert!(self.elemtype() == FieldElemType::Id);
    890 
    891         let ptr = unsafe {
    892             bindings::ndb_filter_get_string_element(self.filter.as_ptr(), self.elements, index)
    893         };
    894 
    895         if ptr.is_null() {
    896             return None;
    897         }
    898 
    899         let byte_slice = unsafe { std::slice::from_raw_parts(ptr as *mut u8, libc::strlen(ptr)) };
    900         Some(unsafe { std::str::from_utf8_unchecked(byte_slice) })
    901     }
    902 }
    903 
    904 impl<'a> FilterIntElements<'a> {
    905     pub(crate) fn new(
    906         filter: &'a bindings::ndb_filter,
    907         elements: *mut bindings::ndb_filter_elements,
    908     ) -> Self {
    909         Self {
    910             _filter: filter,
    911             elements,
    912         }
    913     }
    914 
    915     pub fn count(&self) -> i32 {
    916         unsafe { &*self.elements }.count
    917     }
    918 
    919     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    920     fn elemtype(&self) -> FieldElemType {
    921         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    922             .expect("expected valid filter element type")
    923     }
    924 
    925     pub fn get(self, index: i32) -> Option<u64> {
    926         if index >= self.count() {
    927             return None;
    928         }
    929         assert!(self.elemtype() == FieldElemType::Int);
    930         Some(unsafe { bindings::ndb_filter_get_int_element(self.elements, index) })
    931     }
    932 }
    933 
    934 pub enum FilterField<'a> {
    935     Ids(FilterIdElements<'a>),
    936     Authors(FilterIdElements<'a>),
    937     Kinds(FilterIntElements<'a>),
    938     Tags(char, FilterElements<'a>),
    939     Search(&'a str),
    940     Since(u64),
    941     Until(u64),
    942     Limit(u64),
    943     Relays(FilterStrElements<'a>),
    944     Custom(u64),
    945 }
    946 
    947 pub enum MutFilterField<'a> {
    948     Since(&'a mut u64),
    949     Until(&'a mut u64),
    950     Limit(&'a mut u64),
    951 }
    952 
    953 impl<'a> FilterField<'a> {
    954     pub fn new(elements: FilterElements<'a>) -> Self {
    955         match elements.fieldtype() {
    956             FilterFieldType::Custom => FilterField::Custom(0),
    957 
    958             FilterFieldType::Relays => {
    959                 FilterField::Relays(FilterStrElements::new(elements.filter(), elements.as_ptr()))
    960             }
    961 
    962             FilterFieldType::Search => {
    963                 for element in elements {
    964                     if let FilterElement::Str(s) = element {
    965                         return FilterField::Search(s);
    966                     }
    967                 }
    968 
    969                 panic!("something is very wrong");
    970             }
    971 
    972             FilterFieldType::Ids => {
    973                 FilterField::Ids(FilterIdElements::new(elements.filter(), elements.as_ptr()))
    974             }
    975 
    976             FilterFieldType::Authors => {
    977                 FilterField::Authors(FilterIdElements::new(elements.filter(), elements.as_ptr()))
    978             }
    979 
    980             FilterFieldType::Kinds => {
    981                 FilterField::Kinds(FilterIntElements::new(elements.filter(), elements.as_ptr()))
    982             }
    983 
    984             FilterFieldType::Tags => FilterField::Tags(elements.tag(), elements),
    985 
    986             FilterFieldType::Since => FilterField::Since(
    987                 FilterIntElements::new(elements.filter(), elements.as_ptr())
    988                     .into_iter()
    989                     .next()
    990                     .expect("expected since in filter"),
    991             ),
    992 
    993             FilterFieldType::Until => FilterField::Until(
    994                 FilterIntElements::new(elements.filter(), elements.as_ptr())
    995                     .into_iter()
    996                     .next()
    997                     .expect("expected until in filter"),
    998             ),
    999 
   1000             FilterFieldType::Limit => FilterField::Limit(
   1001                 FilterIntElements::new(elements.filter(), elements.as_ptr())
   1002                     .into_iter()
   1003                     .next()
   1004                     .expect("expected limit in filter"),
   1005             ),
   1006         }
   1007     }
   1008 }
   1009 
   1010 impl<'a> FilterElements<'a> {
   1011     pub(crate) fn new(
   1012         filter: &'a bindings::ndb_filter,
   1013         elements: *mut bindings::ndb_filter_elements,
   1014     ) -> Self {
   1015         FilterElements { filter, elements }
   1016     }
   1017 
   1018     pub fn filter(self) -> &'a bindings::ndb_filter {
   1019         self.filter
   1020     }
   1021 
   1022     pub fn as_ptr(self) -> *mut bindings::ndb_filter_elements {
   1023         self.elements
   1024     }
   1025 
   1026     pub fn count(&self) -> i32 {
   1027         unsafe { &*self.elements }.count
   1028     }
   1029 
   1030     pub fn field(self) -> FilterField<'a> {
   1031         FilterField::new(self)
   1032     }
   1033 
   1034     /// Mutably access since, until, limit. We can probably do others in
   1035     /// the future, but this is the most useful at the moment
   1036     pub fn field_mut(self) -> Option<MutFilterField<'a>> {
   1037         if self.count() != 1 {
   1038             return None;
   1039         }
   1040 
   1041         if self.elemtype() != FieldElemType::Int {
   1042             return None;
   1043         }
   1044 
   1045         match self.fieldtype() {
   1046             FilterFieldType::Since => Some(MutFilterField::Since(self.get_mut_int(0))),
   1047             FilterFieldType::Until => Some(MutFilterField::Until(self.get_mut_int(0))),
   1048             FilterFieldType::Limit => Some(MutFilterField::Limit(self.get_mut_int(0))),
   1049             _ => None,
   1050         }
   1051     }
   1052 
   1053     pub fn get_mut_int(&self, index: i32) -> &'a mut u64 {
   1054         unsafe { &mut *bindings::ndb_filter_get_int_element_ptr(self.elements, index) }
   1055     }
   1056 
   1057     pub fn get(self, index: i32) -> Option<FilterElement<'a>> {
   1058         if index >= self.count() {
   1059             return None;
   1060         }
   1061 
   1062         match self.elemtype() {
   1063             FieldElemType::Id => {
   1064                 let id = unsafe {
   1065                     bindings::ndb_filter_get_id_element(self.filter.as_ptr(), self.elements, index)
   1066                         as *const [u8; 32]
   1067                 };
   1068                 if id.is_null() {
   1069                     return None;
   1070                 }
   1071                 Some(FilterElement::Id(unsafe { &*id }))
   1072             }
   1073 
   1074             FieldElemType::Str => {
   1075                 let cstr = unsafe {
   1076                     bindings::ndb_filter_get_string_element(
   1077                         self.filter.as_ptr(),
   1078                         self.elements,
   1079                         index,
   1080                     )
   1081                 };
   1082                 if cstr.is_null() {
   1083                     return None;
   1084                 }
   1085                 let str = unsafe {
   1086                     let byte_slice =
   1087                         std::slice::from_raw_parts(cstr as *const u8, libc::strlen(cstr));
   1088                     std::str::from_utf8_unchecked(byte_slice)
   1089                 };
   1090                 Some(FilterElement::Str(str))
   1091             }
   1092 
   1093             FieldElemType::Int => {
   1094                 let num = unsafe { bindings::ndb_filter_get_int_element(self.elements, index) };
   1095                 Some(FilterElement::Int(num))
   1096             }
   1097 
   1098             FieldElemType::Custom => {
   1099                 //let custom = unsafe { bindings::ndb_filter_get_custom_filter_element() }
   1100                 Some(FilterElement::Custom)
   1101             }
   1102         }
   1103     }
   1104 
   1105     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
   1106     pub fn elemtype(&self) -> FieldElemType {
   1107         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
   1108             .expect("expected valid filter element type")
   1109     }
   1110 
   1111     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
   1112     pub fn tag(&self) -> char {
   1113         (unsafe { &*self.elements }.field.tag as u8) as char
   1114     }
   1115 
   1116     pub fn fieldtype(self) -> FilterFieldType {
   1117         FilterFieldType::new(unsafe { &*self.elements }.field.type_)
   1118             .expect("expected valid fieldtype")
   1119     }
   1120 }
   1121 
   1122 impl<'a> FilterIter<'a> {
   1123     pub fn new(filter: &'a bindings::ndb_filter) -> Self {
   1124         let index = 0;
   1125         FilterIter { filter, index }
   1126     }
   1127 
   1128     pub fn done(&self) -> bool {
   1129         self.index >= self.filter.num_elements
   1130     }
   1131 }
   1132 
   1133 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
   1134 pub enum FilterFieldType {
   1135     Ids,
   1136     Authors,
   1137     Kinds,
   1138     Tags,
   1139     Since,
   1140     Until,
   1141     Limit,
   1142     Search,
   1143     Relays,
   1144     Custom,
   1145 }
   1146 
   1147 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
   1148 pub enum FieldElemType {
   1149     Str,
   1150     Id,
   1151     Int,
   1152     Custom,
   1153 }
   1154 
   1155 impl FieldElemType {
   1156     pub(crate) fn new(val: bindings::ndb_generic_element_type) -> Option<Self> {
   1157         if val == bindings::ndb_generic_element_type_NDB_ELEMENT_UNKNOWN {
   1158             None
   1159         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_STRING {
   1160             Some(FieldElemType::Str)
   1161         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_ID {
   1162             Some(FieldElemType::Id)
   1163         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_INT {
   1164             Some(FieldElemType::Int)
   1165         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_CUSTOM {
   1166             Some(FieldElemType::Custom)
   1167         } else {
   1168             None
   1169         }
   1170     }
   1171 }
   1172 
   1173 impl FilterFieldType {
   1174     pub(crate) fn new(val: bindings::ndb_filter_fieldtype) -> Option<Self> {
   1175         if val == bindings::ndb_filter_fieldtype_NDB_FILTER_IDS {
   1176             Some(FilterFieldType::Ids)
   1177         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_AUTHORS {
   1178             Some(FilterFieldType::Authors)
   1179         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_KINDS {
   1180             Some(FilterFieldType::Kinds)
   1181         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_TAGS {
   1182             Some(FilterFieldType::Tags)
   1183         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_SINCE {
   1184             Some(FilterFieldType::Since)
   1185         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_UNTIL {
   1186             Some(FilterFieldType::Until)
   1187         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_LIMIT {
   1188             Some(FilterFieldType::Limit)
   1189         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_SEARCH {
   1190             Some(FilterFieldType::Search)
   1191         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_RELAYS {
   1192             Some(FilterFieldType::Relays)
   1193         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_CUSTOM {
   1194             Some(FilterFieldType::Custom)
   1195         } else {
   1196             None
   1197         }
   1198     }
   1199 }
   1200 
   1201 impl<'a> IntoIterator for &'a Filter {
   1202     type Item = FilterField<'a>;
   1203     type IntoIter = FilterIter<'a>;
   1204 
   1205     fn into_iter(self) -> Self::IntoIter {
   1206         FilterIter::new(self.to_ref())
   1207     }
   1208 }
   1209 
   1210 impl<'a> IntoIterator for &'a FilterBuilder {
   1211     type Item = FilterField<'a>;
   1212     type IntoIter = FilterIter<'a>;
   1213 
   1214     fn into_iter(self) -> Self::IntoIter {
   1215         FilterIter::new(self.to_ref())
   1216     }
   1217 }
   1218 
   1219 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
   1220 pub enum FilterElement<'a> {
   1221     Str(&'a str),
   1222     Id(&'a [u8; 32]),
   1223     Int(u64),
   1224     Custom,
   1225 }
   1226 
   1227 impl<'a> Iterator for FilterIter<'a> {
   1228     type Item = FilterField<'a>;
   1229 
   1230     fn next(&mut self) -> Option<FilterField<'a>> {
   1231         if self.done() {
   1232             return None;
   1233         }
   1234 
   1235         let ind = self.index;
   1236         self.index += 1;
   1237 
   1238         self.filter.field(ind)
   1239     }
   1240 }
   1241 
   1242 impl<'a> Iterator for MutFilterIter<'a> {
   1243     type Item = MutFilterField<'a>;
   1244 
   1245     fn next(&mut self) -> Option<MutFilterField<'a>> {
   1246         if self.done() {
   1247             return None;
   1248         }
   1249 
   1250         while !self.done() {
   1251             let mnext = self.filter.field_mut(self.index);
   1252             self.index += 1;
   1253 
   1254             if mnext.is_some() {
   1255                 return mnext;
   1256             }
   1257         }
   1258 
   1259         None
   1260     }
   1261 }
   1262 
   1263 impl<'a> IntoIterator for FilterIdElements<'a> {
   1264     type Item = &'a [u8; 32];
   1265     type IntoIter = FilterIdElemIter<'a>;
   1266 
   1267     fn into_iter(self) -> Self::IntoIter {
   1268         FilterIdElemIter::new(self)
   1269     }
   1270 }
   1271 
   1272 impl<'a> IntoIterator for FilterStrElements<'a> {
   1273     type Item = &'a str;
   1274     type IntoIter = FilterStrElemIter<'a>;
   1275 
   1276     fn into_iter(self) -> Self::IntoIter {
   1277         FilterStrElemIter::new(self)
   1278     }
   1279 }
   1280 
   1281 impl<'a> IntoIterator for FilterIntElements<'a> {
   1282     type Item = u64;
   1283     type IntoIter = FilterIntElemIter<'a>;
   1284 
   1285     fn into_iter(self) -> Self::IntoIter {
   1286         FilterIntElemIter::new(self)
   1287     }
   1288 }
   1289 
   1290 impl Iterator for FilterIntElemIter<'_> {
   1291     type Item = u64;
   1292 
   1293     fn next(&mut self) -> Option<u64> {
   1294         if self.done() {
   1295             return None;
   1296         }
   1297 
   1298         let ind = self.index;
   1299         self.index += 1;
   1300 
   1301         self.ints.get(ind)
   1302     }
   1303 }
   1304 
   1305 impl<'a> Iterator for FilterStrElemIter<'a> {
   1306     type Item = &'a str;
   1307 
   1308     fn next(&mut self) -> Option<&'a str> {
   1309         if self.done() {
   1310             return None;
   1311         }
   1312 
   1313         let ind = self.index;
   1314         self.index += 1;
   1315 
   1316         self.strs.get(ind)
   1317     }
   1318 }
   1319 
   1320 impl<'a> Iterator for FilterIdElemIter<'a> {
   1321     type Item = &'a [u8; 32];
   1322 
   1323     fn next(&mut self) -> Option<&'a [u8; 32]> {
   1324         if self.done() {
   1325             return None;
   1326         }
   1327 
   1328         let ind = self.index;
   1329         self.index += 1;
   1330 
   1331         self.ids.get(ind)
   1332     }
   1333 }
   1334 
   1335 impl<'a> IntoIterator for FilterElements<'a> {
   1336     type Item = FilterElement<'a>;
   1337     type IntoIter = FilterElemIter<'a>;
   1338 
   1339     fn into_iter(self) -> Self::IntoIter {
   1340         FilterElemIter::new(self)
   1341     }
   1342 }
   1343 
   1344 impl<'a> Iterator for FilterElemIter<'a> {
   1345     type Item = FilterElement<'a>;
   1346 
   1347     fn next(&mut self) -> Option<FilterElement<'a>> {
   1348         let element = self.elements.get(self.index);
   1349         if element.is_some() {
   1350             self.index += 1;
   1351             element
   1352         } else {
   1353             None
   1354         }
   1355     }
   1356 }
   1357 
   1358 #[derive(Copy, Clone, Debug)]
   1359 pub struct FilterElemIter<'a> {
   1360     elements: FilterElements<'a>,
   1361     index: i32,
   1362 }
   1363 
   1364 impl<'a> FilterElemIter<'a> {
   1365     pub(crate) fn new(elements: FilterElements<'a>) -> Self {
   1366         let index = 0;
   1367         FilterElemIter { elements, index }
   1368     }
   1369 }
   1370 
   1371 extern "C" fn custom_filter_trampoline(
   1372     ctx: *mut ::std::os::raw::c_void,
   1373     note: *mut bindings::ndb_note,
   1374 ) -> bool {
   1375     unsafe {
   1376         // Convert the raw pointer back into a reference to our closure.
   1377         // We know this pointer was created by Box::into_raw in `set_sub_callback_rust`.
   1378         let closure_ptr = ctx as *mut Box<dyn FnMut(Note<'_>) -> bool>;
   1379         assert!(!closure_ptr.is_null());
   1380         let closure = &mut *closure_ptr;
   1381         let note = Note::new_unowned(&*note);
   1382         closure(note)
   1383     }
   1384 }
   1385 
   1386 #[cfg(test)]
   1387 mod tests {
   1388     use super::*;
   1389 
   1390     #[test]
   1391     fn filter_limit_iter_works() {
   1392         let filter = Filter::new().limit(42).build();
   1393         let mut hit = 0;
   1394         for element in &filter {
   1395             if let FilterField::Limit(42) = element {
   1396                 hit += 1;
   1397             }
   1398         }
   1399         assert!(hit == 1);
   1400     }
   1401 
   1402     #[test]
   1403     fn filter_quick_since_mut_works() {
   1404         let id: [u8; 32] = [
   1405             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1406             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1407             0xe8, 0x5b, 0xa8, 0x59,
   1408         ];
   1409 
   1410         let mut hit = 0;
   1411         let mut filter = Filter::new().ids([&id, &id, &id]).build();
   1412 
   1413         // mutate
   1414         filter = filter.since_mut(3);
   1415 
   1416         for element in &filter {
   1417             if let FilterField::Since(s) = element {
   1418                 hit += 1;
   1419                 assert_eq!(s, 3);
   1420             }
   1421         }
   1422         assert!(hit == 1);
   1423     }
   1424 
   1425     #[test]
   1426     fn filter_since_mut_works() {
   1427         let id: [u8; 32] = [
   1428             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1429             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1430             0xe8, 0x5b, 0xa8, 0x59,
   1431         ];
   1432 
   1433         let mut hit = 0;
   1434         let filter = Filter::new().ids([&id, &id, &id]).since(1);
   1435 
   1436         for element in filter.mut_iter() {
   1437             if let MutFilterField::Since(since_ref) = element {
   1438                 hit += 1;
   1439                 assert_eq!(*since_ref, 1);
   1440                 *since_ref = 2;
   1441             }
   1442         }
   1443         for element in &filter {
   1444             if let FilterField::Since(s) = element {
   1445                 hit += 1;
   1446                 assert_eq!(s, 2);
   1447             }
   1448         }
   1449         assert!(hit == 2);
   1450     }
   1451 
   1452     #[test]
   1453     fn filter_id_iter_works() {
   1454         let id: [u8; 32] = [
   1455             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1456             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1457             0xe8, 0x5b, 0xa8, 0x59,
   1458         ];
   1459 
   1460         let filter = Filter::new().ids([&id, &id, &id]).build();
   1461         let mut hit = 0;
   1462         for element in &filter {
   1463             if let FilterField::Ids(ids) = element {
   1464                 for same_id in ids {
   1465                     hit += 1;
   1466                     assert!(same_id == &id);
   1467                 }
   1468             }
   1469         }
   1470         assert!(hit == 3);
   1471     }
   1472 
   1473     #[test]
   1474     fn filter_int_iter_works() {
   1475         let filter = Filter::new().kinds(vec![1, 2, 3]).build();
   1476         let mut hit = 0;
   1477         for element in &filter {
   1478             if let FilterField::Kinds(ks) = element {
   1479                 hit += 1;
   1480                 assert!(vec![1, 2, 3] == ks.into_iter().collect::<Vec<u64>>());
   1481             }
   1482         }
   1483         assert!(hit == 1);
   1484     }
   1485 
   1486     #[test]
   1487     fn filter_multiple_field_iter_works() {
   1488         let id: [u8; 32] = [
   1489             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1490             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1491             0xe8, 0x5b, 0xa8, 0x59,
   1492         ];
   1493         let filter = Filter::new().event(&id).kinds(vec![1, 2, 3]).build();
   1494         let mut hit = 0;
   1495         for element in &filter {
   1496             if let FilterField::Kinds(ks) = element {
   1497                 hit += 1;
   1498                 assert!(vec![1, 2, 3] == ks.into_iter().collect::<Vec<u64>>());
   1499             } else if let FilterField::Tags('e', ids) = element {
   1500                 for i in ids {
   1501                     hit += 1;
   1502                     assert!(i == FilterElement::Id(&id));
   1503                 }
   1504             }
   1505         }
   1506         assert!(hit == 2);
   1507     }
   1508 
   1509     #[test]
   1510     fn custom_filter_works() {
   1511         use crate::NoteBuilder;
   1512 
   1513         let seckey: [u8; 32] = [
   1514             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1515             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1516             0xe8, 0x5b, 0xa8, 0x59,
   1517         ];
   1518 
   1519         let note = NoteBuilder::new()
   1520             .kind(1)
   1521             .content("this is the content")
   1522             .created_at(42)
   1523             .start_tag()
   1524             .tag_str("comment")
   1525             .tag_str("this is a comment")
   1526             .start_tag()
   1527             .tag_str("blah")
   1528             .tag_str("something")
   1529             .sign(&seckey)
   1530             .build()
   1531             .expect("expected build to work");
   1532 
   1533         {
   1534             let filter = Filter::new().custom(|n| n.created_at() == 43).build();
   1535             assert!(!filter.matches(&note));
   1536         }
   1537 
   1538         {
   1539             let filter = Filter::new().custom(|n| n.created_at() == 42).build();
   1540             // test Arc
   1541             let _filter2 = filter.clone();
   1542             assert!(filter.matches(&note));
   1543         }
   1544 
   1545         {
   1546             let filter = Filter::new()
   1547                 .custom(|n| {
   1548                     n.tags()
   1549                         .into_iter()
   1550                         .next()
   1551                         .and_then(|t| t.get_str(1))
   1552                         .map_or(false, |s| s == "this is a comment")
   1553                 })
   1554                 .build();
   1555             assert!(filter.matches(&note));
   1556         }
   1557     }
   1558 }