You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.2 KiB
200 lines
5.2 KiB
//! Helper traits and stuff for working with lists and iterators of objects
|
|
|
|
// Re-export itertools for convenience
|
|
pub use itertools;
|
|
|
|
use crate::{data, insert, model, update, ID};
|
|
|
|
use itertools::Itertools;
|
|
use std::collections::HashMap;
|
|
|
|
pub trait GetParent {
|
|
fn get_parent(&self) -> ID;
|
|
}
|
|
|
|
macro_rules! impl_get_parent {
|
|
($($struct:ty),+) => {
|
|
$(
|
|
impl GetParent for $struct {
|
|
fn get_parent(&self) -> ID { self.object }
|
|
}
|
|
impl GetParent for &$struct {
|
|
fn get_parent(&self) -> ID { self.object }
|
|
}
|
|
impl GetParent for &&$struct {
|
|
fn get_parent(&self) -> ID { self.object }
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
|
|
impl_get_parent!(
|
|
data::Value, data::Relation,
|
|
model::RelationModel, model::PropertyModel);
|
|
|
|
pub trait GetModelID {
|
|
fn get_model_id(&self) -> ID;
|
|
}
|
|
|
|
macro_rules! impl_get_model_id {
|
|
($($struct:ty),+) => {
|
|
$(
|
|
impl GetModelID for $struct {
|
|
fn get_model_id(&self) -> ID { self.model }
|
|
}
|
|
impl GetModelID for &$struct {
|
|
fn get_model_id(&self) -> ID { self.model }
|
|
}
|
|
impl GetModelID for &&$struct {
|
|
fn get_model_id(&self) -> ID { self.model }
|
|
}
|
|
)+
|
|
}
|
|
}
|
|
|
|
impl_get_model_id!(
|
|
data::Object, data::Value, data::Relation,
|
|
insert::InsertRel, insert::InsertValue, insert::InsertObj,
|
|
update::UpsertRelation, update::UpsertValue);
|
|
|
|
// This would be nice, but doesn't work
|
|
|
|
//
|
|
// pub struct FilterOfParent<'a, S: 'a> { iter: S, parent: ID, marker : std::marker::PhantomData<&'a S> }
|
|
//
|
|
// // impl<'a, V: GetParent + 'a, S: Iterator<Item=&'a V>> Iterator for FilterOfParent<S> {
|
|
// // type Item = &'a V;
|
|
// //
|
|
// // #[inline]
|
|
// // fn next(&mut self) -> Option<Self::Item> {
|
|
// // let parent = self.parent;
|
|
// // self.iter.find(|x| x.get_parent() == parent)
|
|
// // }
|
|
// // }
|
|
//
|
|
// impl<'a, V: GetParent + 'a, S: Iterator<Item=V>> Iterator for FilterOfParent<'a, S> {
|
|
// type Item = V;
|
|
//
|
|
// #[inline]
|
|
// fn next(&mut self) -> Option<Self::Item> {
|
|
// let parent = self.parent;
|
|
// self.iter.find(|x| x.get_parent() == parent)
|
|
// }
|
|
// }
|
|
//
|
|
// pub trait WhereParent<'a>: Sized {
|
|
// fn where_parent(self, id: ID) -> FilterOfParent<'a, Self>;
|
|
// }
|
|
//
|
|
// impl<'a, V : 'a, S : 'a + Iterator<Item=V>> WhereParent<'a> for S {
|
|
// fn where_parent(self, id: ID) -> FilterOfParent<'a, Self> {
|
|
// FilterOfParent { iter: self, parent: id, marker: std::marker::PhantomData }
|
|
// }
|
|
// }
|
|
|
|
pub trait GroupByParent<'a, T: 'a + GetParent>: Sized {
|
|
fn group_by_parent(self) -> HashMap<ID, Vec<T>>;
|
|
}
|
|
|
|
impl<'a, T: 'a + GetParent, S: IntoIterator<Item = T>> GroupByParent<'a, T> for S {
|
|
#[inline]
|
|
fn group_by_parent(self) -> HashMap<ID, Vec<T>> {
|
|
self.into_iter().into_group_map_by(|v| v.get_parent())
|
|
}
|
|
}
|
|
|
|
pub trait GroupByModel<'a, T: 'a + GetModelID>: Sized {
|
|
fn group_by_model(self) -> HashMap<ID, Vec<T>>;
|
|
}
|
|
|
|
impl<'a, T: 'a + GetModelID, S: IntoIterator<Item = T>> GroupByModel<'a, T> for S {
|
|
#[inline]
|
|
fn group_by_model(self) -> HashMap<ID, Vec<T>> {
|
|
self.into_iter().into_group_map_by(|v| v.get_model_id())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::helpers::{GetParent, GroupByParent};
|
|
use crate::id::random_id;
|
|
use crate::ID;
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
struct Child(ID, &'static str);
|
|
|
|
impl GetParent for Child {
|
|
fn get_parent(&self) -> ID {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn group_vec() {
|
|
let parent1 = random_id();
|
|
let parent2 = random_id();
|
|
|
|
let vec = vec![
|
|
Child(parent1, "A"),
|
|
Child(parent2, "C"),
|
|
Child(parent1, "B"),
|
|
Child(parent2, "D"),
|
|
];
|
|
|
|
let mut grouped = vec.group_by_parent();
|
|
|
|
assert_eq!(2, grouped.len());
|
|
|
|
assert_eq!(
|
|
grouped.remove(&parent1).unwrap(),
|
|
vec![Child(parent1, "A"), Child(parent1, "B"),]
|
|
);
|
|
|
|
assert_eq!(
|
|
grouped.remove(&parent2).unwrap(),
|
|
vec![Child(parent2, "C"), Child(parent2, "D"),]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn group_iter() {
|
|
let parent1 = random_id();
|
|
let parent2 = random_id();
|
|
|
|
let vec = vec![
|
|
Child(parent1, "A"),
|
|
Child(parent2, "C"),
|
|
Child(parent1, "B"),
|
|
Child(parent2, "D"),
|
|
];
|
|
|
|
let mut grouped = vec.into_iter().group_by_parent();
|
|
|
|
assert_eq!(2, grouped.len());
|
|
|
|
assert_eq!(
|
|
grouped.remove(&parent1).unwrap(),
|
|
vec![Child(parent1, "A"), Child(parent1, "B"),]
|
|
);
|
|
|
|
assert_eq!(
|
|
grouped.remove(&parent2).unwrap(),
|
|
vec![Child(parent2, "C"), Child(parent2, "D"),]
|
|
);
|
|
}
|
|
|
|
// #[test]
|
|
// fn count_where_parent() {
|
|
// let parent1 = random_id();
|
|
// let parent2 = random_id();
|
|
//
|
|
// let vec = vec![
|
|
// Child(parent1, "A"),
|
|
// Child(parent2, "C"),
|
|
// Child(parent1, "B"),
|
|
// Child(parent2, "D"),
|
|
// ];
|
|
//
|
|
// let _ = vec.iter().where_parent(parent2).next();
|
|
// }
|
|
}
|
|
|