graphrecords-query 0.5.0

High-performance graph-based data records
Documentation
mod equal_to;
mod greater_than;
mod greater_than_or_equal_to;
mod less_than;
mod less_than_or_equal_to;
mod not_equal_to;

use crate::{
    Failure, IndexDomain, Mask, ValueDomain,
    element::{BarePipeline, IndexedValuePipeline, Pipeline, Retention},
    error::comparison::IncomparableValues,
    operations::{ArgumentSource, Keyed, Unaligned},
    registry::OperationManifest,
};
pub use equal_to::EqualToOperation;
pub use greater_than::GreaterThanOperation;
pub use greater_than_or_equal_to::GreaterThanOrEqualToOperation;
pub use less_than::LessThanOperation;
pub use less_than_or_equal_to::LessThanOrEqualToOperation;
pub use not_equal_to::NotEqualToOperation;
use std::{
    cmp::Ordering,
    fmt::{Debug, Display},
};

pub(super) fn operation_manifests() -> Vec<OperationManifest> {
    vec![
        equal_to::operation_manifest(),
        greater_than::operation_manifest(),
        greater_than_or_equal_to::operation_manifest(),
        less_than::operation_manifest(),
        less_than_or_equal_to::operation_manifest(),
        not_equal_to::operation_manifest(),
    ]
}

fn equality_indexed<'a, I, V, A>(
    prepared: A::Prepared<'a>,
    label: &'static str,
    equality: fn(&V::Value<'a>, &V::Value<'a>) -> bool,
) -> IndexedValuePipeline<'a, I, V, Mask, A::Retention>
where
    I: IndexDomain,
    V: ValueDomain,
    A: ArgumentSource<Keyed<I>, V>,
    A::Prepared<'a>: 'a,
{
    Pipeline::keyed(move |index, item| {
        let value = match item {
            Ok(value) => value,
            Err(original) => {
                return A::Retention::keep(Err(original));
            }
        };

        let step = A::resolve(&prepared, &index, label);

        A::Retention::map_step(step, |resolved| {
            resolved.map(|argument| equality(&value, &argument))
        })
    })
}

fn equality_bare<'a, V, A>(
    prepared: A::Prepared<'a>,
    label: &'static str,
    equality: fn(&V::Value<'a>, &V::Value<'a>) -> bool,
) -> BarePipeline<'a, V, Mask, A::Retention>
where
    V: ValueDomain,
    A: ArgumentSource<Unaligned, V>,
    A::Prepared<'a>: 'a,
{
    Pipeline::new(move |item| {
        let value = match item {
            Ok(value) => value,
            Err(original) => {
                return A::Retention::keep(Err(original));
            }
        };

        let step = A::resolve(&prepared, &(), label);

        A::Retention::map_step(step, |resolved| {
            resolved.map(|argument| equality(&value, &argument))
        })
    })
}

fn ordering_indexed<'a, I, V, A>(
    prepared: A::Prepared<'a>,
    label: &'static str,
    ordering: fn(&V::Value<'a>, &V::Value<'a>) -> Option<Ordering>,
    predicate: fn(Ordering) -> bool,
) -> IndexedValuePipeline<'a, I, V, Mask, A::Retention>
where
    I: IndexDomain,
    V: ValueDomain,
    A: ArgumentSource<Keyed<I>, V>,
    V::Owned: Debug + Display + Send + Sync,
    A::Prepared<'a>: 'a,
{
    Pipeline::keyed(move |index, item| {
        let value = match item {
            Ok(value) => value,
            Err(original) => {
                return A::Retention::keep(Err(original));
            }
        };

        let step = A::resolve(&prepared, &index, label);

        A::Retention::map_step(step, |resolved| {
            resolved.and_then(|argument| match ordering(&value, &argument) {
                Some(outcome) => Ok(predicate(outcome)),
                None => Err(Failure::new_at::<I, _>(
                    label,
                    IncomparableValues::new(V::into_owned(value), V::into_owned(argument)),
                    &index,
                )),
            })
        })
    })
}

fn ordering_bare<'a, V, A>(
    prepared: A::Prepared<'a>,
    label: &'static str,
    ordering: fn(&V::Value<'a>, &V::Value<'a>) -> Option<Ordering>,
    predicate: fn(Ordering) -> bool,
) -> BarePipeline<'a, V, Mask, A::Retention>
where
    V: ValueDomain,
    A: ArgumentSource<Unaligned, V>,
    V::Owned: Debug + Display + Send + Sync,
    A::Prepared<'a>: 'a,
{
    Pipeline::new(move |item| {
        let value = match item {
            Ok(value) => value,
            Err(original) => {
                return A::Retention::keep(Err(original));
            }
        };

        let step = A::resolve(&prepared, &(), label);

        A::Retention::map_step(step, |resolved| {
            resolved.and_then(|argument| match ordering(&value, &argument) {
                Some(outcome) => Ok(predicate(outcome)),
                None => Err(Failure::new(
                    label,
                    IncomparableValues::new(V::into_owned(value), V::into_owned(argument)),
                )),
            })
        })
    })
}