Skip to content

Commit

Permalink
feat: implement exclude operation (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
JabobKrauskopf authored Oct 17, 2024
1 parent 78a6b80 commit a183c40
Show file tree
Hide file tree
Showing 14 changed files with 580 additions and 17 deletions.
59 changes: 59 additions & 0 deletions crates/medmodels-core/src/medrecord/querying/attributes/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,18 @@ impl AttributesTreeOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<AttributesTreeOperand>),
{
let mut operand = Wrapper::<AttributesTreeOperand>::new(self.context.clone());

query(&mut operand);

self.operations
.push(AttributesTreeOperation::Exclude { operand });
}
}

impl Wrapper<AttributesTreeOperand> {
Expand Down Expand Up @@ -407,6 +419,13 @@ impl Wrapper<AttributesTreeOperand> {
{
self.0.write_or_panic().either_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<AttributesTreeOperand>),
{
self.0.write_or_panic().exclude(query)
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -575,6 +594,19 @@ impl MultipleAttributesOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<MultipleAttributesOperand>),
{
let mut operand =
Wrapper::<MultipleAttributesOperand>::new(self.context.clone(), self.kind.clone());

query(&mut operand);

self.operations
.push(MultipleAttributesOperation::Exclude { operand });
}
}

impl Wrapper<MultipleAttributesOperand> {
Expand Down Expand Up @@ -663,6 +695,13 @@ impl Wrapper<MultipleAttributesOperand> {
{
self.0.write_or_panic().either_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<MultipleAttributesOperand>),
{
self.0.write_or_panic().exclude(query)
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -794,6 +833,19 @@ impl SingleAttributeOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<SingleAttributeOperand>),
{
let mut operand =
Wrapper::<SingleAttributeOperand>::new(self.context.clone(), self.kind.clone());

query(&mut operand);

self.operations
.push(SingleAttributeOperation::Exclude { operand });
}
}

impl Wrapper<SingleAttributeOperand> {
Expand Down Expand Up @@ -871,4 +923,11 @@ impl Wrapper<SingleAttributeOperand> {
{
self.0.write_or_panic().eiter_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<SingleAttributeOperand>),
{
self.0.write_or_panic().exclude(query);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
use itertools::Itertools;
use std::{
cmp::Ordering,
collections::HashMap,
collections::{HashMap, HashSet},
fmt::Display,
hash::Hash,
ops::{Add, Mul, Range, Sub},
Expand Down Expand Up @@ -119,6 +119,9 @@ pub enum AttributesTreeOperation {
either: Wrapper<AttributesTreeOperand>,
or: Wrapper<AttributesTreeOperand>,
},
Exclude {
operand: Wrapper<AttributesTreeOperand>,
},
}

impl DeepClone for AttributesTreeOperation {
Expand Down Expand Up @@ -155,6 +158,9 @@ impl DeepClone for AttributesTreeOperation {
either: either.deep_clone(),
or: or.deep_clone(),
},
Self::Exclude { operand } => Self::Exclude {
operand: operand.deep_clone(),
},
}
}
}
Expand Down Expand Up @@ -221,6 +227,7 @@ impl AttributesTreeOperation {
Self::EitherOr { either, or } => {
Self::evaluate_either_or(medrecord, attributes, either, or)
}
Self::Exclude { operand } => Self::evaluate_exclude(medrecord, attributes, operand),
}
}

Expand Down Expand Up @@ -670,6 +677,26 @@ impl AttributesTreeOperation {
.unique_by(|attribute| attribute.0),
))
}

#[inline]
fn evaluate_exclude<'a, T: 'a + Eq + Hash + GetAttributes + Display>(
medrecord: &'a MedRecord,
attributes: impl Iterator<Item = (&'a T, Vec<MedRecordAttribute>)>,
operand: &Wrapper<AttributesTreeOperand>,
) -> MedRecordResult<BoxedIterator<'a, (&'a T, Vec<MedRecordAttribute>)>> {
let attributes = attributes.collect::<Vec<_>>();

let result = operand
.evaluate(medrecord, attributes.clone().into_iter())?
.map(|(index, _)| index)
.collect::<HashSet<_>>();

Ok(Box::new(
attributes
.into_iter()
.filter(move |(index, _)| !result.contains(index)),
))
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -709,6 +736,9 @@ pub enum MultipleAttributesOperation {
either: Wrapper<MultipleAttributesOperand>,
or: Wrapper<MultipleAttributesOperand>,
},
Exclude {
operand: Wrapper<MultipleAttributesOperand>,
},
}

impl DeepClone for MultipleAttributesOperation {
Expand Down Expand Up @@ -748,6 +778,9 @@ impl DeepClone for MultipleAttributesOperation {
either: either.deep_clone(),
or: or.deep_clone(),
},
Self::Exclude { operand } => Self::Exclude {
operand: operand.deep_clone(),
},
}
}
}
Expand Down Expand Up @@ -805,6 +838,7 @@ impl MultipleAttributesOperation {
Self::EitherOr { either, or } => {
Self::evaluate_either_or(medrecord, attributes, either, or)
}
Self::Exclude { operand } => Self::evaluate_exclude(medrecord, attributes, operand),
}
}

Expand Down Expand Up @@ -1151,6 +1185,26 @@ impl MultipleAttributesOperation {
.unique_by(|attribute| attribute.0),
))
}

#[inline]
fn evaluate_exclude<'a, T: 'a + Eq + Hash + GetAttributes + Display>(
medrecord: &'a MedRecord,
attributes: impl Iterator<Item = (&'a T, MedRecordAttribute)>,
operand: &Wrapper<MultipleAttributesOperand>,
) -> MedRecordResult<BoxedIterator<'a, (&'a T, MedRecordAttribute)>> {
let attributes = attributes.collect::<Vec<_>>();

let result = operand
.evaluate(medrecord, attributes.clone().into_iter())?
.map(|(index, _)| index)
.collect::<HashSet<_>>();

Ok(Box::new(
attributes
.into_iter()
.filter(move |(index, _)| !result.contains(index)),
))
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -1180,6 +1234,9 @@ pub enum SingleAttributeOperation {
either: Wrapper<SingleAttributeOperand>,
or: Wrapper<SingleAttributeOperand>,
},
Exclude {
operand: Wrapper<SingleAttributeOperand>,
},
}

impl DeepClone for SingleAttributeOperation {
Expand Down Expand Up @@ -1211,6 +1268,9 @@ impl DeepClone for SingleAttributeOperation {
either: either.deep_clone(),
or: or.deep_clone(),
},
Self::Exclude { operand } => Self::Exclude {
operand: operand.deep_clone(),
},
}
}
}
Expand Down Expand Up @@ -1255,6 +1315,12 @@ impl SingleAttributeOperation {
Self::EitherOr { either, or } => {
Self::evaluate_either_or(medrecord, attribute, either, or)
}
Self::Exclude { operand } => {
Ok(match operand.evaluate(medrecord, attribute.clone())? {
Some(_) => None,
None => Some(attribute),
})
}
}
}

Expand Down
56 changes: 56 additions & 0 deletions crates/medmodels-core/src/medrecord/querying/edges/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ impl EdgeOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeOperand>),
{
let mut operand = Wrapper::<EdgeOperand>::new();

query(&mut operand);

self.operations.push(EdgeOperation::Exclude { operand });
}
}

impl Wrapper<EdgeOperand> {
Expand Down Expand Up @@ -203,6 +214,13 @@ impl Wrapper<EdgeOperand> {
{
self.0.write_or_panic().either_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeOperand>),
{
self.0.write_or_panic().exclude(query);
}
}

macro_rules! implement_index_operation {
Expand Down Expand Up @@ -450,6 +468,18 @@ impl EdgeIndicesOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeIndicesOperand>),
{
let mut operand = Wrapper::<EdgeIndicesOperand>::new(self.context.clone());

query(&mut operand);

self.operations
.push(EdgeIndicesOperation::Exclude { operand });
}
}

impl Wrapper<EdgeIndicesOperand> {
Expand Down Expand Up @@ -505,6 +535,13 @@ impl Wrapper<EdgeIndicesOperand> {
{
self.0.write_or_panic().either_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeIndicesOperand>),
{
self.0.write_or_panic().exclude(query);
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -607,6 +644,18 @@ impl EdgeIndexOperand {
or: or_operand,
});
}

pub fn exclude<Q>(&mut self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeIndexOperand>),
{
let mut operand = Wrapper::<EdgeIndexOperand>::new(self.context.clone(), self.kind.clone());

query(&mut operand);

self.operations
.push(EdgeIndexOperation::Exclude { operand });
}
}

impl Wrapper<EdgeIndexOperand> {
Expand Down Expand Up @@ -652,4 +701,11 @@ impl Wrapper<EdgeIndexOperand> {
{
self.0.write_or_panic().eiter_or(either_query, or_query);
}

pub fn exclude<Q>(&self, query: Q)
where
Q: FnOnce(&mut Wrapper<EdgeIndexOperand>),
{
self.0.write_or_panic().exclude(query);
}
}
Loading

0 comments on commit a183c40

Please sign in to comment.