Skip to main content

apache_datasketches/theta/
wrapped.rs

1use crate::error::SketchError;
2use apache_datasketches_sys::theta_wrapped::ffi as sys;
3use cxx::UniquePtr;
4use std::marker::PhantomData;
5
6/// A zero-copy, read-only view over an already-serialized compact theta
7/// sketch's bytes, usable directly as set-operation input without a full
8/// [`super::CompactThetaSketch::deserialize`]. Build one with [`Self::wrap`].
9///
10/// The lifetime `'a` ties this view to the borrowed `&'a [u8]` buffer it
11/// wraps — it cannot outlive the bytes it was built from.
12pub struct WrappedCompactThetaSketch<'a> {
13    pub(crate) inner: UniquePtr<sys::WrappedCompactThetaSketchShim>,
14    _marker: PhantomData<&'a [u8]>,
15}
16
17unsafe impl<'a> Send for WrappedCompactThetaSketch<'a> {}
18
19impl<'a> WrappedCompactThetaSketch<'a> {
20    /// Wraps a serialized compact theta sketch's bytes without copying or
21    /// fully deserializing them.
22    pub fn wrap(bytes: &'a [u8]) -> Result<Self, SketchError> {
23        let inner = sys::wrapped_compact_theta_sketch_wrap(bytes)
24            .map_err(|e| SketchError::Deserialization(e.what().to_string()))?;
25        Ok(Self {
26            inner,
27            _marker: PhantomData,
28        })
29    }
30
31    /// Returns the current estimate of the number of distinct items in the
32    /// wrapped sketch.
33    pub fn get_estimate(&self) -> f64 {
34        self.inner.get_estimate()
35    }
36
37    /// Returns the lower bound of the confidence interval around
38    /// [`Self::get_estimate`]. See
39    /// [`ThetaSketch::get_lower_bound`](super::ThetaSketch::get_lower_bound)
40    /// for the meaning of `num_std_dev`.
41    pub fn get_lower_bound(&self, num_std_dev: u8) -> Result<f64, SketchError> {
42        self.inner
43            .get_lower_bound(num_std_dev)
44            .map_err(|e| SketchError::InvalidConfig(e.what().to_string()))
45    }
46
47    /// Returns the upper bound of the confidence interval around
48    /// [`Self::get_estimate`]. See
49    /// [`ThetaSketch::get_lower_bound`](super::ThetaSketch::get_lower_bound)
50    /// for the meaning of `num_std_dev`.
51    pub fn get_upper_bound(&self, num_std_dev: u8) -> Result<f64, SketchError> {
52        self.inner
53            .get_upper_bound(num_std_dev)
54            .map_err(|e| SketchError::InvalidConfig(e.what().to_string()))
55    }
56
57    /// Returns `true` if the wrapped sketch represents an empty set.
58    pub fn is_empty(&self) -> bool {
59        self.inner.is_empty()
60    }
61
62    /// Returns `true` if the wrapped sketch's theta threshold is below
63    /// `1.0` (i.e. [`Self::get_estimate`] is a statistical estimate rather
64    /// than an exact count).
65    pub fn is_estimation_mode(&self) -> bool {
66        self.inner.is_estimation_mode()
67    }
68
69    /// Returns `true` if the wrapped sketch's retained entries are sorted
70    /// by hash value.
71    pub fn is_ordered(&self) -> bool {
72        self.inner.is_ordered()
73    }
74
75    /// Returns the wrapped sketch's current theta threshold (`1.0` if not
76    /// in estimation mode).
77    pub fn get_theta(&self) -> f64 {
78        self.inner.get_theta()
79    }
80
81    /// Returns the number of entries retained by the wrapped sketch.
82    pub fn get_num_retained(&self) -> u32 {
83        self.inner.get_num_retained()
84    }
85}