graphrecords-query 0.5.0

High-performance graph-based data records
Documentation
use super::{
    descriptor::{ArityDescriptor, RetentionDescriptor},
    manifest::describe::{DescribeArity, DescribeEmission},
};
use crate::{
    Arity, Definite, Multiple, Ordered, Single, Unordered,
    element::{Dropping, ElementEmission, Expanding, Preserving},
};
use graphrecords_utils::aliases::GrHashMap;

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum EmissionKind {
    Preserving,
    Dropping,
    ExpandingOrdered,
    ExpandingUnordered,
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum EmissionSpec {
    Fixed(EmissionKind),
    OfArgument,
}

#[derive(Default)]
pub struct OutArityTable {
    cells: GrHashMap<(EmissionSpec, ArityDescriptor), ArityDescriptor>,
}

impl OutArityTable {
    pub(super) fn builtins() -> Self {
        let mut table = Self::default();

        table.insert_row::<Preserving>();
        table.insert_row::<Dropping>();
        table.insert_row::<Expanding<Ordered>>();
        table.insert_row::<Expanding<Unordered>>();

        table
    }

    fn insert_row<E>(&mut self)
    where
        E: ElementEmission + DescribeEmission,
        E::OutArity<Multiple<Ordered>>: DescribeArity,
        E::OutArity<Multiple<Unordered>>: DescribeArity,
        E::OutArity<Single>: DescribeArity,
        E::OutArity<Definite>: DescribeArity,
    {
        self.insert_cell::<E, Multiple<Ordered>>();
        self.insert_cell::<E, Multiple<Unordered>>();
        self.insert_cell::<E, Single>();
        self.insert_cell::<E, Definite>();
    }

    fn insert_cell<E, C>(&mut self)
    where
        E: ElementEmission + DescribeEmission,
        C: Arity + DescribeArity,
        E::OutArity<C>: DescribeArity,
    {
        self.cells.insert(
            (E::emission_spec(), C::arity_descriptor()),
            <E::OutArity<C> as DescribeArity>::arity_descriptor(),
        );
    }

    pub(super) fn resolve(
        &self,
        emission: EmissionSpec,
        arity: ArityDescriptor,
        retention: RetentionDescriptor,
    ) -> ArityDescriptor {
        let emission = match emission {
            EmissionSpec::Fixed(_) => emission,
            EmissionSpec::OfArgument => EmissionSpec::Fixed(match retention {
                RetentionDescriptor::Preserving => EmissionKind::Preserving,
                RetentionDescriptor::Dropping => EmissionKind::Dropping,
            }),
        };

        *self.cells.get(&(emission, arity)).unwrap_or_else(|| {
            panic!("registry has no materialized out arity for {emission:?} applied to {arity:?}")
        })
    }
}