use atomic_refcell::AtomicRef;
use crate::common::bitvec::{BitSlice, BitSliceExt as _};
use crate::common::types::{DeferredBehavior, PointOffsetType};
use crate::common::universal_io::{MmapFile, UniversalRead};
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::disk_id_tracker::mappings::DiskMappingsRef;
use crate::segment::id_tracker::point_mappings::PointMappings;
use crate::segment::types::PointIdType;
pub enum PointMappingsRefEnum<'a, S: UniversalRead> {
Plain(&'a PointMappings),
Compressed(&'a CompressedPointMappings),
Disk(DiskMappingsRef<'a, S>),
}
impl<S: UniversalRead> Clone for PointMappingsRefEnum<'_, S> {
fn clone(&self) -> Self {
*self
}
}
impl<S: UniversalRead> Copy for PointMappingsRefEnum<'_, S> {}
impl<'a, S: UniversalRead> PointMappingsRefEnum<'a, S> {
pub fn iter_external(self) -> impl Iterator<Item = PointIdType> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => Either::Left(m.iter_external()),
PointMappingsRefEnum::Compressed(m) => Either::Right(Either::Left(m.iter_external())),
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_external())),
}
}
pub fn iter_internal(self) -> impl Iterator<Item = PointOffsetType> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => Either::Left(m.iter_internal()),
PointMappingsRefEnum::Compressed(m) => Either::Right(Either::Left(m.iter_internal())),
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_internal())),
}
}
pub fn iter_from(
self,
external_id: Option<PointIdType>,
) -> impl Iterator<Item = (PointIdType, PointOffsetType)> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => Either::Left(m.iter_from(external_id)),
PointMappingsRefEnum::Compressed(m) => {
Either::Right(Either::Left(m.iter_from(external_id)))
}
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_from(external_id))),
}
}
pub fn iter_internal_excluding(
self,
exclude_bitslice: &'a BitSlice,
) -> impl Iterator<Item = PointOffsetType> + 'a {
self.iter_internal()
.filter(move |point| !exclude_bitslice.get_bit(*point as usize).unwrap_or(false))
}
pub fn iter_internal_visible(self) -> impl Iterator<Item = PointOffsetType> + 'a {
match self.deferred_internal_id() {
None => Either::Left(self.iter_internal()),
Some(deferred_internal_id) => Either::Right(
self.iter_internal()
.take_while(move |&id| id < deferred_internal_id),
),
}
}
pub fn iter_internal_with_behavior(
self,
deferred_behavior: DeferredBehavior,
) -> impl Iterator<Item = PointOffsetType> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => {
Either::Left(m.iter_internal_with_behavior(deferred_behavior))
}
PointMappingsRefEnum::Compressed(m) => {
Either::Right(Either::Left(m.iter_internal()))
}
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_internal())),
}
}
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 => {
let shadowed = self.shadowed();
Either::Left(iter.filter(move |&id| {
!deleted.get_bit(id as usize).unwrap_or(false)
&& !shadowed.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_with_behavior(
self,
external_id: Option<PointIdType>,
deferred_behavior: DeferredBehavior,
) -> impl Iterator<Item = (PointIdType, PointOffsetType)> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => {
Either::Left(m.iter_from_with_behavior(external_id, deferred_behavior))
}
PointMappingsRefEnum::Compressed(m) => {
Either::Right(Either::Left(m.iter_from(external_id)))
}
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_from(external_id))),
}
}
pub fn iter_random_with_behavior(
self,
deferred_behavior: DeferredBehavior,
) -> impl Iterator<Item = (PointIdType, PointOffsetType)> + 'a {
match self {
PointMappingsRefEnum::Plain(m) => {
Either::Left(m.iter_random_with_behavior(deferred_behavior))
}
PointMappingsRefEnum::Compressed(m) => Either::Right(Either::Left(m.iter_random())),
PointMappingsRefEnum::Disk(m) => Either::Right(Either::Right(m.iter_random())),
}
}
pub fn iter_random_visible(self) -> impl Iterator<Item = (PointIdType, PointOffsetType)> + 'a {
self.iter_random_with_behavior(DeferredBehavior::VisibleOnly)
}
fn deferred_internal_id(self) -> Option<PointOffsetType> {
match self {
PointMappingsRefEnum::Plain(m) => m.deferred_internal_id(),
PointMappingsRefEnum::Compressed(_) | PointMappingsRefEnum::Disk(_) => None,
}
}
fn deleted(self) -> &'a BitSlice {
match self {
PointMappingsRefEnum::Plain(m) => m.deleted(),
PointMappingsRefEnum::Compressed(m) => m.deleted(),
PointMappingsRefEnum::Disk(m) => m.deleted(),
}
}
fn shadowed(self) -> &'a BitSlice {
match self {
PointMappingsRefEnum::Plain(m) => m.shadowed_bitslice(),
PointMappingsRefEnum::Compressed(_) | PointMappingsRefEnum::Disk(_) => {
BitSlice::empty()
}
}
}
}
type IdTrackerEnumMappingsRef<'a> = PointMappingsRefEnum<'a, MmapFile>;
self_cell! {
pub struct PointMappingsGuard<'a> {
owner: AtomicRef<'a, IdTrackerEnum>,
#[covariant]
dependent: IdTrackerEnumMappingsRef,
}
}