raphtory_api/core/storage/
timeindex.rs1use 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}