Skip to main content

apache_datasketches/theta/
intersection.rs

1use super::input::ThetaInput;
2use super::CompactThetaSketch;
3use crate::error::SketchError;
4use apache_datasketches_sys::theta_input::ThetaInputRef;
5use apache_datasketches_sys::theta_intersection::ffi as sys;
6use cxx::UniquePtr;
7
8/// Computes the intersection of theta sketches fed via [`Self::update`].
9/// Unlike [`super::ThetaUnion`]/[`super::ThetaAnotB`], intersection has no
10/// builder — the intersecting universe is defined entirely by the sketches
11/// passed to `update`, matching upstream's plain-constructor
12/// `theta_intersection`.
13pub struct ThetaIntersection {
14    inner: UniquePtr<sys::ThetaIntersectionShim>,
15}
16
17unsafe impl Send for ThetaIntersection {}
18
19impl Default for ThetaIntersection {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl ThetaIntersection {
26    /// Creates a new intersection accumulator with no result yet — call
27    /// [`Self::update`] at least once before [`Self::get_result`].
28    pub fn new() -> Self {
29        Self {
30            inner: sys::new_theta_intersection(),
31        }
32    }
33
34    /// Narrows this intersection's running result to also require
35    /// membership in the given sketch. The first call establishes the
36    /// initial universe; each subsequent call intersects further.
37    pub fn update(&mut self, input: &impl ThetaInput) {
38        match input.as_theta_input() {
39            ThetaInputRef::Sketch(s) => self.inner.pin_mut().update_with_sketch(s),
40            ThetaInputRef::Compact(c) => self.inner.pin_mut().update_with_compact(c),
41            ThetaInputRef::Wrapped(w) => self.inner.pin_mut().update_with_wrapped(w),
42        }
43    }
44
45    /// Returns the current intersection result as a [`CompactThetaSketch`],
46    /// or [`SketchError::EmptyIntersection`] if [`Self::update`] has never
47    /// been called. If `ordered` is `true`, the result's entries are
48    /// sorted by hash value.
49    pub fn get_result(&self, ordered: bool) -> Result<CompactThetaSketch, SketchError> {
50        if !self.inner.has_result() {
51            return Err(SketchError::EmptyIntersection);
52        }
53        let inner = self
54            .inner
55            .get_result(ordered)
56            .map_err(|e| SketchError::Cpp(e.what().to_string()))?;
57        Ok(CompactThetaSketch::from_shim(inner))
58    }
59
60    /// Returns `true` if [`Self::update`] has been called at least once.
61    pub fn has_result(&self) -> bool {
62        self.inner.has_result()
63    }
64}