1use crate::storage::timeindex::{AsTime, EventTime, TimeIndexOps, TimeIndexWindow};
2use either::Either;
3use iter_enum::{DoubleEndedIterator, ExactSizeIterator, Extend, FusedIterator, Iterator};
4use raphtory_api::core::storage::{sorted_vec_map::SVM, timeindex::TimeIndexLike};
5use serde::{Deserialize, Serialize};
6use std::{collections::BTreeMap, fmt::Debug, ops::Range};
7
8#[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize)]
9pub enum TCell<A> {
11 #[default]
12 Empty,
13 TCell1(EventTime, A),
14 TCellCap(SVM<EventTime, A>),
15 TCellN(BTreeMap<EventTime, A>),
16}
17
18#[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, Extend)]
19enum TCellVariants<Empty, TCell1, TCellCap, TCellN> {
20 Empty(Empty),
21 TCell1(TCell1),
22 TCellCap(TCellCap),
23 TCellN(TCellN),
24}
25
26const BTREE_CUTOFF: usize = 128;
27
28impl<A: PartialEq> TCell<A> {
29 pub fn new(t: EventTime, value: A) -> Self {
30 TCell::TCell1(t, value)
31 }
32
33 #[inline]
34 pub fn set(&mut self, t: EventTime, value: A) {
35 match self {
36 TCell::Empty => {
37 *self = TCell::TCell1(t, value);
38 }
39 TCell::TCell1(t0, v) => {
40 if &t != t0 {
41 if let TCell::TCell1(t0, value0) = std::mem::take(self) {
42 let mut svm = SVM::new();
43 svm.insert(t, value);
44 svm.insert(t0, value0);
45 *self = TCell::TCellCap(svm)
46 }
47 } else {
48 *v = value
49 }
50 }
51 TCell::TCellCap(svm) => {
52 if svm.len() < BTREE_CUTOFF {
53 svm.insert(t, value);
54 } else {
55 let svm = std::mem::take(svm);
56 let mut btm: BTreeMap<EventTime, A> = BTreeMap::new();
57 for (k, v) in svm.into_iter() {
58 btm.insert(k, v);
59 }
60 btm.insert(t, value);
61 *self = TCell::TCellN(btm)
62 }
63 }
64 TCell::TCellN(btm) => {
65 btm.insert(t, value);
66 }
67 }
68 }
69
70 pub fn at(&self, ti: &EventTime) -> Option<&A> {
71 match self {
72 TCell::Empty => None,
73 TCell::TCell1(t, v) => (t == ti).then_some(v),
74 TCell::TCellCap(svm) => svm.get(ti),
75 TCell::TCellN(btm) => btm.get(ti),
76 }
77 }
78}
79impl<A: Sync + Send> TCell<A> {
80 pub fn iter(&self) -> impl DoubleEndedIterator<Item = (&EventTime, &A)> + Send + Sync {
81 match self {
82 TCell::Empty => TCellVariants::Empty(std::iter::empty()),
83 TCell::TCell1(t, value) => TCellVariants::TCell1(std::iter::once((t, value))),
84 TCell::TCellCap(svm) => TCellVariants::TCellCap(svm.iter()),
85 TCell::TCellN(btm) => TCellVariants::TCellN(btm.iter()),
86 }
87 }
88
89 pub fn iter_t(&self) -> impl DoubleEndedIterator<Item = (i64, &A)> + Send + Sync {
90 self.iter().map(|(t, a)| (t.t(), a))
91 }
92
93 pub fn iter_window(
94 &self,
95 r: Range<EventTime>,
96 ) -> impl DoubleEndedIterator<Item = (&EventTime, &A)> + Send + Sync {
97 match self {
98 TCell::Empty => TCellVariants::Empty(std::iter::empty()),
99 TCell::TCell1(t, value) => TCellVariants::TCell1(if r.contains(t) {
100 Either::Left(std::iter::once((t, value)))
101 } else {
102 Either::Right(std::iter::empty())
103 }),
104 TCell::TCellCap(svm) => TCellVariants::TCellCap(svm.range(r)),
105 TCell::TCellN(btm) => TCellVariants::TCellN(btm.range(r)),
106 }
107 }
108
109 pub fn iter_window_t(
110 &self,
111 r: Range<i64>,
112 ) -> impl DoubleEndedIterator<Item = (i64, &A)> + Send + Sync + '_ {
113 self.iter_window(EventTime::range(r))
114 .map(|(t, a)| (t.t(), a))
115 }
116
117 pub fn last_before(&self, t: EventTime) -> Option<(EventTime, &A)> {
118 match self {
119 TCell::Empty => None,
120 TCell::TCell1(t2, v) => (*t2 < t).then_some((*t2, v)),
121 TCell::TCellCap(map) => map
122 .range(EventTime::MIN..t)
123 .next_back()
124 .map(|(ti, v)| (*ti, v)),
125 TCell::TCellN(map) => map
126 .range(EventTime::MIN..t)
127 .next_back()
128 .map(|(ti, v)| (*ti, v)),
129 }
130 }
131
132 pub fn last_value(&self) -> Option<(EventTime, &A)> {
133 match self {
134 TCell::Empty => None,
135 TCell::TCell1(t, v) => Some((*t, v)),
136 TCell::TCellCap(map) => map.last_key_value().map(|(t, v)| (*t, v)),
137 TCell::TCellN(map) => map.last_key_value().map(|(t, v)| (*t, v)),
138 }
139 }
140
141 #[inline]
142 pub fn len(&self) -> usize {
143 match self {
144 TCell::Empty => 0,
145 TCell::TCell1(_, _) => 1,
146 TCell::TCellCap(v) => v.len(),
147 TCell::TCellN(v) => v.len(),
148 }
149 }
150
151 #[inline]
152 pub fn is_empty(&self) -> bool {
153 self.len() == 0
154 }
155}
156
157impl<'a, A: Send + Sync> TimeIndexOps<'a> for &'a TCell<A> {
158 type IndexType = EventTime;
159 type RangeType = TimeIndexWindow<'a, Self::IndexType, TCell<A>>;
160
161 #[inline]
162 fn active(&self, w: Range<Self::IndexType>) -> bool {
163 match self {
164 TCell::Empty => false,
165 TCell::TCell1(time_index_entry, _) => w.contains(time_index_entry),
166 TCell::TCellCap(svm) => svm.active(w),
167 TCell::TCellN(btree_map) => btree_map.range(w).next().is_some(),
168 }
169 }
170
171 fn range(&self, w: Range<Self::IndexType>) -> Self::RangeType {
172 let range = match self {
173 TCell::Empty => TimeIndexWindow::Empty,
174 TCell::TCell1(t, _) => {
175 if w.contains(t) {
176 TimeIndexWindow::All(*self)
177 } else {
178 TimeIndexWindow::Empty
179 }
180 }
181 _ => {
182 if let Some(min_val) = self.first() {
183 if let Some(max_val) = self.last() {
184 if min_val >= w.start && max_val < w.end {
185 TimeIndexWindow::All(*self)
186 } else {
187 TimeIndexWindow::Range {
188 timeindex: *self,
189 range: w,
190 }
191 }
192 } else {
193 TimeIndexWindow::Empty
194 }
195 } else {
196 TimeIndexWindow::Empty
197 }
198 }
199 };
200 range
201 }
202
203 fn first(&self) -> Option<Self::IndexType> {
204 match self {
205 TCell::Empty => None,
206 TCell::TCell1(t, _) => Some(*t),
207 TCell::TCellCap(svm) => svm.first_key_value().map(|(ti, _)| *ti),
208 TCell::TCellN(btm) => btm.first_key_value().map(|(ti, _)| *ti),
209 }
210 }
211
212 fn last(&self) -> Option<Self::IndexType> {
213 match self {
214 TCell::Empty => None,
215 TCell::TCell1(t, _) => Some(*t),
216 TCell::TCellCap(svm) => svm.last_key_value().map(|(ti, _)| *ti),
217 TCell::TCellN(btm) => btm.last_key_value().map(|(ti, _)| *ti),
218 }
219 }
220
221 #[allow(refining_impl_trait)]
222 fn iter(self) -> impl DoubleEndedIterator<Item = Self::IndexType> + Send + Sync + 'a {
223 match self {
224 TCell::Empty => TCellVariants::Empty(std::iter::empty()),
225 TCell::TCell1(t, _) => TCellVariants::TCell1(std::iter::once(*t)),
226 TCell::TCellCap(svm) => TCellVariants::TCellCap(svm.iter().map(|(ti, _)| *ti)),
227 TCell::TCellN(btm) => TCellVariants::TCellN(btm.keys().copied()),
228 }
229 }
230
231 fn iter_rev(self) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
232 TimeIndexOps::iter(self).rev()
233 }
234
235 fn len(&self) -> usize {
236 match self {
237 TCell::Empty => 0,
238 TCell::TCell1(_, _) => 1,
239 TCell::TCellCap(svm) => svm.len(),
240 TCell::TCellN(btm) => btm.len(),
241 }
242 }
243}
244
245impl<'a, A: Send + Sync> TimeIndexLike<'a> for &'a TCell<A> {
246 #[allow(refining_impl_trait)]
247 fn range_iter(
248 self,
249 w: Range<Self::IndexType>,
250 ) -> impl DoubleEndedIterator<Item = Self::IndexType> + Send + Sync + 'a {
251 self.iter_window(w).map(|(ti, _)| *ti)
252 }
253
254 fn range_iter_rev(
255 self,
256 w: Range<Self::IndexType>,
257 ) -> impl Iterator<Item = Self::IndexType> + Send + Sync + 'a {
258 self.range_iter(w).rev()
259 }
260
261 fn range_count(&self, w: Range<Self::IndexType>) -> usize {
262 match self {
263 TCell::Empty => 0,
264 TCell::TCell1(t, _) => {
265 if w.contains(t) {
266 1
267 } else {
268 0
269 }
270 }
271 TCell::TCellCap(ts) => ts.range(w).count(),
272 TCell::TCellN(ts) => ts.range(w).count(),
273 }
274 }
275
276 fn last_range(&self, w: Range<Self::IndexType>) -> Option<Self::IndexType> {
277 self.iter_window(w).next_back().map(|(ti, _)| *ti)
278 }
279}
280
281#[cfg(test)]
282mod tcell_tests {
283 use super::TCell;
284 use crate::storage::timeindex::{AsTime, EventTime};
285
286 #[test]
287 fn set_new_value_for_tcell_initialized_as_empty() {
288 let mut tcell = TCell::default();
289 tcell.set(EventTime::start(16), String::from("lobster"));
290
291 assert_eq!(
292 tcell.iter().map(|(_, v)| v).collect::<Vec<_>>(),
293 vec!["lobster"]
294 );
295 }
296
297 #[test]
298 fn every_new_update_to_the_same_prop_is_recorded_as_history() {
299 let mut tcell = TCell::new(EventTime::start(1), "Pometry");
300 tcell.set(EventTime::start(2), "Pometry Inc.");
301
302 assert_eq!(
303 tcell.iter_t().collect::<Vec<_>>(),
304 vec![(1, &"Pometry"), (2, &"Pometry Inc."),]
305 );
306 }
307
308 #[test]
309 fn new_update_with_the_same_time_to_a_prop_is_ignored() {
310 let mut tcell = TCell::new(EventTime::start(1), "Pometry");
311 tcell.set(EventTime::start(1), "Pometry Inc.");
312
313 assert_eq!(
314 tcell.iter_t().collect::<Vec<_>>(),
315 vec![(1, &"Pometry Inc.")]
316 );
317 }
318
319 #[test]
320 fn updates_to_prop_can_be_iterated() {
321 let tcell: TCell<String> = TCell::default();
322
323 let actual = tcell.iter().collect::<Vec<_>>();
324 let expected = vec![];
325 assert_eq!(actual, expected);
326
327 assert_eq!(tcell.iter_t().collect::<Vec<_>>(), vec![]);
328
329 let tcell = TCell::new(EventTime::start(3), "Pometry");
330
331 assert_eq!(
332 tcell.iter().collect::<Vec<_>>(),
333 vec![(&EventTime::start(3), &"Pometry")]
334 );
335
336 assert_eq!(tcell.iter_t().collect::<Vec<_>>(), vec![(3, &"Pometry")]);
337
338 let mut tcell = TCell::new(EventTime::start(2), "Pometry");
339 tcell.set(EventTime::start(1), "Inc. Pometry");
340
341 assert_eq!(
342 tcell.iter_t().collect::<Vec<_>>(),
344 vec![(1, &"Inc. Pometry"), (2, &"Pometry"),]
345 );
346
347 assert_eq!(
348 tcell.iter().collect::<Vec<_>>(),
350 vec![
351 (&EventTime::start(1), &"Inc. Pometry"),
352 (&EventTime::start(2), &"Pometry")
353 ]
354 );
355
356 let mut tcell: TCell<i64> = TCell::default();
357 for n in 1..130 {
358 tcell.set(EventTime::start(n), n)
359 }
360
361 assert_eq!(tcell.iter_t().count(), 129);
362
363 assert_eq!(tcell.iter().count(), 129)
364 }
365
366 #[test]
367 fn updates_to_prop_can_be_window_iterated() {
368 let tcell: TCell<String> = TCell::default();
369
370 let actual = tcell
371 .iter_window(EventTime::MIN..EventTime::MAX)
372 .collect::<Vec<_>>();
373 let expected = vec![];
374 assert_eq!(actual, expected);
375
376 assert_eq!(
377 tcell.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
378 vec![]
379 );
380
381 let tcell = TCell::new(EventTime::start(3), "Pometry");
382
383 assert_eq!(
384 tcell
385 .iter_window(EventTime::range(3..4))
386 .collect::<Vec<_>>(),
387 vec![(&EventTime(3, 0), &"Pometry")]
388 );
389
390 assert_eq!(
391 tcell.iter_window_t(3..4).collect::<Vec<_>>(),
392 vec![(3, &"Pometry")]
393 );
394
395 let mut tcell = TCell::new(EventTime::start(3), "Pometry");
396 tcell.set(EventTime::start(1), "Pometry Inc.");
397 tcell.set(EventTime::start(2), "Raphtory");
398
399 let one = EventTime::start(1);
400 let two = EventTime::start(2);
401 let three = EventTime::start(3);
402
403 assert_eq!(
404 tcell.iter_window_t(2..3).collect::<Vec<_>>(),
405 vec![(2, &"Raphtory")]
406 );
407
408 let expected = vec![];
409 assert_eq!(
410 tcell
411 .iter_window(EventTime::range(4..5))
412 .collect::<Vec<_>>(),
413 expected
414 );
415
416 assert_eq!(
417 tcell
418 .iter_window(EventTime::range(1..i64::MAX))
419 .collect::<Vec<_>>(),
420 vec![
421 (&one, &"Pometry Inc."),
422 (&two, &"Raphtory"),
423 (&three, &"Pometry")
424 ]
425 );
426
427 assert_eq!(
428 tcell
429 .iter_window(EventTime::range(3..i64::MAX))
430 .collect::<Vec<_>>(),
431 vec![(&three, &"Pometry")]
432 );
433
434 assert_eq!(
435 tcell
436 .iter_window(EventTime::range(2..i64::MAX))
437 .collect::<Vec<_>>(),
438 vec![(&two, &"Raphtory"), (&three, &"Pometry")]
439 );
440
441 let expected = vec![];
442 assert_eq!(
443 tcell
444 .iter_window(EventTime::range(5..i64::MAX))
445 .collect::<Vec<_>>(),
446 expected
447 );
448
449 assert_eq!(
450 tcell
451 .iter_window(EventTime::range(i64::MIN..4))
452 .collect::<Vec<_>>(),
453 vec![
454 (&one, &"Pometry Inc."),
455 (&two, &"Raphtory"),
456 (&three, &"Pometry")
457 ]
458 );
459
460 let expected = vec![];
461 assert_eq!(
462 tcell
463 .iter_window(EventTime::range(i64::MIN..1))
464 .collect::<Vec<_>>(),
465 expected
466 );
467
468 let mut tcell: TCell<i64> = TCell::default();
469 for n in 1..130 {
470 tcell.set(EventTime::start(n), n)
471 }
472
473 assert_eq!(tcell.iter_window_t(i64::MIN..i64::MAX).count(), 129);
474
475 assert_eq!(
476 tcell
477 .iter_window(EventTime::range(i64::MIN..i64::MAX))
478 .count(),
479 129
480 )
481 }
482}