use std::cell::RefCell;
use vortex_error::{VortexExpect, VortexResult};
use crate::pipeline::operator::{NodeId, PipelineNode};
use crate::pipeline::vec::Vector;
use crate::pipeline::{VType, VectorId};
#[derive(Debug)]
pub struct VectorAllocationPlan {
pub(crate) output_targets: Vec<OutputTarget>,
pub(crate) vectors: Vec<RefCell<Vector>>,
}
#[derive(Debug, Clone)]
pub(crate) enum OutputTarget {
ExternalOutput,
IntermediateVector(usize), }
impl OutputTarget {
pub fn vector_id(&self) -> Option<VectorId> {
match self {
OutputTarget::IntermediateVector(idx) => Some(*idx),
OutputTarget::ExternalOutput => None,
}
}
}
#[derive(Debug, Clone)]
struct VectorAllocation {
element_type: VType,
}
pub(super) fn allocate_vectors(
dag: &[PipelineNode],
execution_order: &[NodeId],
) -> VortexResult<VectorAllocationPlan> {
let mut output_targets: Vec<Option<OutputTarget>> = vec![None; dag.len()];
let mut allocations = Vec::new();
for &node_idx in execution_order.iter().rev() {
let node = &dag[node_idx];
let operator = &node.operator;
let output_target = if node.parents.is_empty() {
OutputTarget::ExternalOutput
} else {
let alloc_id = allocations.len();
allocations.push(VectorAllocation {
element_type: operator.dtype().into(),
});
OutputTarget::IntermediateVector(alloc_id)
};
output_targets[node_idx] = Some(output_target);
}
Ok(VectorAllocationPlan {
output_targets: output_targets
.into_iter()
.map(|target| target.vortex_expect("missing target"))
.collect(),
vectors: allocations
.into_iter()
.map(|alloc| RefCell::new(Vector::new_with_vtype(alloc.element_type)))
.collect(),
})
}