use crate::{
core::{
storage::timeindex::{AsTime, EventTime},
utils::iter::GenLockedIter,
},
db::{
api::{
properties::{internal::InternalPropertiesOps, TemporalPropertyView},
state::{
ops,
ops::{node::NodeOp, HistoryOp, NodeFilterOp},
LazyNodeState,
},
view::{
internal::{EdgeTimeSemanticsOps, NodeTimeSemanticsOps},
BaseNodeViewOps, BoxableGraphView, BoxedLIter, IntoDynBoxed,
},
},
graph::{
edge::{edge_valid_layer, EdgeView},
node::NodeView,
path::{PathFromGraph, PathFromNode},
views::layer_graph::LayeredGraph,
},
},
prelude::*,
};
use chrono::{DateTime, Utc};
use itertools::Itertools;
use raphtory_api::{
core::{entities::LayerIds, storage::timeindex::TimeError},
iter::BoxedIter,
};
use rayon::iter::ParallelIterator;
use std::{iter, marker::PhantomData, sync::Arc};
pub trait InternalHistoryOps: Send + Sync {
fn iter(&self) -> BoxedLIter<'_, EventTime>;
fn iter_rev(&self) -> BoxedLIter<'_, EventTime>;
fn earliest_time(&self) -> Option<EventTime>;
fn latest_time(&self) -> Option<EventTime>;
fn first(&self) -> Option<EventTime> {
self.iter().next()
}
fn last(&self) -> Option<EventTime> {
self.iter_rev().next()
}
fn len(&self) -> usize {
self.iter().count()
}
}
pub trait IntoArcDynHistoryOps: InternalHistoryOps + Sized + 'static {
fn into_arc_dyn(self) -> Arc<dyn InternalHistoryOps> {
Arc::new(self)
}
}
#[derive(Debug, Clone, Copy)]
pub struct History<'a, T>(pub T, PhantomData<&'a T>);
impl<'a, T: InternalHistoryOps + 'a> History<'a, T> {
pub fn new(item: T) -> Self {
Self(item, PhantomData)
}
pub fn reverse(self) -> History<'a, ReversedHistoryOps<T>> {
History(ReversedHistoryOps(self.0), PhantomData)
}
pub fn t(self) -> HistoryTimestamp<T> {
HistoryTimestamp(self.0)
}
pub fn dt(self) -> HistoryDateTime<T> {
HistoryDateTime(self.0)
}
pub fn event_id(self) -> HistoryEventId<T> {
HistoryEventId(self.0)
}
pub fn intervals(self) -> Intervals<T> {
Intervals(self.0)
}
pub fn merge<R: InternalHistoryOps>(self, right: History<R>) -> History<MergedHistory<T, R>> {
History::new(MergedHistory::new(self.0, right.0))
}
fn into_iter_rev(self) -> BoxedLIter<'a, EventTime> {
GenLockedIter::from(self.0, |item| item.iter_rev()).into_dyn_boxed()
}
pub fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter()
}
pub fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter_rev()
}
pub fn collect(&self) -> Vec<EventTime> {
self.0.iter().collect_vec()
}
pub fn collect_rev(&self) -> Vec<EventTime> {
self.0.iter_rev().collect_vec()
}
pub fn is_empty(&self) -> bool {
self.iter().next().is_none()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn earliest_time(&self) -> Option<EventTime> {
self.0.earliest_time()
}
pub fn latest_time(&self) -> Option<EventTime> {
self.0.latest_time()
}
pub fn first(&self) -> Option<EventTime> {
self.0.first()
}
pub fn last(&self) -> Option<EventTime> {
self.0.last()
}
pub fn as_ref(&self) -> History<'_, &T> {
History::new(&self.0)
}
pub fn print(&self, prelude: &str) {
println!("{}{:?}", prelude, self.0.iter().collect::<Vec<_>>());
}
}
impl<'a, 'b, T: InternalHistoryOps + Clone + 'b> History<'a, &'a T> {
pub fn cloned(&self) -> History<'b, T> {
History::new(self.0.clone())
}
}
impl History<'_, EmptyHistory> {
pub fn create_empty() -> Self {
History::new(EmptyHistory)
}
}
impl<T: IntoArcDynHistoryOps> History<'_, T> {
pub fn into_arc_dyn(self) -> History<'static, Arc<dyn InternalHistoryOps>> {
History::new(self.0.into_arc_dyn())
}
}
impl<'a, T: InternalHistoryOps + 'a> IntoIterator for History<'a, T> {
type Item = EventTime;
type IntoIter = BoxedLIter<'a, EventTime>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self.0, |item| item.iter()).into_dyn_boxed()
}
}
impl<'b, T: InternalHistoryOps + 'b, L, I: Copy> PartialEq<L> for History<'b, T>
where
for<'a> &'a L: IntoIterator<Item = &'a I>,
EventTime: PartialEq<I>,
{
fn eq(&self, other: &L) -> bool {
self.iter().eq(other.into_iter().copied())
}
}
impl<'a, T: InternalHistoryOps + 'a> PartialEq for History<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<'a, T: InternalHistoryOps + 'a> Eq for History<'a, T> {}
impl<T: InternalHistoryOps + ?Sized> InternalHistoryOps for Box<T> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
T::iter(self)
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
T::iter_rev(self)
}
fn earliest_time(&self) -> Option<EventTime> {
T::earliest_time(self)
}
fn latest_time(&self) -> Option<EventTime> {
T::latest_time(self)
}
fn first(&self) -> Option<EventTime> {
T::first(self)
}
fn last(&self) -> Option<EventTime> {
T::last(self)
}
fn len(&self) -> usize {
T::len(self)
}
}
impl<T: InternalHistoryOps + 'static> IntoArcDynHistoryOps for Box<T> {
fn into_arc_dyn(self) -> Arc<dyn InternalHistoryOps> {
Arc::from(self as Box<dyn InternalHistoryOps>)
}
}
impl IntoArcDynHistoryOps for Box<dyn InternalHistoryOps> {
fn into_arc_dyn(self) -> Arc<dyn InternalHistoryOps> {
Arc::from(self)
}
}
impl<T: InternalHistoryOps + ?Sized> InternalHistoryOps for Arc<T> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
T::iter(self)
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
T::iter_rev(self)
}
fn earliest_time(&self) -> Option<EventTime> {
T::earliest_time(self)
}
fn latest_time(&self) -> Option<EventTime> {
T::latest_time(self)
}
fn first(&self) -> Option<EventTime> {
T::first(self)
}
fn last(&self) -> Option<EventTime> {
T::last(self)
}
fn len(&self) -> usize {
T::len(self)
}
}
impl<T: InternalHistoryOps + 'static> IntoArcDynHistoryOps for Arc<T> {
fn into_arc_dyn(self) -> Arc<dyn InternalHistoryOps> {
self
}
}
impl IntoArcDynHistoryOps for Arc<dyn InternalHistoryOps> {
fn into_arc_dyn(self) -> Arc<dyn InternalHistoryOps> {
self
}
}
impl<T: InternalHistoryOps + ?Sized> InternalHistoryOps for &T {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
T::iter(self)
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
T::iter_rev(self)
}
fn earliest_time(&self) -> Option<EventTime> {
T::earliest_time(self)
}
fn latest_time(&self) -> Option<EventTime> {
T::latest_time(self)
}
fn first(&self) -> Option<EventTime> {
T::first(self)
}
fn last(&self) -> Option<EventTime> {
T::last(self)
}
fn len(&self) -> usize {
T::len(self)
}
}
#[derive(Debug, Clone, Copy)]
pub struct MergedHistory<L, R> {
left: L,
right: R,
}
impl<L: InternalHistoryOps, R: InternalHistoryOps> MergedHistory<L, R> {
pub fn new(left: L, right: R) -> Self {
Self { left, right }
}
}
impl<L: InternalHistoryOps, R: InternalHistoryOps> InternalHistoryOps for MergedHistory<L, R> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.left.iter().merge(self.right.iter()).into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.left
.iter_rev()
.merge_by(self.right.iter_rev(), |a, b| a >= b)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
self.left.earliest_time().min(self.right.earliest_time())
}
fn latest_time(&self) -> Option<EventTime> {
self.left.latest_time().max(self.right.latest_time())
}
fn len(&self) -> usize {
self.left.len() + self.right.len()
}
}
impl<L: InternalHistoryOps + 'static, R: InternalHistoryOps + 'static> IntoArcDynHistoryOps
for MergedHistory<L, R>
{
}
#[derive(Clone)]
pub struct CompositeHistory<'a, T> {
history_objects: Box<[T]>,
phantom: PhantomData<&'a T>,
}
impl<'a, T: InternalHistoryOps + 'a> CompositeHistory<'a, T> {
pub fn new(history_objects: Vec<T>) -> Self {
Self {
history_objects: history_objects.into_boxed_slice(),
phantom: PhantomData,
}
}
}
pub fn compose_multiple_histories<'a, T: InternalHistoryOps + 'a>(
objects: impl IntoIterator<Item = History<'a, T>>,
) -> History<'a, CompositeHistory<'a, T>> {
History::new(CompositeHistory::new(
objects.into_iter().map(|h| h.0).collect(),
))
}
pub fn compose_history_from_items<'a, T: InternalHistoryOps + 'a>(
objects: impl IntoIterator<Item = T>,
) -> History<'a, CompositeHistory<'a, T>> {
History::new(CompositeHistory::new(objects.into_iter().collect()))
}
impl<'a, T: InternalHistoryOps + 'a> InternalHistoryOps for CompositeHistory<'a, T> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.history_objects
.iter()
.map(|object| object.iter())
.kmerge()
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.history_objects
.iter()
.map(|object| object.iter_rev())
.kmerge_by(|a, b| a >= b)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
self.history_objects
.iter()
.filter_map(|history| history.earliest_time())
.min()
}
fn latest_time(&self) -> Option<EventTime> {
self.history_objects
.iter()
.filter_map(|history| history.latest_time())
.max()
}
}
impl<T: InternalHistoryOps + 'static> IntoArcDynHistoryOps for CompositeHistory<'static, T> {}
#[derive(Debug, Clone, Copy)]
pub struct EmptyHistory;
impl InternalHistoryOps for EmptyHistory {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
iter::empty().into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
iter::empty().into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
None
}
fn latest_time(&self) -> Option<EventTime> {
None
}
fn first(&self) -> Option<EventTime> {
None
}
fn last(&self) -> Option<EventTime> {
None
}
fn len(&self) -> usize {
0
}
}
impl IntoArcDynHistoryOps for EmptyHistory {}
impl<'graph, G: GraphViewOps<'graph> + Send + Sync + Send + Sync> InternalHistoryOps
for NodeView<'graph, G>
{
fn iter(&self) -> BoxedLIter<'_, EventTime> {
let semantics = self.graph.node_time_semantics();
let node = self.graph.core_node(self.node);
GenLockedIter::from(node, move |node| {
semantics
.node_history(node.as_ref(), &self.graph)
.into_dyn_boxed()
})
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
let semantics = self.graph.node_time_semantics();
let node = self.graph.core_node(self.node);
GenLockedIter::from(node, move |node| {
semantics
.node_history_rev(node.as_ref(), &self.graph)
.into_dyn_boxed()
})
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
ops::EarliestTime {
view: self.graph().clone(),
}
.apply(self.graph.core_graph(), self.node)
}
fn latest_time(&self) -> Option<EventTime> {
ops::LatestTime {
view: self.graph().clone(),
}
.apply(self.graph.core_graph(), self.node)
}
}
impl<G: GraphViewOps<'static> + Send + Sync> IntoArcDynHistoryOps for NodeView<'static, G> {}
impl<G: BoxableGraphView + Clone> InternalHistoryOps for EdgeView<G> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
let g = &self.graph;
let e = self.edge;
if edge_valid_layer(g, e) {
match e.time() {
Some(t) => iter::once(t).into_dyn_boxed(),
None => {
let time_semantics = g.edge_time_semantics();
let edge = g.core_edge(e.pid());
match e.layer() {
None => GenLockedIter::from(edge, move |edge| {
time_semantics
.edge_history(edge.as_ref(), g, g.layer_ids())
.map(|(ti, _)| ti)
.into_dyn_boxed()
})
.into_dyn_boxed(),
Some(layer) => {
let layer_ids = LayerIds::One(layer);
GenLockedIter::from((edge, layer_ids), move |(edge, layer_ids)| {
time_semantics
.edge_history(edge.as_ref(), g, layer_ids)
.map(|(ti, _)| ti)
.into_dyn_boxed()
})
.into_dyn_boxed()
}
}
}
}
} else {
iter::empty().into_dyn_boxed()
}
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
let g = &self.graph;
let e = self.edge;
if edge_valid_layer(&g, e) {
match e.time() {
Some(t) => iter::once(t).into_dyn_boxed(),
None => {
let time_semantics = g.edge_time_semantics();
let edge = g.core_edge(e.pid());
match e.layer() {
None => GenLockedIter::from(edge, move |edge| {
time_semantics
.edge_history_rev(edge.as_ref(), g, g.layer_ids())
.map(|(ti, _)| ti)
.into_dyn_boxed()
})
.into_dyn_boxed(),
Some(layer) => {
let layer_ids = LayerIds::One(layer);
GenLockedIter::from((edge, layer_ids), move |(edge, layer_ids)| {
time_semantics
.edge_history_rev(edge.as_ref(), g, layer_ids)
.map(|(ti, _)| ti)
.into_dyn_boxed()
})
.into_dyn_boxed()
}
}
}
}
} else {
iter::empty().into_dyn_boxed()
}
}
fn earliest_time(&self) -> Option<EventTime> {
EdgeViewOps::earliest_time(self)
}
fn latest_time(&self) -> Option<EventTime> {
EdgeViewOps::latest_time(self)
}
fn len(&self) -> usize {
let g = &self.graph;
let e = self.edge;
if edge_valid_layer(g, e) {
match e.time() {
Some(_) => 1,
None => match e.layer() {
None => g
.edge_time_semantics()
.edge_exploded_count(g.core_edge(e.pid()).as_ref(), g),
Some(layer) => g.edge_time_semantics().edge_exploded_count(
g.core_edge(e.pid()).as_ref(),
LayeredGraph::new(g, LayerIds::One(layer)),
),
},
}
} else {
0
}
}
}
impl<G: BoxableGraphView + Clone + 'static> IntoArcDynHistoryOps for EdgeView<G> {}
impl<
'graph,
G: GraphViewOps<'graph>,
GH: GraphViewOps<'graph>,
F: NodeFilterOp + Clone + 'graph,
> InternalHistoryOps for LazyNodeState<'graph, HistoryOp<'graph, GH>, G, GH, F>
{
fn iter(&self) -> BoxedLIter<'_, EventTime> {
NodeStateOps::iter_values(self)
.map(|history| history.into_iter())
.kmerge()
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
NodeStateOps::iter_values(self)
.map(|history| history.into_iter_rev())
.kmerge_by(|a, b| a >= b)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
NodeStateOps::par_iter_values(self)
.filter_map(|history| history.earliest_time())
.min()
}
fn latest_time(&self) -> Option<EventTime> {
NodeStateOps::par_iter_values(self)
.filter_map(|history| history.latest_time())
.max()
}
}
impl<G: GraphViewOps<'static>, GH: GraphViewOps<'static>, F: NodeFilterOp + Clone + 'static>
IntoArcDynHistoryOps for LazyNodeState<'static, HistoryOp<'static, GH>, G, GH, F>
{
}
impl<P: InternalPropertiesOps> InternalHistoryOps for TemporalPropertyView<P> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.props
.temporal_iter(self.id)
.map(|(t, _)| t)
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.props
.temporal_iter_rev(self.id)
.map(|(t, _)| t)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
InternalHistoryOps::iter(self).next()
}
fn latest_time(&self) -> Option<EventTime> {
InternalHistoryOps::iter_rev(self).next()
}
}
impl<P: InternalPropertiesOps + 'static> IntoArcDynHistoryOps for TemporalPropertyView<P> {}
impl<'graph, G: GraphViewOps<'graph>> InternalHistoryOps for PathFromNode<'graph, G> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.iter()
.map(|nodeview| GenLockedIter::from(nodeview, move |node| node.iter()))
.kmerge()
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.iter()
.map(|nodeview| GenLockedIter::from(nodeview, move |node| node.iter_rev()))
.kmerge_by(|a, b| a >= b)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
self.iter()
.filter_map(|nodeview| InternalHistoryOps::earliest_time(&nodeview))
.min()
}
fn latest_time(&self) -> Option<EventTime> {
self.iter()
.filter_map(|nodeview| InternalHistoryOps::latest_time(&nodeview))
.max()
}
}
impl<G: GraphViewOps<'static>> IntoArcDynHistoryOps for PathFromNode<'static, G> {}
impl<'graph, G: GraphViewOps<'graph>> InternalHistoryOps for PathFromGraph<'graph, G> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.iter()
.map(|path_from_node| {
GenLockedIter::from(path_from_node, |item| InternalHistoryOps::iter(item))
})
.kmerge()
.into_dyn_boxed()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.iter()
.map(|path_from_node| {
GenLockedIter::from(path_from_node, |item| InternalHistoryOps::iter_rev(item))
})
.kmerge_by(|a, b| a >= b)
.into_dyn_boxed()
}
fn earliest_time(&self) -> Option<EventTime> {
self.iter()
.filter_map(|path_from_node| InternalHistoryOps::earliest_time(&path_from_node))
.min()
}
fn latest_time(&self) -> Option<EventTime> {
self.iter()
.filter_map(|path_from_node| InternalHistoryOps::latest_time(&path_from_node))
.max()
}
}
impl<G: GraphViewOps<'static>> IntoArcDynHistoryOps for PathFromGraph<'static, G> {}
#[derive(Debug, Clone, Copy)]
pub struct ReversedHistoryOps<T>(T);
impl<T: InternalHistoryOps> ReversedHistoryOps<T> {
pub fn new(item: T) -> Self {
Self(item)
}
}
impl<T: InternalHistoryOps> InternalHistoryOps for ReversedHistoryOps<T> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter_rev()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter()
}
fn earliest_time(&self) -> Option<EventTime> {
self.0.earliest_time()
}
fn latest_time(&self) -> Option<EventTime> {
self.0.latest_time()
}
fn len(&self) -> usize {
self.0.len()
}
}
impl<T: InternalHistoryOps + 'static> IntoArcDynHistoryOps for ReversedHistoryOps<T> {}
#[derive(Debug, Clone, Copy)]
pub struct HistoryTimestamp<T>(pub(crate) T);
impl<T: InternalHistoryOps> HistoryTimestamp<T> {
pub fn new(item: T) -> Self {
Self(item)
}
pub fn iter(&self) -> BoxedLIter<'_, i64> {
self.0.iter().map(|t| t.0).into_dyn_boxed()
}
pub fn iter_rev(&self) -> BoxedLIter<'_, i64> {
self.0.iter_rev().map(|t| t.0).into_dyn_boxed()
}
pub fn collect(&self) -> Vec<i64> {
self.0.iter().map(|t| t.0).collect()
}
pub fn collect_rev(&self) -> Vec<i64> {
self.0.iter_rev().map(|t| t.0).collect()
}
}
impl<T: InternalHistoryOps + 'static> IntoIterator for HistoryTimestamp<T> {
type Item = i64;
type IntoIter = BoxedIter<i64>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self, |item| item.iter()).into_dyn_boxed()
}
}
impl<'b, T: InternalHistoryOps + 'b, L, I: Copy> PartialEq<L> for HistoryTimestamp<T>
where
for<'a> &'a L: IntoIterator<Item = &'a I>,
i64: PartialEq<I>,
{
fn eq(&self, other: &L) -> bool {
self.iter().eq(other.into_iter().copied())
}
}
impl<'a, T: InternalHistoryOps + 'a> PartialEq for HistoryTimestamp<T> {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<'a, T: InternalHistoryOps + 'a> Eq for HistoryTimestamp<T> {}
#[derive(Debug, Clone, Copy)]
pub struct HistoryDateTime<T>(pub(crate) T);
impl<T: InternalHistoryOps> HistoryDateTime<T> {
pub fn new(item: T) -> Self {
Self(item)
}
pub fn iter(&self) -> BoxedLIter<'_, Result<DateTime<Utc>, TimeError>> {
self.0.iter().map(|t| t.dt()).into_dyn_boxed()
}
pub fn iter_rev(&self) -> BoxedLIter<'_, Result<DateTime<Utc>, TimeError>> {
self.0.iter_rev().map(|t| t.dt()).into_dyn_boxed()
}
pub fn collect(&self) -> Result<Vec<DateTime<Utc>>, TimeError> {
self.0
.iter()
.map(|x| x.dt())
.collect::<Result<Vec<_>, TimeError>>()
}
pub fn collect_rev(&self) -> Result<Vec<DateTime<Utc>>, TimeError> {
self.0
.iter_rev()
.map(|x| x.dt())
.collect::<Result<Vec<_>, TimeError>>()
}
}
impl<T: InternalHistoryOps + 'static> IntoIterator for HistoryDateTime<T> {
type Item = Result<DateTime<Utc>, TimeError>;
type IntoIter = BoxedIter<Result<DateTime<Utc>, TimeError>>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self, |item| item.iter()).into_dyn_boxed()
}
}
impl<'b, T: InternalHistoryOps + 'b, L, I: Copy> PartialEq<L> for HistoryDateTime<T>
where
for<'a> &'a L: IntoIterator<Item = &'a I>,
Result<DateTime<Utc>, TimeError>: PartialEq<I>,
{
fn eq(&self, other: &L) -> bool {
self.iter().eq(other.into_iter().copied())
}
}
impl<'a, T: InternalHistoryOps + 'a> PartialEq for HistoryDateTime<T> {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<'a, T: InternalHistoryOps + 'a> Eq for HistoryDateTime<T> {}
#[derive(Debug, Clone, Copy)]
pub struct HistoryEventId<T>(pub(crate) T);
impl<T: InternalHistoryOps> HistoryEventId<T> {
pub fn new(item: T) -> Self {
Self(item)
}
pub fn iter(&self) -> BoxedLIter<'_, usize> {
self.0.iter().map(|t| t.1).into_dyn_boxed()
}
pub fn iter_rev(&self) -> BoxedLIter<'_, usize> {
self.0.iter_rev().map(|t| t.1).into_dyn_boxed()
}
pub fn collect(&self) -> Vec<usize> {
self.0.iter().map(|t| t.1).collect()
}
pub fn collect_rev(&self) -> Vec<usize> {
self.0.iter_rev().map(|t| t.1).collect()
}
}
impl<T: InternalHistoryOps + 'static> IntoIterator for HistoryEventId<T> {
type Item = usize;
type IntoIter = BoxedIter<usize>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self, |item| item.iter()).into_dyn_boxed()
}
}
impl<'b, T: InternalHistoryOps + 'b, L, I: Copy> PartialEq<L> for HistoryEventId<T>
where
for<'a> &'a L: IntoIterator<Item = &'a I>,
usize: PartialEq<I>,
{
fn eq(&self, other: &L) -> bool {
self.iter().eq(other.into_iter().copied())
}
}
impl<'a, T: InternalHistoryOps + 'a> PartialEq for HistoryEventId<T> {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<'a, T: InternalHistoryOps + 'a> Eq for HistoryEventId<T> {}
#[derive(Debug, Clone, Copy)]
pub struct Intervals<T>(pub T);
impl<T: InternalHistoryOps> Intervals<T> {
pub fn new(item: T) -> Self {
Intervals(item)
}
pub fn collect(&self) -> Vec<i64> {
self.iter().collect()
}
pub fn collect_rev(&self) -> Vec<i64> {
self.iter_rev().collect()
}
pub fn iter(&self) -> BoxedLIter<'_, i64> {
self.0
.iter()
.map(|t| t.0)
.tuple_windows()
.map(|(w1, w2)| w2 - w1)
.into_dyn_boxed()
}
pub fn iter_rev(&self) -> BoxedLIter<'_, i64> {
self.0
.iter_rev()
.map(|t| t.0)
.tuple_windows()
.map(|(w1, w2)| w2 - w1)
.into_dyn_boxed()
}
pub fn mean(&self) -> Option<f64> {
if self.iter().next().is_none() {
return None;
}
let (len, sum) = self.iter().fold((0i64, 0f64), |(count, sum), item| {
(count + 1, sum + (item as f64))
});
Some(sum / len as f64)
}
pub fn median(&self) -> Option<i64> {
if self.iter().next().is_none() {
return None;
}
let mut intervals: Vec<i64> = self.iter().collect();
intervals.sort_unstable();
let mid = intervals.len() / 2;
if intervals.len() % 2 == 0 {
let mid_sum = intervals[mid - 1] + intervals[mid];
if mid_sum % 2 == 0 {
Some(mid_sum / 2)
} else {
Some((mid_sum / 2) + 1) }
} else {
Some(intervals[mid])
}
}
pub fn max(&self) -> Option<i64> {
self.iter().max()
}
pub fn min(&self) -> Option<i64> {
self.iter().min()
}
}
impl<T: InternalHistoryOps + 'static> IntoIterator for Intervals<T> {
type Item = i64;
type IntoIter = BoxedIter<i64>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self, |item| item.iter()).into_dyn_boxed()
}
}
impl<'b, T: InternalHistoryOps + 'b, L, I: Copy> PartialEq<L> for Intervals<T>
where
for<'a> &'a L: IntoIterator<Item = &'a I>,
i64: PartialEq<I>,
{
fn eq(&self, other: &L) -> bool {
self.iter().eq(other.into_iter().copied())
}
}
impl<'a, T: InternalHistoryOps + 'a> PartialEq for Intervals<T> {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
}
}
impl<'a, T: InternalHistoryOps + 'a> Eq for Intervals<T> {}
pub trait InternalDeletionOps: Send + Sync {
fn iter(&self) -> BoxedLIter<'_, EventTime>;
fn iter_rev(&self) -> BoxedLIter<'_, EventTime>;
fn earliest_time(&self) -> Option<EventTime>;
fn latest_time(&self) -> Option<EventTime>;
fn first(&self) -> Option<EventTime> {
self.iter().next()
}
fn last(&self) -> Option<EventTime> {
self.iter_rev().next()
}
fn len(&self) -> usize {
self.iter().count()
}
}
#[derive(Debug, Clone, Copy)]
pub struct DeletionHistory<T>(T);
impl<T: InternalDeletionOps> DeletionHistory<T> {
pub fn new(item: T) -> Self {
DeletionHistory(item)
}
}
impl<T: InternalDeletionOps> InternalHistoryOps for DeletionHistory<T> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter()
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
self.0.iter_rev()
}
fn earliest_time(&self) -> Option<EventTime> {
self.0.earliest_time()
}
fn latest_time(&self) -> Option<EventTime> {
self.0.latest_time()
}
}
impl<T: InternalDeletionOps + 'static> IntoArcDynHistoryOps for DeletionHistory<T> {}
impl<G: BoxableGraphView + Clone> InternalDeletionOps for EdgeView<G> {
fn iter(&self) -> BoxedLIter<'_, EventTime> {
let g = &self.graph;
let e = self.edge;
if edge_valid_layer(g, e) {
let time_semantics = g.edge_time_semantics();
let edge = g.core_edge(e.pid());
match e.time() {
Some(t) => {
let layer = e.layer().expect("exploded edge should have layer");
time_semantics
.edge_exploded_deletion(edge.as_ref(), g, t, layer)
.into_iter()
.into_dyn_boxed()
}
None => match e.layer() {
None => GenLockedIter::from(edge, move |edge| {
time_semantics
.edge_deletion_history(edge.as_ref(), g, g.layer_ids())
.map(|(t, _)| t)
.into_dyn_boxed()
})
.into_dyn_boxed(),
Some(layer) => {
if self.graph.layer_ids().contains(&layer) {
let layer_ids = LayerIds::One(layer);
GenLockedIter::from((edge, layer_ids), move |(edge, layer_ids)| {
time_semantics
.edge_deletion_history(edge.as_ref(), g, layer_ids)
.map(|(t, _)| t)
.into_dyn_boxed()
})
.into_dyn_boxed()
} else {
iter::empty().into_dyn_boxed()
}
}
},
}
} else {
iter::empty().into_dyn_boxed()
}
}
fn iter_rev(&self) -> BoxedLIter<'_, EventTime> {
let g = &self.graph;
let e = self.edge;
if edge_valid_layer(g, e) {
let time_semantics = g.edge_time_semantics();
let edge = g.core_edge(e.pid());
match e.time() {
Some(t) => {
let layer = e.layer().expect("exploded edge should have layer");
time_semantics
.edge_exploded_deletion(edge.as_ref(), g, t, layer)
.into_iter()
.into_dyn_boxed()
}
None => match e.layer() {
None => GenLockedIter::from(edge, move |edge| {
time_semantics
.edge_deletion_history_rev(edge.as_ref(), g, g.layer_ids())
.map(|(t, _)| t)
.into_dyn_boxed()
})
.into_dyn_boxed(),
Some(layer) => {
if self.graph.layer_ids().contains(&layer) {
let layer_ids = LayerIds::One(layer);
GenLockedIter::from((edge, layer_ids), move |(edge, layer_ids)| {
time_semantics
.edge_deletion_history_rev(edge.as_ref(), g, layer_ids)
.map(|(t, _)| t)
.into_dyn_boxed()
})
.into_dyn_boxed()
} else {
iter::empty().into_dyn_boxed()
}
}
},
}
} else {
iter::empty().into_dyn_boxed()
}
}
fn earliest_time(&self) -> Option<EventTime> {
InternalDeletionOps::iter(self).next()
}
fn latest_time(&self) -> Option<EventTime> {
InternalDeletionOps::iter_rev(self).next()
}
}