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();
|
||||||
|
// }
|
||||||
|
} |
@ -1,20 +1,19 @@ |
|||||||
//! Serialize atomic ID by fetching its value
|
//! Serialize atomic ID by fetching its value
|
||||||
|
|
||||||
use crate::id::ID; |
use crate::id::ID; |
||||||
use serde::{Serialize, Deserializer, Deserialize}; |
use serde::{Deserialize, Deserializer, Serialize}; |
||||||
|
|
||||||
pub fn serialize<S>(x: &atomic::Atomic<ID>, s: S) -> Result<S::Ok, S::Error> |
pub fn serialize<S>(x: &atomic::Atomic<ID>, s: S) -> Result<S::Ok, S::Error> |
||||||
where |
where |
||||||
S: serde::Serializer, |
S: serde::Serializer, |
||||||
{ |
{ |
||||||
x.load(atomic::Ordering::Relaxed) |
x.load(atomic::Ordering::Relaxed).serialize(s) |
||||||
.serialize(s) |
|
||||||
} |
} |
||||||
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<atomic::Atomic<ID>, D::Error> |
pub fn deserialize<'de, D>(deserializer: D) -> Result<atomic::Atomic<ID>, D::Error> |
||||||
where |
where |
||||||
D: Deserializer<'de> |
D: Deserializer<'de>, |
||||||
{ |
{ |
||||||
let id : ID = ID::deserialize(deserializer)?; |
let id: ID = ID::deserialize(deserializer)?; |
||||||
Ok(atomic::Atomic::new(id)) |
Ok(atomic::Atomic::new(id)) |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue