use apache_datasketches_sys::tuple_generic::{RawSummaryOps, RustSummary};
use std::any::Any;
pub trait TupleSummary: Clone + Send + 'static {
type Update: ?Sized;
fn create(update: &Self::Update) -> Self;
fn union_combine(&mut self, other: &Self);
fn intersection_combine(&mut self, other: &Self);
}
pub(crate) struct Adapter<S: TupleSummary> {
value: S,
}
impl<S: TupleSummary> Adapter<S> {
fn new(value: S) -> Self {
Self { value }
}
fn downcast(other: &dyn RawSummaryOps) -> &S {
match other.as_any().downcast_ref::<Adapter<S>>() {
Some(adapter) => &adapter.value,
None => panic!(
"apache-datasketches internal invariant violated: a generic Tuple \
summary of a different concrete type reached a combine callback. \
This should be impossible through the public API; please report it."
),
}
}
}
impl<S: TupleSummary> RawSummaryOps for Adapter<S> {
fn clone_boxed(&self) -> Box<dyn RawSummaryOps + Send> {
Box::new(Adapter::new(self.value.clone()))
}
fn union_combine(&mut self, other: &dyn RawSummaryOps) {
let other = Self::downcast(other);
self.value.union_combine(other);
}
fn intersection_combine(&mut self, other: &dyn RawSummaryOps) {
let other = Self::downcast(other);
self.value.intersection_combine(other);
}
fn as_any(&self) -> &dyn Any {
self
}
}
pub(crate) fn erase<S: TupleSummary>(value: S) -> RustSummary {
RustSummary::new(Box::new(Adapter::new(value)))
}
pub(crate) fn unerase<S: TupleSummary>(summary: &RustSummary) -> S {
match summary.ops().as_any().downcast_ref::<Adapter<S>>() {
Some(adapter) => adapter.value.clone(),
None => panic!(
"apache-datasketches internal invariant violated: a generic Tuple summary \
of a different concrete type was returned from the sketch. This should be \
impossible through the public API; please report it."
),
}
}