apache_datasketches/tuple/generic/a_not_b.rs
1use super::{CompactTupleSketch, TupleInput, TupleSummary};
2use apache_datasketches_sys::tuple_generic_a_not_b::ffi as sys;
3use apache_datasketches_sys::tuple_generic_input::TupleGenericInputRef;
4use cxx::UniquePtr;
5use std::marker::PhantomData;
6
7/// Computes the set difference `a - b` over generic Tuple sketches.
8///
9/// Retained entries keep `a`'s summaries unchanged: unlike
10/// [`TupleUnion`](super::TupleUnion) and
11/// [`TupleIntersection`](super::TupleIntersection), a-not-b has no combine
12/// policy at all, so neither [`TupleSummary::union_combine`] nor
13/// [`TupleSummary::intersection_combine`] is ever invoked. Each surviving
14/// summary is cloned out of `a`, which leaves `a` itself untouched and usable
15/// afterwards.
16///
17/// Stateless between calls, and asymmetric: `compute(a, b)` and
18/// `compute(b, a)` are different operations.
19///
20/// No builder: upstream's type has a plain constructor, matching
21/// [`ArrayOfDoublesAnotB`](crate::tuple::ArrayOfDoublesAnotB).
22pub struct TupleAnotB<S: TupleSummary> {
23 inner: UniquePtr<sys::TupleGenericAnotBShim>,
24 _marker: PhantomData<fn() -> S>,
25}
26
27// Sound because `S: Send` is a supertrait of `TupleSummary` and every summary
28// that crosses through this calculator is a `Box<dyn RawSummaryOps + Send>`.
29// Deliberately not `Sync`, matching `TupleSketch<S>`, `CompactTupleSketch<S>`,
30// `TupleUnion<S>` and `TupleIntersection<S>`.
31unsafe impl<S: TupleSummary> Send for TupleAnotB<S> {}
32
33impl<S: TupleSummary> Default for TupleAnotB<S> {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl<S: TupleSummary> TupleAnotB<S> {
40 /// Creates a reusable a-not-b calculator.
41 pub fn new() -> Self {
42 Self {
43 inner: sys::new_tuple_generic_a_not_b(),
44 _marker: PhantomData,
45 }
46 }
47
48 /// Computes `a - b`: keys in `a` that are not in `b`, carrying `a`'s
49 /// summaries. If `ordered` is `true`, the result's entries are sorted by
50 /// hash value.
51 ///
52 /// Infallible: upstream throws only on a seed-hash mismatch, and this
53 /// family never exposes a seed — every sketch here is built with the
54 /// default one.
55 pub fn compute(
56 &self,
57 a: &impl TupleInput<S>,
58 b: &impl TupleInput<S>,
59 ordered: bool,
60 ) -> CompactTupleSketch<S> {
61 let inner = match (a.as_input(), b.as_input()) {
62 (TupleGenericInputRef::Sketch(a), TupleGenericInputRef::Sketch(b)) => {
63 self.inner.compute_sketch_sketch(a, b, ordered)
64 }
65 (TupleGenericInputRef::Sketch(a), TupleGenericInputRef::Compact(b)) => {
66 self.inner.compute_sketch_compact(a, b, ordered)
67 }
68 (TupleGenericInputRef::Compact(a), TupleGenericInputRef::Sketch(b)) => {
69 self.inner.compute_compact_sketch(a, b, ordered)
70 }
71 (TupleGenericInputRef::Compact(a), TupleGenericInputRef::Compact(b)) => {
72 self.inner.compute_compact_compact(a, b, ordered)
73 }
74 };
75 CompactTupleSketch::from_shim(inner)
76 }
77}