Skip to content

Commit

Permalink
expose filter subset optimization function
Browse files Browse the repository at this point in the history
We added this to nostrdb, so lets expose it to rust now

Signed-off-by: William Casarin <[email protected]>
  • Loading branch information
jb55 committed Nov 3, 2024
1 parent 9bbafd8 commit b88d5c7
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 5 deletions.
6 changes: 3 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ fn main() {
println!("cargo:rustc-link-lib=static=nostrdb");

// Link Security framework on macOS
//if cfg!(target_os = "macos") {
//println!("cargo:rustc-link-lib=framework=Security");
//}
if cfg!(target_os = "macos") {
println!("cargo:rustc-link-lib=framework=Security");
}

//
// We only need bindgen when we update the bindings.
Expand Down
2 changes: 1 addition & 1 deletion nostrdb
Submodule nostrdb updated 3 files
+147 −9 src/nostrdb.c
+8 −0 src/nostrdb.h
+64 −0 test.c
31 changes: 30 additions & 1 deletion src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ pub const __MAC_14_3: u32 = 140300;
pub const __MAC_14_4: u32 = 140400;
pub const __MAC_14_5: u32 = 140500;
pub const __MAC_15_0: u32 = 150000;
pub const __MAC_15_1: u32 = 150100;
pub const __IPHONE_2_0: u32 = 20000;
pub const __IPHONE_2_1: u32 = 20100;
pub const __IPHONE_2_2: u32 = 20200;
Expand Down Expand Up @@ -359,6 +360,7 @@ pub const __IPHONE_17_3: u32 = 170300;
pub const __IPHONE_17_4: u32 = 170400;
pub const __IPHONE_17_5: u32 = 170500;
pub const __IPHONE_18_0: u32 = 180000;
pub const __IPHONE_18_1: u32 = 180100;
pub const __WATCHOS_1_0: u32 = 10000;
pub const __WATCHOS_2_0: u32 = 20000;
pub const __WATCHOS_2_1: u32 = 20100;
Expand Down Expand Up @@ -407,6 +409,7 @@ pub const __WATCHOS_10_3: u32 = 100300;
pub const __WATCHOS_10_4: u32 = 100400;
pub const __WATCHOS_10_5: u32 = 100500;
pub const __WATCHOS_11_0: u32 = 110000;
pub const __WATCHOS_11_1: u32 = 110100;
pub const __TVOS_9_0: u32 = 90000;
pub const __TVOS_9_1: u32 = 90100;
pub const __TVOS_9_2: u32 = 90200;
Expand Down Expand Up @@ -456,6 +459,7 @@ pub const __TVOS_17_3: u32 = 170300;
pub const __TVOS_17_4: u32 = 170400;
pub const __TVOS_17_5: u32 = 170500;
pub const __TVOS_18_0: u32 = 180000;
pub const __TVOS_18_1: u32 = 180100;
pub const __BRIDGEOS_2_0: u32 = 20000;
pub const __BRIDGEOS_3_0: u32 = 30000;
pub const __BRIDGEOS_3_1: u32 = 30100;
Expand Down Expand Up @@ -483,6 +487,7 @@ pub const __BRIDGEOS_8_3: u32 = 80300;
pub const __BRIDGEOS_8_4: u32 = 80400;
pub const __BRIDGEOS_8_5: u32 = 80500;
pub const __BRIDGEOS_9_0: u32 = 90000;
pub const __BRIDGEOS_9_1: u32 = 90100;
pub const __DRIVERKIT_19_0: u32 = 190000;
pub const __DRIVERKIT_20_0: u32 = 200000;
pub const __DRIVERKIT_21_0: u32 = 210000;
Expand All @@ -497,10 +502,12 @@ pub const __DRIVERKIT_23_3: u32 = 230300;
pub const __DRIVERKIT_23_4: u32 = 230400;
pub const __DRIVERKIT_23_5: u32 = 230500;
pub const __DRIVERKIT_24_0: u32 = 240000;
pub const __DRIVERKIT_24_1: u32 = 240100;
pub const __VISIONOS_1_0: u32 = 10000;
pub const __VISIONOS_1_1: u32 = 10100;
pub const __VISIONOS_1_2: u32 = 10200;
pub const __VISIONOS_2_0: u32 = 20000;
pub const __VISIONOS_2_1: u32 = 20100;
pub const MAC_OS_X_VERSION_10_0: u32 = 1000;
pub const MAC_OS_X_VERSION_10_1: u32 = 1010;
pub const MAC_OS_X_VERSION_10_2: u32 = 1020;
Expand Down Expand Up @@ -563,8 +570,10 @@ pub const MAC_OS_VERSION_14_3: u32 = 140300;
pub const MAC_OS_VERSION_14_4: u32 = 140400;
pub const MAC_OS_VERSION_14_5: u32 = 140500;
pub const MAC_OS_VERSION_15_0: u32 = 150000;
pub const __MAC_OS_X_VERSION_MAX_ALLOWED: u32 = 150000;
pub const MAC_OS_VERSION_15_1: u32 = 150100;
pub const __MAC_OS_X_VERSION_MAX_ALLOWED: u32 = 150100;
pub const __ENABLE_LEGACY_MAC_AVAILABILITY: u32 = 1;
pub const USE_CLANG_TYPES: u32 = 0;
pub const __PTHREAD_SIZE__: u32 = 8176;
pub const __PTHREAD_ATTR_SIZE__: u32 = 56;
pub const __PTHREAD_MUTEXATTR_SIZE__: u32 = 8;
Expand All @@ -576,6 +585,7 @@ pub const __PTHREAD_RWLOCK_SIZE__: u32 = 192;
pub const __PTHREAD_RWLOCKATTR_SIZE__: u32 = 16;
pub const __DARWIN_WCHAR_MIN: i32 = -2147483648;
pub const _FORTIFY_SOURCE: u32 = 2;
pub const USE_CLANG_STDDEF: u32 = 0;
pub const __WORDSIZE: u32 = 64;
pub const INT8_MAX: u32 = 127;
pub const INT16_MAX: u32 = 32767;
Expand Down Expand Up @@ -635,6 +645,7 @@ pub const HAVE_LITTLE_ENDIAN: u32 = 1;
pub const __bool_true_false_are_defined: u32 = 1;
pub const true_: u32 = 1;
pub const false_: u32 = 0;
pub const USE_CLANG_STDARG: u32 = 0;
pub const RENAME_SECLUDE: u32 = 1;
pub const RENAME_SWAP: u32 = 2;
pub const RENAME_EXCL: u32 = 4;
Expand Down Expand Up @@ -5760,6 +5771,17 @@ extern "C" {
str_: *const ::std::os::raw::c_char,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn ndb_filter_eq(arg1: *const ndb_filter, arg2: *const ndb_filter)
-> ::std::os::raw::c_int;
}
extern "C" {
#[doc = " is `a` a subset of `b`"]
pub fn ndb_filter_is_subset_of(
a: *const ndb_filter,
b: *const ndb_filter,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn ndb_filter_from_json(
arg1: *const ::std::os::raw::c_char,
Expand Down Expand Up @@ -5867,6 +5889,13 @@ extern "C" {
extern "C" {
pub fn ndb_num_subscriptions(arg1: *mut ndb) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn ndb_subscription_filters(
arg1: *mut ndb,
subid: u64,
filters: *mut ::std::os::raw::c_int,
) -> *mut ndb_filter;
}
extern "C" {
pub fn ndb_text_search(
txn: *mut ndb_txn,
Expand Down
65 changes: 65 additions & 0 deletions src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ pub struct Filter {
pub data: bindings::ndb_filter,
}

impl PartialEq for Filter {
fn eq(&self, other: &Filter) -> bool {
unsafe {
bindings::ndb_filter_eq(self.as_ptr(), other.as_ptr()) == 1
}
}
}

impl Clone for Filter {
fn clone(&self) -> Self {
let mut new_filter: bindings::ndb_filter = Default::default();
Expand Down Expand Up @@ -112,6 +120,40 @@ impl Filter {
}
}

/// Given a set of filters, filter redundant ones. This is done by
/// finding all the filters that are subsets of every other filter. If
/// a filter is known to be a subset of another, it is removed.
pub fn optimize(filters: &[Filter]) -> Vec<Filter> {
let mut is_subset: Vec<bool> = vec![false; filters.len()];

for (i1, f1) in filters.iter().enumerate() {
for (i2, f2) in filters.iter().enumerate() {
// we don't want to count ourselves
if i1 == i2 {
continue;
}

if f2.is_subset_of(f1) {
is_subset[i2] = true;
}
}
}

filters
.iter()
.enumerate()
.filter(|(i, _f)| !is_subset[*i])
.map(|(_i, f)| f.clone())
.collect()
}

/// Is this filter a subset of another
pub fn is_subset_of(&self, b: &Filter) -> bool {
unsafe {
bindings::ndb_filter_is_subset_of(self.as_ptr(), b.as_ptr()) == 1
}
}

pub fn copy_from<'a, I>(filter: I) -> FilterBuilder
where
I: IntoIterator<Item = FilterField<'a>>,
Expand Down Expand Up @@ -1078,6 +1120,29 @@ impl<'a> FilterElemIter<'a> {
mod tests {
use super::*;

#[test]
fn filter_test_subset_optimize() {
let id: [u8; 32] = [
0xfb, 0x16, 0x5b, 0xe2, 0x2c, 0x7b, 0x25, 0x18, 0xb7, 0x49, 0xaa, 0xbb, 0x71, 0x40,
0xc7, 0x3f, 0x08, 0x87, 0xfe, 0x84, 0x47, 0x5c, 0x82, 0x78, 0x57, 0x00, 0x66, 0x3b,
0xe8, 0x5b, 0xa8, 0x59,
];
let expected = [
Filter::new().kinds(vec![1]).build(),
Filter::new().kinds(vec![2]).build(),
];

let filters = [
Filter::new().kinds(vec![1]).build(),
Filter::new().kinds(vec![2]).build(),
Filter::new().kinds(vec![1]).authors(vec![&id]).build(),
Filter::new().kinds(vec![2]).authors(vec![&id]).build(),
];

let output = Filter::optimize(&filters);
assert_eq!(output, expected);
}

#[test]
fn filter_limit_iter_works() {
let filter = Filter::new().limit(42).build();
Expand Down

0 comments on commit b88d5c7

Please sign in to comment.