parent
e810724cd1
commit
3997381748
@ -0,0 +1,200 @@ |
||||
//! 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();
|
||||
// }
|
||||
} |
Loading…
Reference in new issue