nostrdb-rs

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

filter.rs (32754B)


      1 use crate::{bindings, Error, FilterError, Note, Result};
      2 use std::ffi::CString;
      3 use std::os::raw::c_char;
      4 use std::ptr::null_mut;
      5 use tracing::debug;
      6 
      7 #[derive(Debug)]
      8 pub struct FilterBuilder {
      9     pub data: bindings::ndb_filter,
     10 }
     11 
     12 #[derive(Debug)]
     13 pub struct Filter {
     14     pub data: bindings::ndb_filter,
     15 }
     16 
     17 impl Clone for Filter {
     18     fn clone(&self) -> Self {
     19         let mut new_filter: bindings::ndb_filter = Default::default();
     20         debug!("cloning filter");
     21         unsafe {
     22             bindings::ndb_filter_clone(
     23                 new_filter.as_mut_ptr(),
     24                 self.as_ptr() as *mut bindings::ndb_filter,
     25             );
     26         };
     27         Filter { data: new_filter }
     28     }
     29 }
     30 
     31 impl bindings::ndb_filter {
     32     fn as_ptr(&self) -> *const bindings::ndb_filter {
     33         self as *const bindings::ndb_filter
     34     }
     35 
     36     fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
     37         self as *mut bindings::ndb_filter
     38     }
     39 
     40     fn as_ref(&self) -> &bindings::ndb_filter {
     41         self
     42     }
     43 
     44     pub fn mut_iter(&self) -> MutFilterIter<'_> {
     45         MutFilterIter::new(self.as_ref())
     46     }
     47 
     48     pub fn field(&self, index: i32) -> Option<FilterField<'_>> {
     49         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
     50 
     51         if ptr.is_null() {
     52             return None;
     53         }
     54 
     55         Some(FilterElements::new(self, ptr).field())
     56     }
     57 
     58     pub fn field_mut(&self, index: i32) -> Option<MutFilterField<'_>> {
     59         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
     60 
     61         if ptr.is_null() {
     62             return None;
     63         }
     64 
     65         FilterElements::new(self, ptr).field_mut()
     66     }
     67 
     68     pub fn elements(&self, index: i32) -> Option<FilterElements<'_>> {
     69         let ptr = unsafe { bindings::ndb_filter_get_elements(self.as_ptr(), index) };
     70 
     71         if ptr.is_null() {
     72             return None;
     73         }
     74 
     75         Some(FilterElements::new(self, ptr))
     76     }
     77 }
     78 
     79 impl Default for bindings::ndb_filter {
     80     fn default() -> Self {
     81         let null = null_mut();
     82         let mut filter_data = bindings::ndb_filter {
     83             finalized: 0,
     84             elem_buf: bindings::cursor {
     85                 start: null,
     86                 p: null,
     87                 end: null,
     88             },
     89             data_buf: bindings::cursor {
     90                 start: null,
     91                 p: null,
     92                 end: null,
     93             },
     94             num_elements: 0,
     95             current: -1,
     96             elements: [0, 0, 0, 0, 0, 0, 0],
     97         };
     98 
     99         unsafe {
    100             bindings::ndb_filter_init(filter_data.as_mut_ptr());
    101         };
    102 
    103         filter_data
    104     }
    105 }
    106 
    107 impl Filter {
    108     #[allow(clippy::new_ret_no_self)]
    109     pub fn new() -> FilterBuilder {
    110         FilterBuilder {
    111             data: Default::default(),
    112         }
    113     }
    114 
    115     pub fn copy_from<'a, I>(filter: I) -> FilterBuilder
    116     where
    117         I: IntoIterator<Item = FilterField<'a>>,
    118     {
    119         let mut builder = Filter::new();
    120         for field in filter {
    121             match field {
    122                 FilterField::Ids(ids) => {
    123                     builder = builder.ids(ids);
    124                 }
    125                 FilterField::Authors(authors) => builder = builder.authors(authors),
    126                 FilterField::Kinds(kinds) => builder = builder.kinds(kinds),
    127                 FilterField::Tags(chr, tags) => {
    128                     builder.start_tags_field(chr).unwrap();
    129                     for field in tags {
    130                         match field {
    131                             FilterElement::Id(id) => builder.add_id_element(id).unwrap(),
    132                             FilterElement::Str(str_) => builder.add_str_element(str_).unwrap(),
    133                             FilterElement::Int(int) => builder.add_int_element(int).unwrap(),
    134                         }
    135                     }
    136                     builder.end_field();
    137                 }
    138                 FilterField::Since(n) => builder = builder.since(n),
    139                 FilterField::Until(n) => builder = builder.until(n),
    140                 FilterField::Limit(n) => builder = builder.limit(n),
    141             }
    142         }
    143         builder
    144     }
    145 
    146     pub fn from_json(json: &str) -> Result<Self> {
    147         Self::from_json_with_bufsize(json, 1024usize * 1024usize)
    148     }
    149 
    150     pub fn from_json_with_bufsize(json: &str, bufsize: usize) -> Result<Self> {
    151         let mut buf = Vec::with_capacity(bufsize);
    152         let mut filter = Filter::new();
    153         unsafe {
    154             let json_cstr = CString::new(json).expect("string to cstring conversion failed");
    155             let size = bindings::ndb_filter_from_json(
    156                 json_cstr.as_ptr(),
    157                 json.len() as i32,
    158                 filter.as_mut_ptr(),
    159                 buf.as_mut_ptr(),
    160                 bufsize as ::std::os::raw::c_int,
    161             ) as usize;
    162 
    163             // Step 4: Check the return value for success
    164             if size == 0 {
    165                 return Err(Error::BufferOverflow); // Handle the error appropriately
    166             }
    167 
    168             Ok(Filter { data: filter.data })
    169         }
    170     }
    171 
    172     pub fn to_ref(&self) -> &bindings::ndb_filter {
    173         &self.data
    174     }
    175 
    176     pub fn mut_iter(&self) -> MutFilterIter<'_> {
    177         self.data.mut_iter()
    178     }
    179 
    180     pub fn matches(&self, note: &Note) -> bool {
    181         unsafe {
    182             bindings::ndb_filter_matches(self.as_ptr() as *mut bindings::ndb_filter, note.as_ptr())
    183                 != 0
    184         }
    185     }
    186 
    187     pub fn num_elements(&self) -> i32 {
    188         unsafe { &*(self.as_ptr()) }.num_elements
    189     }
    190 
    191     pub fn limit_mut(self, limit: u64) -> Self {
    192         for field in self.mut_iter() {
    193             if let MutFilterField::Limit(val) = field {
    194                 *val = limit;
    195                 return self;
    196             }
    197         }
    198 
    199         Filter::copy_from(&self).limit(limit).build()
    200     }
    201 
    202     pub fn until_mut(self, until: u64) -> Self {
    203         for field in self.mut_iter() {
    204             if let MutFilterField::Until(val) = field {
    205                 *val = until;
    206                 return self;
    207             }
    208         }
    209 
    210         Filter::copy_from(&self).until(until).build()
    211     }
    212 
    213     pub fn since(&self) -> Option<u64> {
    214         for field in self {
    215             if let FilterField::Since(since) = field {
    216                 return Some(since);
    217             }
    218         }
    219 
    220         None
    221     }
    222 
    223     pub fn limit(&self) -> Option<u64> {
    224         for field in self {
    225             if let FilterField::Limit(limit) = field {
    226                 return Some(limit);
    227             }
    228         }
    229 
    230         None
    231     }
    232 
    233     pub fn until(&self) -> Option<u64> {
    234         for field in self {
    235             if let FilterField::Until(until) = field {
    236                 return Some(until);
    237             }
    238         }
    239 
    240         None
    241     }
    242 
    243     pub fn since_mut(self, since: u64) -> Self {
    244         for field in self.mut_iter() {
    245             if let MutFilterField::Since(val) = field {
    246                 *val = since;
    247                 return self;
    248             }
    249         }
    250 
    251         Filter::copy_from(&self).since(since).build()
    252     }
    253 
    254     pub fn as_ptr(&self) -> *const bindings::ndb_filter {
    255         self.data.as_ptr()
    256     }
    257 
    258     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
    259         self.data.as_mut_ptr()
    260     }
    261 
    262     pub fn json_with_bufsize(&self, bufsize: usize) -> Result<String> {
    263         let mut buf = Vec::with_capacity(bufsize);
    264         unsafe {
    265             let size = bindings::ndb_filter_json(
    266                 self.as_ptr(),
    267                 buf.as_mut_ptr() as *mut ::std::os::raw::c_char,
    268                 bufsize as ::std::os::raw::c_int,
    269             ) as usize;
    270 
    271             // Step 4: Check the return value for success
    272             if size == 0 {
    273                 return Err(Error::BufferOverflow); // Handle the error appropriately
    274             }
    275 
    276             buf.set_len(size);
    277 
    278             Ok(std::str::from_utf8_unchecked(&buf[..size - 1]).to_string())
    279         }
    280     }
    281 
    282     pub fn json(&self) -> Result<String> {
    283         // 1mb buffer
    284         self.json_with_bufsize(1024usize * 1024usize)
    285     }
    286 }
    287 
    288 impl Default for FilterBuilder {
    289     fn default() -> Self {
    290         FilterBuilder::new()
    291     }
    292 }
    293 
    294 impl FilterBuilder {
    295     pub fn new() -> FilterBuilder {
    296         Self {
    297             data: Default::default(),
    298         }
    299     }
    300 
    301     pub fn to_ref(&self) -> &bindings::ndb_filter {
    302         &self.data
    303     }
    304 
    305     pub fn mut_iter(&self) -> MutFilterIter<'_> {
    306         self.data.mut_iter()
    307     }
    308 
    309     pub fn as_ptr(&self) -> *const bindings::ndb_filter {
    310         self.data.as_ptr()
    311     }
    312 
    313     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_filter {
    314         self.data.as_mut_ptr()
    315     }
    316 
    317     pub fn add_int_element(&mut self, i: u64) -> Result<()> {
    318         let res = unsafe { bindings::ndb_filter_add_int_element(self.as_mut_ptr(), i) };
    319         if res == 0 {
    320             return Err(FilterError::already_exists());
    321         }
    322 
    323         Ok(())
    324     }
    325 
    326     pub fn add_str_element(&mut self, s: &str) -> Result<()> {
    327         let c_str = CString::new(s).expect("string to cstring conversion failed");
    328         let r = unsafe { bindings::ndb_filter_add_str_element(self.as_mut_ptr(), c_str.as_ptr()) };
    329 
    330         if r == 0 {
    331             return Err(FilterError::already_exists());
    332         }
    333 
    334         Ok(())
    335     }
    336 
    337     pub fn add_id_element(&mut self, id: &[u8; 32]) -> Result<()> {
    338         let ptr: *const ::std::os::raw::c_uchar = id.as_ptr() as *const ::std::os::raw::c_uchar;
    339         let r = unsafe { bindings::ndb_filter_add_id_element(self.as_mut_ptr(), ptr) };
    340 
    341         if r == 0 {
    342             return Err(FilterError::already_exists());
    343         }
    344 
    345         Ok(())
    346     }
    347 
    348     pub fn start_field(&mut self, field: bindings::ndb_filter_fieldtype) -> Result<()> {
    349         let r = unsafe { bindings::ndb_filter_start_field(self.as_mut_ptr(), field) };
    350 
    351         if r == 0 {
    352             return Err(FilterError::already_started());
    353         }
    354 
    355         Ok(())
    356     }
    357 
    358     pub fn start_tags_field(&mut self, tag: char) -> Result<()> {
    359         let r =
    360             unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
    361         if r == 0 {
    362             return Err(FilterError::already_started());
    363         }
    364         Ok(())
    365     }
    366 
    367     pub fn start_kinds_field(&mut self) -> Result<()> {
    368         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_KINDS)
    369     }
    370 
    371     pub fn start_authors_field(&mut self) -> Result<()> {
    372         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_AUTHORS)
    373     }
    374 
    375     pub fn start_since_field(&mut self) -> Result<()> {
    376         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_SINCE)
    377     }
    378 
    379     pub fn start_until_field(&mut self) -> Result<()> {
    380         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_UNTIL)
    381     }
    382 
    383     pub fn start_limit_field(&mut self) -> Result<()> {
    384         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_LIMIT)
    385     }
    386 
    387     pub fn start_ids_field(&mut self) -> Result<()> {
    388         self.start_field(bindings::ndb_filter_fieldtype_NDB_FILTER_IDS)
    389     }
    390 
    391     #[allow(dead_code)]
    392     pub fn start_events_field(&mut self) -> Result<()> {
    393         self.start_tags_field('e')
    394     }
    395 
    396     pub fn start_pubkeys_field(&mut self) -> Result<()> {
    397         self.start_tags_field('p')
    398     }
    399 
    400     pub fn start_tag_field(&mut self, tag: char) -> Result<()> {
    401         let r =
    402             unsafe { bindings::ndb_filter_start_tag_field(self.as_mut_ptr(), tag as u8 as c_char) };
    403         if r == 0 {
    404             return Err(FilterError::FieldAlreadyStarted.into());
    405         }
    406         Ok(())
    407     }
    408 
    409     pub fn end_field(&mut self) {
    410         unsafe {
    411             bindings::ndb_filter_end_field(self.as_mut_ptr());
    412         };
    413     }
    414 
    415     pub fn events<'a, I>(mut self, events: I) -> Self
    416     where
    417         I: IntoIterator<Item = &'a [u8; 32]>,
    418     {
    419         self.start_tag_field('e').unwrap();
    420         for id in events {
    421             self.add_id_element(id).unwrap();
    422         }
    423         self.end_field();
    424         self
    425     }
    426 
    427     pub fn event(mut self, id: &[u8; 32]) -> Self {
    428         self.start_tag_field('e').unwrap();
    429         self.add_id_element(id).unwrap();
    430         self.end_field();
    431         self
    432     }
    433 
    434     pub fn ids<'a, I>(mut self, ids: I) -> Self
    435     where
    436         I: IntoIterator<Item = &'a [u8; 32]>,
    437     {
    438         self.start_ids_field().unwrap();
    439         for id in ids {
    440             self.add_id_element(id).unwrap();
    441         }
    442         self.end_field();
    443         self
    444     }
    445 
    446     pub fn pubkeys<'a, I>(mut self, pubkeys: I) -> Self
    447     where
    448         I: IntoIterator<Item = &'a [u8; 32]>,
    449     {
    450         self.start_tag_field('p').unwrap();
    451         for pk in pubkeys {
    452             self.add_id_element(pk).unwrap();
    453         }
    454         self.end_field();
    455         self
    456     }
    457 
    458     pub fn authors<'a, I>(mut self, authors: I) -> Self
    459     where
    460         I: IntoIterator<Item = &'a [u8; 32]>,
    461     {
    462         self.start_authors_field().unwrap();
    463         for author in authors {
    464             self.add_id_element(author).unwrap();
    465         }
    466         self.end_field();
    467         self
    468     }
    469 
    470     pub fn kinds<I>(mut self, kinds: I) -> Self
    471     where
    472         I: IntoIterator<Item = u64>,
    473     {
    474         self.start_kinds_field().unwrap();
    475         for kind in kinds {
    476             self.add_int_element(kind).unwrap();
    477         }
    478         self.end_field();
    479         self
    480     }
    481 
    482     pub fn pubkey<'a, I>(mut self, pubkeys: I) -> Self
    483     where
    484         I: IntoIterator<Item = &'a [u8; 32]>,
    485     {
    486         self.start_pubkeys_field().unwrap();
    487         for pubkey in pubkeys {
    488             self.add_id_element(pubkey).unwrap();
    489         }
    490         self.end_field();
    491         self
    492     }
    493 
    494     pub fn tags<I>(mut self, tags: I, tag: char) -> Self
    495     where
    496         I: IntoIterator<Item = String>,
    497     {
    498         self.start_tag_field(tag).unwrap();
    499         for tag in tags {
    500             self.add_str_element(&tag).unwrap();
    501         }
    502         self.end_field();
    503         self
    504     }
    505 
    506     pub fn since(mut self, since: u64) -> Self {
    507         for field in self.mut_iter() {
    508             if let MutFilterField::Since(val) = field {
    509                 *val = since;
    510                 return self;
    511             }
    512         }
    513 
    514         self.start_since_field().unwrap();
    515         self.add_int_element(since).unwrap();
    516         self.end_field();
    517         self
    518     }
    519 
    520     pub fn until(mut self, until: u64) -> Self {
    521         for field in self.mut_iter() {
    522             if let MutFilterField::Until(val) = field {
    523                 *val = until;
    524                 return self;
    525             }
    526         }
    527 
    528         self.start_until_field().unwrap();
    529         self.add_int_element(until).unwrap();
    530         self.end_field();
    531         self
    532     }
    533 
    534     pub fn limit(mut self, limit: u64) -> Self {
    535         for field in self.mut_iter() {
    536             if let MutFilterField::Limit(val) = field {
    537                 *val = limit;
    538                 return self;
    539             }
    540         }
    541 
    542         self.start_limit_field().unwrap();
    543         self.add_int_element(limit).unwrap();
    544         self.end_field();
    545         self
    546     }
    547 
    548     pub fn build(&mut self) -> Filter {
    549         unsafe {
    550             bindings::ndb_filter_end(self.as_mut_ptr());
    551         };
    552         Filter { data: self.data }
    553     }
    554 }
    555 
    556 impl Drop for Filter {
    557     fn drop(&mut self) {
    558         debug!("dropping filter {:?}", self);
    559         unsafe { bindings::ndb_filter_destroy(self.as_mut_ptr()) };
    560     }
    561 }
    562 
    563 #[derive(Debug, Copy, Clone)]
    564 pub struct MutFilterIter<'a> {
    565     filter: &'a bindings::ndb_filter,
    566     index: i32,
    567 }
    568 
    569 impl<'a> MutFilterIter<'a> {
    570     pub(crate) fn new(filter: &'a bindings::ndb_filter) -> Self {
    571         let index = 0;
    572         MutFilterIter { filter, index }
    573     }
    574 
    575     pub fn done(&self) -> bool {
    576         self.index >= self.filter.num_elements
    577     }
    578 }
    579 
    580 #[derive(Debug, Copy, Clone)]
    581 pub struct FilterIter<'a> {
    582     filter: &'a bindings::ndb_filter,
    583     index: i32,
    584 }
    585 
    586 /// Filter element: `authors`, `limit`, etc
    587 #[derive(Copy, Clone, Debug)]
    588 pub struct FilterElements<'a> {
    589     filter: &'a bindings::ndb_filter,
    590     elements: *mut bindings::ndb_filter_elements,
    591 }
    592 
    593 #[derive(Copy, Clone, Debug)]
    594 pub struct FilterIdElements<'a> {
    595     filter: &'a bindings::ndb_filter,
    596     elements: *mut bindings::ndb_filter_elements,
    597 }
    598 
    599 #[derive(Copy, Clone, Debug)]
    600 pub struct FilterIntElements<'a> {
    601     _filter: &'a bindings::ndb_filter,
    602     elements: *mut bindings::ndb_filter_elements,
    603 }
    604 
    605 pub struct FilterIdElemIter<'a> {
    606     ids: FilterIdElements<'a>,
    607     index: i32,
    608 }
    609 
    610 pub struct FilterIntElemIter<'a> {
    611     ints: FilterIntElements<'a>,
    612     index: i32,
    613 }
    614 
    615 impl<'a> FilterIdElemIter<'a> {
    616     pub(crate) fn new(ids: FilterIdElements<'a>) -> Self {
    617         let index = 0;
    618         Self { ids, index }
    619     }
    620 
    621     pub fn done(&self) -> bool {
    622         self.index >= self.ids.count()
    623     }
    624 }
    625 
    626 impl<'a> FilterIntElemIter<'a> {
    627     pub(crate) fn new(ints: FilterIntElements<'a>) -> Self {
    628         let index = 0;
    629         Self { ints, index }
    630     }
    631 
    632     pub fn done(&self) -> bool {
    633         self.index >= self.ints.count()
    634     }
    635 }
    636 
    637 impl<'a> FilterIdElements<'a> {
    638     pub(crate) fn new(
    639         filter: &'a bindings::ndb_filter,
    640         elements: *mut bindings::ndb_filter_elements,
    641     ) -> Self {
    642         Self { filter, elements }
    643     }
    644 
    645     pub fn count(&self) -> i32 {
    646         unsafe { &*self.elements }.count
    647     }
    648 
    649     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    650     fn elemtype(&self) -> FieldElemType {
    651         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    652             .expect("expected valid filter element type")
    653     }
    654 
    655     pub fn get(self, index: i32) -> Option<&'a [u8; 32]> {
    656         assert!(self.elemtype() == FieldElemType::Id);
    657 
    658         let id = unsafe {
    659             bindings::ndb_filter_get_id_element(self.filter.as_ptr(), self.elements, index)
    660                 as *const [u8; 32]
    661         };
    662 
    663         if id.is_null() {
    664             return None;
    665         }
    666 
    667         Some(unsafe { &*id })
    668     }
    669 }
    670 
    671 impl<'a> FilterIntElements<'a> {
    672     pub(crate) fn new(
    673         filter: &'a bindings::ndb_filter,
    674         elements: *mut bindings::ndb_filter_elements,
    675     ) -> Self {
    676         Self {
    677             _filter: filter,
    678             elements,
    679         }
    680     }
    681 
    682     pub fn count(&self) -> i32 {
    683         unsafe { &*self.elements }.count
    684     }
    685 
    686     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    687     fn elemtype(&self) -> FieldElemType {
    688         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    689             .expect("expected valid filter element type")
    690     }
    691 
    692     pub fn get(self, index: i32) -> Option<u64> {
    693         if index >= self.count() {
    694             return None;
    695         }
    696         assert!(self.elemtype() == FieldElemType::Int);
    697         Some(unsafe { bindings::ndb_filter_get_int_element(self.elements, index) })
    698     }
    699 }
    700 
    701 pub enum FilterField<'a> {
    702     Ids(FilterIdElements<'a>),
    703     Authors(FilterIdElements<'a>),
    704     Kinds(FilterIntElements<'a>),
    705     Tags(char, FilterElements<'a>),
    706     Since(u64),
    707     Until(u64),
    708     Limit(u64),
    709 }
    710 
    711 pub enum MutFilterField<'a> {
    712     Since(&'a mut u64),
    713     Until(&'a mut u64),
    714     Limit(&'a mut u64),
    715 }
    716 
    717 impl<'a> FilterField<'a> {
    718     pub fn new(elements: FilterElements<'a>) -> Self {
    719         match elements.fieldtype() {
    720             FilterFieldType::Ids => {
    721                 FilterField::Ids(FilterIdElements::new(elements.filter(), elements.as_ptr()))
    722             }
    723 
    724             FilterFieldType::Authors => {
    725                 FilterField::Authors(FilterIdElements::new(elements.filter(), elements.as_ptr()))
    726             }
    727 
    728             FilterFieldType::Kinds => {
    729                 FilterField::Kinds(FilterIntElements::new(elements.filter(), elements.as_ptr()))
    730             }
    731 
    732             FilterFieldType::Tags => FilterField::Tags(elements.tag(), elements),
    733 
    734             FilterFieldType::Since => FilterField::Since(
    735                 FilterIntElements::new(elements.filter(), elements.as_ptr())
    736                     .into_iter()
    737                     .next()
    738                     .expect("expected since in filter"),
    739             ),
    740 
    741             FilterFieldType::Until => FilterField::Until(
    742                 FilterIntElements::new(elements.filter(), elements.as_ptr())
    743                     .into_iter()
    744                     .next()
    745                     .expect("expected until in filter"),
    746             ),
    747 
    748             FilterFieldType::Limit => FilterField::Limit(
    749                 FilterIntElements::new(elements.filter(), elements.as_ptr())
    750                     .into_iter()
    751                     .next()
    752                     .expect("expected limit in filter"),
    753             ),
    754         }
    755     }
    756 }
    757 
    758 impl<'a> FilterElements<'a> {
    759     pub(crate) fn new(
    760         filter: &'a bindings::ndb_filter,
    761         elements: *mut bindings::ndb_filter_elements,
    762     ) -> Self {
    763         FilterElements { filter, elements }
    764     }
    765 
    766     pub fn filter(self) -> &'a bindings::ndb_filter {
    767         self.filter
    768     }
    769 
    770     pub fn as_ptr(self) -> *mut bindings::ndb_filter_elements {
    771         self.elements
    772     }
    773 
    774     pub fn count(&self) -> i32 {
    775         unsafe { &*self.elements }.count
    776     }
    777 
    778     pub fn field(self) -> FilterField<'a> {
    779         FilterField::new(self)
    780     }
    781 
    782     /// Mutably access since, until, limit. We can probably do others in
    783     /// the future, but this is the most useful at the moment
    784     pub fn field_mut(self) -> Option<MutFilterField<'a>> {
    785         if self.count() != 1 {
    786             return None;
    787         }
    788 
    789         if self.elemtype() != FieldElemType::Int {
    790             return None;
    791         }
    792 
    793         match self.fieldtype() {
    794             FilterFieldType::Since => Some(MutFilterField::Since(self.get_mut_int(0))),
    795             FilterFieldType::Until => Some(MutFilterField::Until(self.get_mut_int(0))),
    796             FilterFieldType::Limit => Some(MutFilterField::Limit(self.get_mut_int(0))),
    797             _ => None,
    798         }
    799     }
    800 
    801     pub fn get_mut_int(&self, index: i32) -> &'a mut u64 {
    802         unsafe { &mut *bindings::ndb_filter_get_int_element_ptr(self.elements, index) }
    803     }
    804 
    805     pub fn get(self, index: i32) -> Option<FilterElement<'a>> {
    806         if index >= self.count() {
    807             return None;
    808         }
    809 
    810         match self.elemtype() {
    811             FieldElemType::Id => {
    812                 let id = unsafe {
    813                     bindings::ndb_filter_get_id_element(self.filter.as_ptr(), self.elements, index)
    814                         as *const [u8; 32]
    815                 };
    816                 if id.is_null() {
    817                     return None;
    818                 }
    819                 Some(FilterElement::Id(unsafe { &*id }))
    820             }
    821 
    822             FieldElemType::Str => {
    823                 let cstr = unsafe {
    824                     bindings::ndb_filter_get_string_element(
    825                         self.filter.as_ptr(),
    826                         self.elements,
    827                         index,
    828                     )
    829                 };
    830                 if cstr.is_null() {
    831                     return None;
    832                 }
    833                 let str = unsafe {
    834                     let byte_slice =
    835                         std::slice::from_raw_parts(cstr as *const u8, libc::strlen(cstr));
    836                     std::str::from_utf8_unchecked(byte_slice)
    837                 };
    838                 Some(FilterElement::Str(str))
    839             }
    840 
    841             FieldElemType::Int => {
    842                 let num = unsafe { bindings::ndb_filter_get_int_element(self.elements, index) };
    843                 Some(FilterElement::Int(num))
    844             }
    845         }
    846     }
    847 
    848     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    849     pub fn elemtype(&self) -> FieldElemType {
    850         FieldElemType::new(unsafe { &*self.elements }.field.elem_type)
    851             .expect("expected valid filter element type")
    852     }
    853 
    854     /// Field element type. In the case of ids, it would be FieldElemType::Id, etc
    855     pub fn tag(&self) -> char {
    856         (unsafe { &*self.elements }.field.tag as u8) as char
    857     }
    858 
    859     pub fn fieldtype(self) -> FilterFieldType {
    860         FilterFieldType::new(unsafe { &*self.elements }.field.type_)
    861             .expect("expected valid fieldtype")
    862     }
    863 }
    864 
    865 impl<'a> FilterIter<'a> {
    866     pub fn new(filter: &'a bindings::ndb_filter) -> Self {
    867         let index = 0;
    868         FilterIter { filter, index }
    869     }
    870 
    871     pub fn done(&self) -> bool {
    872         self.index >= self.filter.num_elements
    873     }
    874 }
    875 
    876 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    877 pub enum FilterFieldType {
    878     Ids,
    879     Authors,
    880     Kinds,
    881     Tags,
    882     Since,
    883     Until,
    884     Limit,
    885 }
    886 
    887 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    888 pub enum FieldElemType {
    889     Str,
    890     Id,
    891     Int,
    892 }
    893 
    894 impl FieldElemType {
    895     pub(crate) fn new(val: bindings::ndb_generic_element_type) -> Option<Self> {
    896         if val == bindings::ndb_generic_element_type_NDB_ELEMENT_UNKNOWN {
    897             None
    898         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_STRING {
    899             Some(FieldElemType::Str)
    900         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_ID {
    901             Some(FieldElemType::Id)
    902         } else if val == bindings::ndb_generic_element_type_NDB_ELEMENT_INT {
    903             Some(FieldElemType::Int)
    904         } else {
    905             None
    906         }
    907     }
    908 }
    909 
    910 impl FilterFieldType {
    911     pub(crate) fn new(val: bindings::ndb_filter_fieldtype) -> Option<Self> {
    912         if val == bindings::ndb_filter_fieldtype_NDB_FILTER_IDS {
    913             Some(FilterFieldType::Ids)
    914         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_AUTHORS {
    915             Some(FilterFieldType::Authors)
    916         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_KINDS {
    917             Some(FilterFieldType::Kinds)
    918         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_TAGS {
    919             Some(FilterFieldType::Tags)
    920         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_SINCE {
    921             Some(FilterFieldType::Since)
    922         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_UNTIL {
    923             Some(FilterFieldType::Until)
    924         } else if val == bindings::ndb_filter_fieldtype_NDB_FILTER_LIMIT {
    925             Some(FilterFieldType::Limit)
    926         } else {
    927             None
    928         }
    929     }
    930 }
    931 
    932 impl<'a> IntoIterator for &'a Filter {
    933     type Item = FilterField<'a>;
    934     type IntoIter = FilterIter<'a>;
    935 
    936     fn into_iter(self) -> Self::IntoIter {
    937         FilterIter::new(self.to_ref())
    938     }
    939 }
    940 
    941 impl<'a> IntoIterator for &'a FilterBuilder {
    942     type Item = FilterField<'a>;
    943     type IntoIter = FilterIter<'a>;
    944 
    945     fn into_iter(self) -> Self::IntoIter {
    946         FilterIter::new(self.to_ref())
    947     }
    948 }
    949 
    950 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    951 pub enum FilterElement<'a> {
    952     Str(&'a str),
    953     Id(&'a [u8; 32]),
    954     Int(u64),
    955 }
    956 
    957 impl<'a> Iterator for FilterIter<'a> {
    958     type Item = FilterField<'a>;
    959 
    960     fn next(&mut self) -> Option<FilterField<'a>> {
    961         if self.done() {
    962             return None;
    963         }
    964 
    965         let ind = self.index;
    966         self.index += 1;
    967 
    968         self.filter.field(ind)
    969     }
    970 }
    971 
    972 impl<'a> Iterator for MutFilterIter<'a> {
    973     type Item = MutFilterField<'a>;
    974 
    975     fn next(&mut self) -> Option<MutFilterField<'a>> {
    976         if self.done() {
    977             return None;
    978         }
    979 
    980         while !self.done() {
    981             let mnext = self.filter.field_mut(self.index);
    982             self.index += 1;
    983 
    984             if mnext.is_some() {
    985                 return mnext;
    986             }
    987         }
    988 
    989         None
    990     }
    991 }
    992 
    993 impl<'a> IntoIterator for FilterIdElements<'a> {
    994     type Item = &'a [u8; 32];
    995     type IntoIter = FilterIdElemIter<'a>;
    996 
    997     fn into_iter(self) -> Self::IntoIter {
    998         FilterIdElemIter::new(self)
    999     }
   1000 }
   1001 
   1002 impl<'a> IntoIterator for FilterIntElements<'a> {
   1003     type Item = u64;
   1004     type IntoIter = FilterIntElemIter<'a>;
   1005 
   1006     fn into_iter(self) -> Self::IntoIter {
   1007         FilterIntElemIter::new(self)
   1008     }
   1009 }
   1010 
   1011 impl Iterator for FilterIntElemIter<'_> {
   1012     type Item = u64;
   1013 
   1014     fn next(&mut self) -> Option<u64> {
   1015         if self.done() {
   1016             return None;
   1017         }
   1018 
   1019         let ind = self.index;
   1020         self.index += 1;
   1021 
   1022         self.ints.get(ind)
   1023     }
   1024 }
   1025 
   1026 impl<'a> Iterator for FilterIdElemIter<'a> {
   1027     type Item = &'a [u8; 32];
   1028 
   1029     fn next(&mut self) -> Option<&'a [u8; 32]> {
   1030         if self.done() {
   1031             return None;
   1032         }
   1033 
   1034         let ind = self.index;
   1035         self.index += 1;
   1036 
   1037         self.ids.get(ind)
   1038     }
   1039 }
   1040 
   1041 impl<'a> IntoIterator for FilterElements<'a> {
   1042     type Item = FilterElement<'a>;
   1043     type IntoIter = FilterElemIter<'a>;
   1044 
   1045     fn into_iter(self) -> Self::IntoIter {
   1046         FilterElemIter::new(self)
   1047     }
   1048 }
   1049 
   1050 impl<'a> Iterator for FilterElemIter<'a> {
   1051     type Item = FilterElement<'a>;
   1052 
   1053     fn next(&mut self) -> Option<FilterElement<'a>> {
   1054         let element = self.elements.get(self.index);
   1055         if element.is_some() {
   1056             self.index += 1;
   1057             element
   1058         } else {
   1059             None
   1060         }
   1061     }
   1062 }
   1063 
   1064 #[derive(Copy, Clone, Debug)]
   1065 pub struct FilterElemIter<'a> {
   1066     elements: FilterElements<'a>,
   1067     index: i32,
   1068 }
   1069 
   1070 impl<'a> FilterElemIter<'a> {
   1071     pub(crate) fn new(elements: FilterElements<'a>) -> Self {
   1072         let index = 0;
   1073         FilterElemIter { elements, index }
   1074     }
   1075 }
   1076 
   1077 #[cfg(test)]
   1078 mod tests {
   1079     use super::*;
   1080 
   1081     #[test]
   1082     fn filter_limit_iter_works() {
   1083         let filter = Filter::new().limit(42).build();
   1084         let mut hit = 0;
   1085         for element in &filter {
   1086             if let FilterField::Limit(42) = element {
   1087                 hit += 1;
   1088             }
   1089         }
   1090         assert!(hit == 1);
   1091     }
   1092 
   1093     #[test]
   1094     fn filter_quick_since_mut_works() {
   1095         let id: [u8; 32] = [
   1096             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1097             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1098             0xe8, 0x5b, 0xa8, 0x59,
   1099         ];
   1100 
   1101         let mut hit = 0;
   1102         let mut filter = Filter::new().ids([&id, &id, &id]).build();
   1103 
   1104         // mutate
   1105         filter = filter.since_mut(3);
   1106 
   1107         for element in &filter {
   1108             if let FilterField::Since(s) = element {
   1109                 hit += 1;
   1110                 assert_eq!(s, 3);
   1111             }
   1112         }
   1113         assert!(hit == 1);
   1114     }
   1115 
   1116     #[test]
   1117     fn filter_since_mut_works() {
   1118         let id: [u8; 32] = [
   1119             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1120             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1121             0xe8, 0x5b, 0xa8, 0x59,
   1122         ];
   1123 
   1124         let mut hit = 0;
   1125         let filter = Filter::new().ids([&id, &id, &id]).since(1);
   1126 
   1127         for element in filter.mut_iter() {
   1128             if let MutFilterField::Since(since_ref) = element {
   1129                 hit += 1;
   1130                 assert_eq!(*since_ref, 1);
   1131                 *since_ref = 2;
   1132             }
   1133         }
   1134         for element in &filter {
   1135             if let FilterField::Since(s) = element {
   1136                 hit += 1;
   1137                 assert_eq!(s, 2);
   1138             }
   1139         }
   1140         assert!(hit == 2);
   1141     }
   1142 
   1143     #[test]
   1144     fn filter_id_iter_works() {
   1145         let id: [u8; 32] = [
   1146             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1147             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1148             0xe8, 0x5b, 0xa8, 0x59,
   1149         ];
   1150 
   1151         let filter = Filter::new().ids([&id, &id, &id]).build();
   1152         let mut hit = 0;
   1153         for element in &filter {
   1154             if let FilterField::Ids(ids) = element {
   1155                 for same_id in ids {
   1156                     hit += 1;
   1157                     assert!(same_id == &id);
   1158                 }
   1159             }
   1160         }
   1161         assert!(hit == 3);
   1162     }
   1163 
   1164     #[test]
   1165     fn filter_int_iter_works() {
   1166         let filter = Filter::new().kinds(vec![1, 2, 3]).build();
   1167         let mut hit = 0;
   1168         for element in &filter {
   1169             if let FilterField::Kinds(ks) = element {
   1170                 hit += 1;
   1171                 assert!(vec![1, 2, 3] == ks.into_iter().collect::<Vec<u64>>());
   1172             }
   1173         }
   1174         assert!(hit == 1);
   1175     }
   1176 
   1177     #[test]
   1178     fn filter_multiple_field_iter_works() {
   1179         let id: [u8; 32] = [
   1180             0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
   1181             0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
   1182             0xe8, 0x5b, 0xa8, 0x59,
   1183         ];
   1184         let filter = Filter::new().event(&id).kinds(vec![1, 2, 3]).build();
   1185         let mut hit = 0;
   1186         for element in &filter {
   1187             if let FilterField::Kinds(ks) = element {
   1188                 hit += 1;
   1189                 assert!(vec![1, 2, 3] == ks.into_iter().collect::<Vec<u64>>());
   1190             } else if let FilterField::Tags('e', ids) = element {
   1191                 for i in ids {
   1192                     hit += 1;
   1193                     assert!(i == FilterElement::Id(&id));
   1194                 }
   1195             }
   1196         }
   1197         assert!(hit == 2);
   1198     }
   1199 }