raphtory_api/core/storage/
timeindex.rs

1use chrono::{DateTime, Utc};
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std::{fmt, ops::Range};
5
6#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Ord, PartialOrd, Eq, Hash)]
7pub struct TimeIndexEntry(pub i64, pub usize);
8
9pub trait AsTime: fmt::Debug + Copy + Ord + Eq + Send + Sync + 'static {
10    fn t(&self) -> i64;
11
12    fn dt(&self) -> Option<DateTime<Utc>> {
13        let t = self.t();
14        DateTime::from_timestamp_millis(t)
15    }
16
17    fn range(w: Range<i64>) -> Range<Self>;
18
19    fn i(&self) -> usize {
20        0
21    }
22
23    fn new(t: i64, s: usize) -> Self;
24}
25
26pub trait TimeIndexLike<'a>: TimeIndexOps<'a> {
27    fn range_iter(
28        self,
29        w: Range<Self::IndexType>,
30    ) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a;
31
32    fn range_iter_rev(
33        self,
34        w: Range<Self::IndexType>,
35    ) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a;
36
37    fn range_count(&self, w: Range<Self::IndexType>) -> usize;
38
39    fn first_range(&self, w: Range<Self::IndexType>) -> Option<Self::IndexType> {
40        self.clone().range_iter(w).next()
41    }
42
43    fn last_range(&self, w: Range<Self::IndexType>) -> Option<Self::IndexType> {
44        self.clone().range_iter_rev(w).next()
45    }
46}
47
48pub trait TimeIndexOps<'a>: Sized + Clone + Send + Sync + 'a {
49    type IndexType: AsTime;
50    type RangeType: TimeIndexOps<'a, IndexType = Self::IndexType> + 'a;
51
52    fn active(&self, w: Range<Self::IndexType>) -> bool;
53
54    #[inline]
55    fn active_t(&self, w: Range<i64>) -> bool {
56        self.active(<Self::IndexType as AsTime>::range(w))
57    }
58
59    fn range(&self, w: Range<Self::IndexType>) -> Self::RangeType;
60
61    fn range_t(&self, w: Range<i64>) -> Self::RangeType {
62        self.range(<Self::IndexType as AsTime>::range(w))
63    }
64
65    fn first_t(&self) -> Option<i64> {
66        self.first().map(|ti| ti.t())
67    }
68
69    fn first(&self) -> Option<Self::IndexType> {
70        self.clone().iter().next()
71    }
72
73    fn last_t(&self) -> Option<i64> {
74        self.last().map(|ti| ti.t())
75    }
76
77    fn last(&self) -> Option<Self::IndexType> {
78        self.clone().iter_rev().next()
79    }
80
81    fn iter(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a;
82
83    fn iter_rev(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a;
84
85    fn iter_t(self) -> impl Iterator<Item = i64> + Send + Sync + 'a {
86        self.iter().map(|time| time.t())
87    }
88
89    fn iter_rev_t(self) -> impl Iterator<Item = i64> + Send + Sync + 'a {
90        self.iter_rev().map(|time| time.t())
91    }
92
93    fn len(&self) -> usize;
94
95    fn is_empty(&self) -> bool {
96        self.clone().iter().next().is_none()
97    }
98
99    fn merge<R: TimeIndexOps<'a, IndexType = Self::IndexType>>(
100        self,
101        other: R,
102    ) -> MergedTimeIndex<Self, R> {
103        MergedTimeIndex(self, other)
104    }
105}
106
107impl<'a, T: TimeIndexOps<'a> + Clone> TimeIndexOps<'a> for &'a T {
108    type IndexType = T::IndexType;
109    type RangeType = T::RangeType;
110
111    fn active(&self, w: Range<Self::IndexType>) -> bool {
112        T::active(*self, w)
113    }
114
115    fn range(&self, w: Range<Self::IndexType>) -> Self::RangeType {
116        T::range(*self, w)
117    }
118
119    fn iter(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
120        T::iter(self.clone())
121    }
122
123    fn iter_rev(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
124        T::iter_rev(self.clone())
125    }
126
127    fn len(&self) -> usize {
128        T::len(*self)
129    }
130}
131
132#[derive(Copy, Clone, Debug)]
133pub struct MergedTimeIndex<L, R>(pub L, pub R);
134
135impl<'a, L: TimeIndexOps<'a>, R: TimeIndexOps<'a, IndexType = L::IndexType>> TimeIndexOps<'a>
136    for MergedTimeIndex<L, R>
137{
138    type IndexType = L::IndexType;
139    type RangeType = MergedTimeIndex<L::RangeType, R::RangeType>;
140
141    fn active(&self, w: Range<Self::IndexType>) -> bool {
142        self.0.active(w.clone()) || self.1.active(w.clone())
143    }
144
145    fn range(&self, w: Range<Self::IndexType>) -> Self::RangeType {
146        MergedTimeIndex(self.0.range(w.clone()), self.1.range(w.clone()))
147    }
148
149    fn first(&self) -> Option<Self::IndexType> {
150        self.0.first().into_iter().chain(self.1.first()).min()
151    }
152
153    fn last(&self) -> Option<Self::IndexType> {
154        self.0.last().into_iter().chain(self.1.last()).max()
155    }
156
157    fn iter(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
158        self.0.iter().merge(self.1.iter())
159    }
160
161    fn iter_rev(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
162        self.0.iter_rev().merge_by(self.1.iter_rev(), |l, r| l >= r)
163    }
164
165    fn len(&self) -> usize {
166        self.0.len() + self.1.len()
167    }
168
169    fn is_empty(&self) -> bool {
170        self.0.is_empty() && self.1.is_empty()
171    }
172}
173
174impl From<i64> for TimeIndexEntry {
175    fn from(value: i64) -> Self {
176        Self::start(value)
177    }
178}
179
180impl TimeIndexEntry {
181    pub const MIN: TimeIndexEntry = TimeIndexEntry(i64::MIN, 0);
182
183    pub const MAX: TimeIndexEntry = TimeIndexEntry(i64::MAX, usize::MAX);
184    pub fn new(t: i64, s: usize) -> Self {
185        Self(t, s)
186    }
187
188    pub fn start(t: i64) -> Self {
189        Self(t, 0)
190    }
191
192    pub fn next(&self) -> Self {
193        if self.1 < usize::MAX {
194            Self(self.0, self.1 + 1)
195        } else if self.0 < i64::MAX {
196            Self(self.0 + 1, 0)
197        } else {
198            *self
199        }
200    }
201
202    pub fn previous(&self) -> Self {
203        if self.1 > 0 {
204            Self(self.0, self.1 - 1)
205        } else if self.0 > i64::MIN {
206            Self(self.0 - 1, 0)
207        } else {
208            *self
209        }
210    }
211
212    pub fn end(t: i64) -> Self {
213        Self(t, usize::MAX)
214    }
215}
216
217impl AsTime for i64 {
218    fn t(&self) -> i64 {
219        *self
220    }
221
222    fn range(w: Range<i64>) -> Range<Self> {
223        w
224    }
225
226    fn new(t: i64, _s: usize) -> Self {
227        t
228    }
229}
230
231impl AsTime for TimeIndexEntry {
232    fn t(&self) -> i64 {
233        self.0
234    }
235    fn range(w: Range<i64>) -> Range<Self> {
236        Self::start(w.start)..Self::start(w.end)
237    }
238
239    fn i(&self) -> usize {
240        self.1
241    }
242
243    fn new(t: i64, s: usize) -> Self {
244        Self(t, s)
245    }
246}