Skip to content

feat(bloom): introduce BloomFilterInvertedView for inverted queries - #271

Open
v0id-X wants to merge 4 commits into
apache:mainfrom
v0id-X:feat/bloom-filter-inverted-view
Open

feat(bloom): introduce BloomFilterInvertedView for inverted queries#271
v0id-X wants to merge 4 commits into
apache:mainfrom
v0id-X:feat/bloom-filter-inverted-view

Conversation

@v0id-X

@v0id-X v0id-X commented Sep 3, 2026

Copy link
Copy Markdown
  • Replaces in-place bit inversion on BloomFilter with an owned BloomFilterInvertedView.
  • Prevents unsound mutations on an inverted filter while retaining membership queries.
  • Provides bi-directional conversion via invert() and into_filter().
  • Added unit and integration tests covering the new view type and conversion paths.

Closes #270

Comment thread datasketches/src/bloom/sketch.rs Outdated
/// * Constant space usage
///
/// These guarantees hold until [`invert()`](Self::invert) is called; see its documentation.
/// These guarantees hold unless inverted via [`invert()`](Self::invert).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer relevant because the inverted view is now a brand-new read-only view. It is no longer a BloomFilter.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Removing it.

Comment thread datasketches/src/bloom/sketch.rs Outdated
Comment on lines +261 to +264
/// Updates are disallowed on an inverted view to prevent unsound filter states. An inverted
/// view can be converted back into an updatable [`BloomFilter`] via
/// [`invert()`](BloomFilterInvertedView::invert) or
/// [`into_filter()`](BloomFilterInvertedView::into_filter).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be a document of BloomFilterInvertedView rather than details on the method.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'll trim the method documentation down to its core behavior and move the details regarding disallowed mutations and reinversion up to the BloomFilterInvertedView struct documentation.

Comment thread datasketches/src/bloom/sketch.rs Outdated
Comment on lines +658 to +690
/// Re-inverts the view back into an updatable [`BloomFilter`].
///
/// Inverting twice restores the original bit state and filter guarantees.
///
/// # Examples
///
/// ```
/// use datasketches::bloom::BloomFilterBuilder;
///
/// let mut filter = BloomFilterBuilder::with_accuracy(100, 0.01)
/// .build()
/// .unwrap();
/// filter.insert("apple");
///
/// let inverted = filter.invert();
/// let restored = inverted.invert();
/// assert!(restored.contains(&"apple"));
/// ```
pub fn invert(self) -> BloomFilter {
self.into_filter()
}

/// Converts this inverted view back into an updatable [`BloomFilter`] by
/// inverting the bits again.
///
/// Equivalent to [`invert()`](Self::invert).
pub fn into_filter(mut self) -> BloomFilter {
for word in &mut self.inner.bit_array {
*word = !*word;
}
self.inner.num_bits_set = self.inner.capacity() as u64 - self.inner.num_bits_set;
self.inner
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need alias here. Please think of it by yourself rather than just blindly follow the issue description.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes a lot more sense. Symmetrical .invert() (filter.invert().invert()) is way cleaner anyway. Dropping into_filter and keeping just invert(self) -> BloomFilter.

Comment thread datasketches/src/bloom/sketch.rs Outdated
Comment on lines +692 to +695
/// Returns a reference to the underlying [`BloomFilter`] representation.
pub fn as_filter(&self) -> &BloomFilter {
&self.inner
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have this method?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, this makes the abstraction weaker risking misuse. Removing it entirely.

Comment thread CHANGELOG.md Outdated
All significant changes to this project will be documented in this file.

## Unreleased
- feat(bloom): make post-invert semantics observable via `BloomFilterInvertedView` (#270, #271)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the changelog format like other entries.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, will fix the formatting to match the rest of the file.

@v0id-X

v0id-X commented Sep 3, 2026

Copy link
Copy Markdown
Author

All review comments addressed and updated:

  • Removed the outdated guarantee disclaimer on BloomFilter.
  • Moved mutation/inversion details from BloomFilter::invert's doc to BloomFilterInvertedView's struct-level documentation.
  • Removed the into_filter alias in favor of symmetrical invert(self) -> BloomFilter.
  • Removed as_filter to preserve view encapsulation.
  • Aligned CHANGELOG.md under ### Breaking changes and ### New features per CONTRIBUTING.md.
  • Uncommented the inverted view doctest example in bloom/mod.rs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BloomFilter: make post-invert semantics observable in the type system

2 participants