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}