use std::ops::Range;
use vortex_array::ArrayRef;
use vortex_array::buffer::BufferHandle;
use vortex_array::serde::SerializedArray;
use vortex_error::VortexResult;
use vortex_error::vortex_err;
use vortex_mask::Mask;
use vortex_session::VortexSession;
use crate::plan::physical::SegmentScanPlan;
use crate::plan::physical::operator::Cx;
use crate::plan::physical::operator::Input;
use crate::plan::physical::operator::Operator;
use crate::plan::physical::operator::Source;
use crate::plan::physical::operator::SourceBlocked;
use crate::plan::physical::operator::SourceReady;
use crate::plan::physical::operator::Step;
use crate::segments::SegmentId;
fn decode(
plan: &SegmentScanPlan,
segment: BufferHandle,
session: &VortexSession,
) -> VortexResult<ArrayRef> {
let serialized = match plan.array_tree() {
Some(tree) => SerializedArray::from_flatbuffer_and_segment(tree.clone(), segment)?,
None => SerializedArray::try_from(segment)?,
};
serialized.decode(
plan.dtype(),
usize::try_from(plan.row_count())?,
plan.array_ctx(),
session,
)
}
fn select(
array: ArrayRef,
slice: Option<&Range<usize>>,
filter: Option<&Mask>,
) -> VortexResult<ArrayRef> {
let array = match slice {
Some(slice) => array.slice(slice.clone())?,
None => array,
};
match filter {
Some(filter) => array.filter(filter.clone()),
None => Ok(array),
}
}
pub(crate) struct ScanSource {
plan: SegmentScanPlan,
slice: Option<Range<usize>>,
filter: Option<Mask>,
unread: Option<SegmentId>,
done: bool,
}
impl ScanSource {
pub(crate) fn new(
plan: SegmentScanPlan,
slice: Option<Range<usize>>,
filter: Option<Mask>,
) -> Self {
Self {
unread: Some(plan.segment_id()),
plan,
slice,
filter,
done: false,
}
}
}
impl Source for ScanSource {
fn ready(&mut self, cx: &mut Cx<'_>) -> VortexResult<SourceReady> {
if let Some(segment) = self.unread.take() {
cx.request_read(segment);
return Ok(SourceReady::Blocked(SourceBlocked::Io));
}
Ok(if self.done || cx.has_bytes() {
SourceReady::Ready
} else {
SourceReady::Blocked(SourceBlocked::Io)
})
}
}
impl Operator for ScanSource {
fn compute(&mut self, _input: Input, cx: &mut Cx<'_>) -> VortexResult<Step> {
if self.done {
return Ok(Step::End);
}
let (_, bytes) = cx
.take_segment()
.ok_or_else(|| vortex_err!("Segment scan ran without its bytes"))?;
self.done = true;
let array = decode(&self.plan, bytes, cx.session())?;
Ok(Step::Final(select(
array,
self.slice.as_ref(),
self.filter.as_ref(),
)?))
}
}
pub(crate) struct SelectStage {
slice: Option<Range<usize>>,
filter: Option<Mask>,
}
impl SelectStage {
pub(crate) fn new(slice: Option<Range<usize>>, filter: Option<Mask>) -> Self {
Self { slice, filter }
}
}
impl Operator for SelectStage {
fn compute(&mut self, input: Input, _cx: &mut Cx<'_>) -> VortexResult<Step> {
let Input::Batch(batch) = input else {
return Ok(Step::End);
};
Ok(Step::Final(select(
batch,
self.slice.as_ref(),
self.filter.as_ref(),
)?))
}
}