use super::{SlotSet, SlotSetRead};
use crate::storage::query_workspace::MembershipOperation;
impl SlotSet {
fn apply(&mut self, operation: MembershipOperation, other: &Self) {
self.apply_read(operation, other.read());
}
pub(in crate::storage::warp_table) fn apply_read(
&mut self,
operation: MembershipOperation,
other: SlotSetRead<'_>,
) {
self.0.apply(operation, other.chunks());
}
pub(in crate::storage::warp_table) fn combine_reads(
operation: MembershipOperation,
left: SlotSetRead<'_>,
right: SlotSetRead<'_>,
) -> Self {
use super::membership::{Chunk, Membership};
use crate::storage::query_workspace::QueryChunk;
use crate::storage::warp_table::inconsistency::invariant_violation;
let mut result = Membership::new();
let mut left = left.chunks().peekable();
let mut right = right.chunks().peekable();
let mut output = QueryChunk::EMPTY;
loop {
let left_high = left.peek().map(|(high, _)| *high);
let right_high = right.peek().map(|(high, _)| *high);
let chunk = match (left_high, right_high) {
(Some(a), Some(b)) if a == b => {
let (high, a) = left
.next()
.unwrap_or_else(|| invariant_violation("peeked left chunk missing"));
let (_, b) = right
.next()
.unwrap_or_else(|| invariant_violation("peeked right chunk missing"));
a.combine(operation, b, &mut output)
.unwrap_or_else(|reason| invariant_violation(reason));
let read = output
.read()
.unwrap_or_else(|reason| invariant_violation(reason));
(read.len != 0).then(|| Chunk::from_read(high, read))
}
(Some(a), Some(b)) if a < b => left.next().and_then(|(high, read)| {
(operation != MembershipOperation::Intersection)
.then(|| Chunk::from_read(high, read))
}),
(Some(_), None) => left.next().and_then(|(high, read)| {
(operation != MembershipOperation::Intersection)
.then(|| Chunk::from_read(high, read))
}),
(Some(_), Some(_)) | (None, Some(_)) => right.next().and_then(|(high, read)| {
matches!(
operation,
MembershipOperation::Union | MembershipOperation::SymmetricDifference
)
.then(|| Chunk::from_read(high, read))
}),
(None, None) => break,
};
if let Some(chunk) = chunk {
result.len = result.len.saturating_add(u64::from(chunk.read().len));
result.chunks.push(chunk);
}
}
Self(result)
}
pub fn union(&self, other: &Self) -> Self {
let mut result = self.clone();
result.union_assign(other);
result
}
pub fn intersection(&self, other: &Self) -> Self {
let mut result = self.clone();
result.intersection_assign(other);
result
}
pub fn excluding(&self, other: &Self) -> Self {
let mut result = self.clone();
result.exclude_assign(other);
result
}
pub fn union_excluding_overlap(&self, other: &Self) -> Self {
let mut result = self.clone();
result.union_excluding_overlap_assign(other);
result
}
pub(crate) fn union_assign(&mut self, other: &Self) {
self.apply(MembershipOperation::Union, other)
}
pub(crate) fn intersection_assign(&mut self, other: &Self) {
self.apply(MembershipOperation::Intersection, other)
}
pub(crate) fn exclude_assign(&mut self, other: &Self) {
self.apply(MembershipOperation::Difference, other)
}
pub(crate) fn union_excluding_overlap_assign(&mut self, other: &Self) {
self.apply(MembershipOperation::SymmetricDifference, other)
}
pub(crate) fn intersection_reusing(mut self, other: &Self) -> Self {
self.intersection_assign(other);
self
}
pub(crate) fn intersection_owned(self, other: Self) -> Self {
self.intersection_reusing(&other)
}
pub fn is_disjoint(&self, other: &Self) -> bool {
self.read().is_disjoint(other.read())
}
pub fn is_subset(&self, other: &Self) -> bool {
self.read().is_subset(other.read())
}
}