use std::any::Any;
pub trait RawSummaryOps: Any + Send {
fn clone_boxed(&self) -> Box<dyn RawSummaryOps + Send>;
fn union_combine(&mut self, other: &dyn RawSummaryOps);
fn intersection_combine(&mut self, other: &dyn RawSummaryOps);
fn as_any(&self) -> &dyn Any;
}
pub struct RustSummary {
ops: Box<dyn RawSummaryOps + Send>,
}
impl RustSummary {
pub fn new(ops: Box<dyn RawSummaryOps + Send>) -> Self {
Self { ops }
}
pub fn ops(&self) -> &dyn RawSummaryOps {
&*self.ops
}
pub fn ops_mut(&mut self) -> &mut dyn RawSummaryOps {
&mut *self.ops
}
}
fn abort_on_panic<F, R>(what: &str, f: F) -> R
where
F: FnOnce() -> R,
{
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
Ok(value) => value,
Err(_) => {
eprintln!(
"apache-datasketches: a {what} implementation panicked \
while called from C++. Panics cannot cross the FFI boundary, and the \
sketch cannot be left in a consistent state, so the process is aborting."
);
std::process::abort();
}
}
}
fn rust_summary_clone(summary: &RustSummary) -> Box<RustSummary> {
abort_on_panic("Clone::clone", || {
Box::new(RustSummary {
ops: summary.ops.clone_boxed(),
})
})
}
fn rust_summary_union_combine(target: &mut RustSummary, other: &RustSummary) {
abort_on_panic("TupleSummary::union_combine", || {
target.ops.union_combine(&*other.ops)
})
}
fn rust_summary_intersection_combine(target: &mut RustSummary, other: &RustSummary) {
abort_on_panic("TupleSummary::intersection_combine", || {
target.ops.intersection_combine(&*other.ops)
})
}
#[doc(hidden)]
pub fn clone_for_test(summary: &RustSummary) -> Box<RustSummary> {
rust_summary_clone(summary)
}
#[doc(hidden)]
pub fn union_for_test(target: &mut RustSummary, other: &RustSummary) {
rust_summary_union_combine(target, other)
}
#[doc(hidden)]
pub fn intersection_for_test(target: &mut RustSummary, other: &RustSummary) {
rust_summary_intersection_combine(target, other)
}
#[cxx::bridge(namespace = "apache_datasketches_rs")]
pub mod ffi {
extern "Rust" {
type RustSummary;
fn rust_summary_clone(summary: &RustSummary) -> Box<RustSummary>;
fn rust_summary_union_combine(target: &mut RustSummary, other: &RustSummary);
fn rust_summary_intersection_combine(target: &mut RustSummary, other: &RustSummary);
}
unsafe extern "C++" {
include!("tuple_generic_sketch_shim.h");
type TupleGenericSketchShim;
fn new_tuple_generic_sketch(
lg_k: u8,
rf: u8,
p: f32,
) -> Result<UniquePtr<TupleGenericSketchShim>>;
fn update_u64(self: Pin<&mut TupleGenericSketchShim>, key: u64, value: &RustSummary);
fn update_i64(self: Pin<&mut TupleGenericSketchShim>, key: i64, value: &RustSummary);
fn update_u32(self: Pin<&mut TupleGenericSketchShim>, key: u32, value: &RustSummary);
fn update_i32(self: Pin<&mut TupleGenericSketchShim>, key: i32, value: &RustSummary);
fn update_u16(self: Pin<&mut TupleGenericSketchShim>, key: u16, value: &RustSummary);
fn update_i16(self: Pin<&mut TupleGenericSketchShim>, key: i16, value: &RustSummary);
fn update_u8(self: Pin<&mut TupleGenericSketchShim>, key: u8, value: &RustSummary);
fn update_i8(self: Pin<&mut TupleGenericSketchShim>, key: i8, value: &RustSummary);
fn update_f64(self: Pin<&mut TupleGenericSketchShim>, key: f64, value: &RustSummary);
fn update_str(self: Pin<&mut TupleGenericSketchShim>, key: &str, value: &RustSummary);
fn update_bytes(self: Pin<&mut TupleGenericSketchShim>, key: &[u8], value: &RustSummary);
fn trim(self: Pin<&mut TupleGenericSketchShim>);
fn reset(self: Pin<&mut TupleGenericSketchShim>);
fn get_estimate(self: &TupleGenericSketchShim) -> f64;
fn get_lower_bound(self: &TupleGenericSketchShim, num_std_dev: u8) -> Result<f64>;
fn get_upper_bound(self: &TupleGenericSketchShim, num_std_dev: u8) -> Result<f64>;
fn is_empty(self: &TupleGenericSketchShim) -> bool;
fn is_estimation_mode(self: &TupleGenericSketchShim) -> bool;
fn is_ordered(self: &TupleGenericSketchShim) -> bool;
fn get_theta(self: &TupleGenericSketchShim) -> f64;
fn get_num_retained(self: &TupleGenericSketchShim) -> u32;
include!("tuple_generic_compact_shim.h");
type CompactTupleGenericSketchShim;
fn tuple_generic_sketch_compact(
sketch: &TupleGenericSketchShim,
ordered: bool,
) -> UniquePtr<CompactTupleGenericSketchShim>;
fn compact(
self: &TupleGenericSketchShim,
ordered: bool,
) -> UniquePtr<CompactTupleGenericSketchShim>;
fn get_estimate(self: &CompactTupleGenericSketchShim) -> f64;
fn get_lower_bound(self: &CompactTupleGenericSketchShim, num_std_dev: u8) -> Result<f64>;
fn get_upper_bound(self: &CompactTupleGenericSketchShim, num_std_dev: u8) -> Result<f64>;
fn is_empty(self: &CompactTupleGenericSketchShim) -> bool;
fn is_estimation_mode(self: &CompactTupleGenericSketchShim) -> bool;
fn is_ordered(self: &CompactTupleGenericSketchShim) -> bool;
fn get_theta(self: &CompactTupleGenericSketchShim) -> f64;
fn get_num_retained(self: &CompactTupleGenericSketchShim) -> u32;
fn entry_count(self: &CompactTupleGenericSketchShim) -> u32;
fn entry_hash(self: &CompactTupleGenericSketchShim, index: u32) -> Result<u64>;
fn entry_summary(
self: &CompactTupleGenericSketchShim,
index: u32,
) -> Result<Box<RustSummary>>;
}
}