#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueNeed {
None,
Predicate,
Projection,
Whole,
Numeric,
}
impl ValueNeed {
pub(crate) fn merge(self, other: Self) -> Self {
use ValueNeed::*;
match (self, other) {
(Whole, _) | (_, Whole) => Whole,
(Numeric, _) | (_, Numeric) => Numeric,
(Projection, _) | (_, Projection) => Projection,
(Predicate, _) | (_, Predicate) => Predicate,
(None, None) => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PullDemand {
All,
FirstInput(usize),
LastInput(usize),
NthInput(usize),
UntilOutput(usize),
}
impl PullDemand {
pub(crate) fn cap_inputs(self, n: usize) -> Self {
match self {
PullDemand::All | PullDemand::UntilOutput(_) | PullDemand::LastInput(_) => {
PullDemand::FirstInput(n)
}
PullDemand::FirstInput(m) => PullDemand::FirstInput(m.min(n)),
PullDemand::NthInput(i) => {
if i < n {
PullDemand::NthInput(i)
} else {
PullDemand::FirstInput(n)
}
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Demand {
pub pull: PullDemand,
pub value: ValueNeed,
pub order: bool,
}
impl Demand {
pub const RESULT: Demand = Demand {
pull: PullDemand::All,
value: ValueNeed::Whole,
order: true,
};
pub fn all(value: ValueNeed) -> Self {
Self {
pull: PullDemand::All,
value,
order: true,
}
}
pub fn first(value: ValueNeed) -> Self {
Self {
pull: PullDemand::FirstInput(1),
value,
order: false,
}
}
}
pub trait DemandOperator {
fn propagate_demand(&self, downstream: Demand) -> Demand;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DemandStep<Op> {
pub op: Op,
pub downstream: Demand,
pub upstream: Demand,
}
pub fn propagate_demands<Op>(ops: &[Op], final_demand: Demand) -> Vec<DemandStep<Op>>
where
Op: DemandOperator + Clone,
{
let mut demand = final_demand;
let mut out = Vec::with_capacity(ops.len());
for op in ops.iter().rev() {
let upstream = op.propagate_demand(demand);
out.push(DemandStep {
op: op.clone(),
downstream: demand,
upstream,
});
demand = upstream;
}
out.reverse();
out
}
pub fn source_demand<Op>(ops: &[Op], final_demand: Demand) -> Demand
where
Op: DemandOperator,
{
ops.iter()
.rev()
.fold(final_demand, |demand, op| op.propagate_demand(demand))
}