use atomic_refcell::AtomicRef;
use crate::common::bitvec::{BitSlice, BitSliceExt as _};
use crate::common::types::{DeferredBehavior, PointOffsetType};
use itertools::Either;
use self_cell::self_cell;
use super::tracker_enum::IdTrackerEnum;
use crate::segment::id_tracker::compressed::compressed_point_mappings::CompressedPointMappings;
use crate::segment::id_tracker::point_mappings::PointMappings;
use crate::segment::types::PointIdType;
#[derive(Clone, Copy)]
pub enum PointMappingsRefEnum<'a> {
Plain(&'a PointMappings),
Compressed(&'a CompressedPointMappings),
}
impl<'a> PointMappingsRefEnum<'a> {
pub fn iter_external(self) -> Box<dyn Iterator<Item = PointIdType> + 'a> {
match self {
PointMappingsRefEnum::Plain(m) => m.iter_external(),
PointMappingsRefEnum::Compressed(m) => m.iter_external(),
}
}
pub fn iter_internal(self) -> Box<dyn Iterator<Item = PointOffsetType> + 'a> {
match self {
PointMappingsRefEnum::Plain(m) => m.iter_internal(),
PointMappingsRefEnum::Compressed(m) => m.iter_internal(),
}
}
pub fn iter_from(
self,
external_id: Option<PointIdType>,
) -> Box<dyn Iterator<Item = (PointIdType, PointOffsetType)> + 'a> {
match self {
PointMappingsRefEnum::Plain(m) => m.iter_from(external_id),
PointMappingsRefEnum::Compressed(m) => m.iter_from(external_id),
}
}
pub fn iter_random(self) -> Box<dyn Iterator<Item = (PointIdType, PointOffsetType)> + 'a> {
match self {
PointMappingsRefEnum::Plain(m) => m.iter_random(),
PointMappingsRefEnum::Compressed(m) => m.iter_random(),
}
}
pub fn iter_internal_excluding(
self,
exclude_bitslice: &'a BitSlice,
) -> Box<dyn Iterator<Item = PointOffsetType> + 'a> {
let iter: Box<dyn Iterator<Item = PointOffsetType> + 'a> = match self {
PointMappingsRefEnum::Plain(m) => m.iter_internal(),
PointMappingsRefEnum::Compressed(m) => m.iter_internal(),
};
Box::new(
iter.filter(move |point| !exclude_bitslice.get_bit(*point as usize).unwrap_or(false)),
)
}
pub fn iter_internal_visible(self) -> Box<dyn Iterator<Item = PointOffsetType> + 'a> {
match self.deferred_internal_id() {
None => self.iter_internal(),
Some(deferred_internal_id) => Box::new(
self.iter_internal()
.take_while(move |&id| id < deferred_internal_id),
),
}
}
pub fn iter_internal_with_behavior(
self,
deferred_behavior: DeferredBehavior,
) -> Box<dyn Iterator<Item = PointOffsetType> + 'a> {
if deferred_behavior.include_all_points() {
self.iter_internal()
} else {
self.iter_internal_visible()
}
}
pub fn filter_deferred_and_deleted<I>(
self,
iter: I,
deferred_behavior: DeferredBehavior,
) -> impl Iterator<Item = PointOffsetType>
where
I: Iterator<Item = PointOffsetType>,
{
let deleted = self.deleted();
match deferred_behavior.apply(self.deferred_internal_id()) {
None => {
Either::Left(iter.filter(move |&id| !deleted.get_bit(id as usize).unwrap_or(false)))
}
Some(cutoff) => {
Either::Right(iter.filter(move |&id| {
id < cutoff && !deleted.get_bit(id as usize).unwrap_or(false)
}))
}
}
}
pub fn iter_from_visible(
self,
external_id: Option<PointIdType>,
) -> Box<dyn Iterator<Item = (PointIdType, PointOffsetType)> + 'a> {
match self.deferred_internal_id() {
None => self.iter_from(external_id),
Some(deferred_internal_id) => Box::new(
self.iter_from(external_id)
.filter(move |&(_, iid)| iid < deferred_internal_id),
),
}
}
pub fn iter_random_visible(
self,
) -> Box<dyn Iterator<Item = (PointIdType, PointOffsetType)> + 'a> {
match self.deferred_internal_id() {
None => self.iter_random(),
Some(deferred_internal_id) => Box::new(
self.iter_random()
.filter(move |&(_, iid)| iid < deferred_internal_id),
),
}
}
fn deferred_internal_id(self) -> Option<PointOffsetType> {
match self {
PointMappingsRefEnum::Plain(m) => m.deferred_internal_id(),
PointMappingsRefEnum::Compressed(_) => None,
}
}
fn deleted(self) -> &'a BitSlice {
match self {
PointMappingsRefEnum::Plain(m) => m.deleted(),
PointMappingsRefEnum::Compressed(m) => m.deleted(),
}
}
}
self_cell! {
pub struct PointMappingsGuard<'a> {
owner: AtomicRef<'a, IdTrackerEnum>,
#[covariant]
dependent: PointMappingsRefEnum,
}
}