Skip to main content

raphtory_core/entities/properties/
tprop.rs

1use crate::{
2    entities::properties::tcell::TCell,
3    storage::{timeindex::EventTime, TPropColumn},
4};
5use bigdecimal::BigDecimal;
6use chrono::{DateTime, NaiveDateTime, Utc};
7use iter_enum::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
8#[cfg(feature = "arrow")]
9use raphtory_api::core::entities::properties::prop::PropArray;
10use raphtory_api::core::{
11    entities::properties::{
12        prop::{Prop, PropType},
13        tprop::TPropOps,
14    },
15    storage::arc_str::ArcStr,
16};
17use rustc_hash::FxHashMap;
18use serde::{Deserialize, Serialize};
19use std::{collections::HashMap, iter, ops::Range, sync::Arc};
20use thiserror::Error;
21
22#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
23pub enum TProp {
24    #[default]
25    Empty,
26    Str(TCell<ArcStr>),
27    U8(TCell<u8>),
28    U16(TCell<u16>),
29    I32(TCell<i32>),
30    I64(TCell<i64>),
31    U32(TCell<u32>),
32    U64(TCell<u64>),
33    F32(TCell<f32>),
34    F64(TCell<f64>),
35    Bool(TCell<bool>),
36    DTime(TCell<DateTime<Utc>>),
37    #[cfg(feature = "arrow")]
38    Array(TCell<PropArray>),
39    NDTime(TCell<NaiveDateTime>),
40    List(TCell<Arc<Vec<Prop>>>),
41    Map(TCell<Arc<FxHashMap<ArcStr, Prop>>>),
42    Decimal(TCell<BigDecimal>),
43}
44
45#[derive(Error, Debug)]
46#[error("Property type mismatch, expected {expected:?}, received {actual:?}")]
47pub struct IllegalPropType {
48    pub(crate) expected: PropType,
49    pub(crate) actual: PropType,
50}
51
52#[derive(Debug, Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator)]
53pub enum TPropVariants<
54    Empty,
55    Str,
56    U8,
57    U16,
58    I32,
59    I64,
60    U32,
61    U64,
62    F32,
63    F64,
64    Bool,
65    DTime,
66    #[cfg(feature = "arrow")] Array,
67    NDTime,
68    List,
69    Map,
70    Decimal,
71> {
72    Empty(Empty),
73    Str(Str),
74    U8(U8),
75    U16(U16),
76    I32(I32),
77    I64(I64),
78    U32(U32),
79    U64(U64),
80    F32(F32),
81    F64(F64),
82    Bool(Bool),
83    DTime(DTime),
84    #[cfg(feature = "arrow")]
85    Array(Array),
86    NDTime(NDTime),
87    List(List),
88    Map(Map),
89    Decimal(Decimal),
90}
91
92#[derive(Copy, Clone, Debug)]
93pub struct TPropCell<'a> {
94    t_cell: Option<&'a TCell<Option<usize>>>,
95    log: Option<&'a TPropColumn>,
96}
97
98impl<'a> TPropCell<'a> {
99    pub(crate) fn new(t_cell: &'a TCell<Option<usize>>, log: Option<&'a TPropColumn>) -> Self {
100        Self {
101            t_cell: Some(t_cell),
102            log,
103        }
104    }
105}
106
107impl<'a> TPropOps<'a> for TPropCell<'a> {
108    fn iter(self) -> impl DoubleEndedIterator<Item = (EventTime, Prop)> + Send + Sync + 'a {
109        let log = self.log;
110        self.t_cell.into_iter().flat_map(move |t_cell| {
111            t_cell
112                .iter()
113                .filter_map(move |(t, &id)| log?.get(id?).map(|prop| (*t, prop)))
114        })
115    }
116
117    fn iter_window(
118        self,
119        r: Range<EventTime>,
120    ) -> impl DoubleEndedIterator<Item = (EventTime, Prop)> + Send + Sync + 'a {
121        self.t_cell.into_iter().flat_map(move |t_cell| {
122            t_cell
123                .iter_window(r.clone())
124                .filter_map(move |(t, &id)| self.log?.get(id?).map(|prop| (*t, prop)))
125        })
126    }
127
128    fn at(&self, ti: &EventTime) -> Option<Prop> {
129        self.t_cell?.at(ti).and_then(|&id| self.log?.get(id?))
130    }
131}
132
133impl TProp {
134    pub(crate) fn from(t: EventTime, prop: Prop) -> Self {
135        match prop {
136            Prop::Str(value) => TProp::Str(TCell::new(t, value)),
137            Prop::I32(value) => TProp::I32(TCell::new(t, value)),
138            Prop::I64(value) => TProp::I64(TCell::new(t, value)),
139            Prop::U8(value) => TProp::U8(TCell::new(t, value)),
140            Prop::U16(value) => TProp::U16(TCell::new(t, value)),
141            Prop::U32(value) => TProp::U32(TCell::new(t, value)),
142            Prop::U64(value) => TProp::U64(TCell::new(t, value)),
143            Prop::F32(value) => TProp::F32(TCell::new(t, value)),
144            Prop::F64(value) => TProp::F64(TCell::new(t, value)),
145            Prop::Bool(value) => TProp::Bool(TCell::new(t, value)),
146            Prop::DTime(value) => TProp::DTime(TCell::new(t, value)),
147            Prop::NDTime(value) => TProp::NDTime(TCell::new(t, value)),
148            #[cfg(feature = "arrow")]
149            Prop::Array(value) => TProp::Array(TCell::new(t, value)),
150            Prop::List(value) => TProp::List(TCell::new(t, value)),
151            Prop::Map(value) => TProp::Map(TCell::new(t, value)),
152            Prop::Decimal(value) => TProp::Decimal(TCell::new(t, value)),
153        }
154    }
155
156    pub fn dtype(&self) -> PropType {
157        match self {
158            TProp::Empty => PropType::Empty,
159            TProp::Str(_) => PropType::Str,
160            TProp::U8(_) => PropType::U8,
161            TProp::U16(_) => PropType::U16,
162            TProp::I32(_) => PropType::I32,
163            TProp::I64(_) => PropType::I64,
164            TProp::U32(_) => PropType::U32,
165            TProp::U64(_) => PropType::U64,
166            TProp::F32(_) => PropType::F32,
167            TProp::F64(_) => PropType::F64,
168            TProp::Bool(_) => PropType::Bool,
169            TProp::DTime(_) => PropType::DTime,
170            #[cfg(feature = "arrow")]
171            TProp::Array(_) => PropType::Array(Box::new(PropType::Empty)),
172            TProp::NDTime(_) => PropType::NDTime,
173            TProp::List(_) => PropType::List(Box::new(PropType::Empty)),
174            TProp::Map(_) => PropType::Map(HashMap::new().into()),
175            TProp::Decimal(_) => PropType::Decimal { scale: 0 },
176        }
177    }
178
179    pub(crate) fn set(&mut self, t: EventTime, prop: Prop) -> Result<(), IllegalPropType> {
180        if matches!(self, TProp::Empty) {
181            *self = TProp::from(t, prop);
182        } else {
183            match (self, prop) {
184                (TProp::Empty, _) => {}
185
186                (TProp::Str(cell), Prop::Str(a)) => {
187                    cell.set(t, a);
188                }
189                (TProp::I32(cell), Prop::I32(a)) => {
190                    cell.set(t, a);
191                }
192                (TProp::I64(cell), Prop::I64(a)) => {
193                    cell.set(t, a);
194                }
195                (TProp::U32(cell), Prop::U32(a)) => {
196                    cell.set(t, a);
197                }
198                (TProp::U8(cell), Prop::U8(a)) => {
199                    cell.set(t, a);
200                }
201                (TProp::U16(cell), Prop::U16(a)) => {
202                    cell.set(t, a);
203                }
204                (TProp::U64(cell), Prop::U64(a)) => {
205                    cell.set(t, a);
206                }
207                (TProp::F32(cell), Prop::F32(a)) => {
208                    cell.set(t, a);
209                }
210                (TProp::F64(cell), Prop::F64(a)) => {
211                    cell.set(t, a);
212                }
213                (TProp::Bool(cell), Prop::Bool(a)) => {
214                    cell.set(t, a);
215                }
216                (TProp::DTime(cell), Prop::DTime(a)) => {
217                    cell.set(t, a);
218                }
219                (TProp::NDTime(cell), Prop::NDTime(a)) => {
220                    cell.set(t, a);
221                }
222                #[cfg(feature = "arrow")]
223                (TProp::Array(cell), Prop::Array(a)) => {
224                    cell.set(t, a);
225                }
226                (TProp::List(cell), Prop::List(a)) => {
227                    cell.set(t, a);
228                }
229                (TProp::Map(cell), Prop::Map(a)) => {
230                    cell.set(t, a);
231                }
232                (TProp::Decimal(cell), Prop::Decimal(a)) => {
233                    cell.set(t, a);
234                }
235                (cell, prop) => {
236                    return Err(IllegalPropType {
237                        expected: cell.dtype(),
238                        actual: prop.dtype(),
239                    })
240                }
241            };
242        }
243        Ok(())
244    }
245}
246
247impl<'a> TPropOps<'a> for &'a TProp {
248    fn last_before(&self, t: EventTime) -> Option<(EventTime, Prop)> {
249        match self {
250            TProp::Empty => None,
251            TProp::Str(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::Str(v.clone()))),
252            TProp::I32(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::I32(*v))),
253            TProp::I64(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::I64(*v))),
254            TProp::U8(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::U8(*v))),
255            TProp::U16(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::U16(*v))),
256            TProp::U32(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::U32(*v))),
257            TProp::U64(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::U64(*v))),
258            TProp::F32(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::F32(*v))),
259            TProp::F64(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::F64(*v))),
260            TProp::Bool(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::Bool(*v))),
261            TProp::DTime(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::DTime(*v))),
262            TProp::NDTime(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::NDTime(*v))),
263            #[cfg(feature = "arrow")]
264            TProp::Array(cell) => cell
265                .last_before(t)
266                .map(|(t, v)| (t, Prop::Array(v.clone()))),
267            TProp::List(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::List(v.clone()))),
268            TProp::Map(cell) => cell.last_before(t).map(|(t, v)| (t, Prop::Map(v.clone()))),
269            TProp::Decimal(cell) => cell
270                .last_before(t)
271                .map(|(t, v)| (t, Prop::Decimal(v.clone()))),
272        }
273    }
274
275    fn iter(self) -> impl DoubleEndedIterator<Item = (EventTime, Prop)> + Send + Sync + 'a {
276        match self {
277            TProp::Empty => TPropVariants::Empty(iter::empty()),
278            TProp::Str(cell) => {
279                TPropVariants::Str(cell.iter().map(|(t, value)| (*t, Prop::Str(value.clone()))))
280            }
281            TProp::I32(cell) => {
282                TPropVariants::I32(cell.iter().map(|(t, value)| (*t, Prop::I32(*value))))
283            }
284            TProp::I64(cell) => {
285                TPropVariants::I64(cell.iter().map(|(t, value)| (*t, Prop::I64(*value))))
286            }
287            TProp::U8(cell) => {
288                TPropVariants::U8(cell.iter().map(|(t, value)| (*t, Prop::U8(*value))))
289            }
290            TProp::U16(cell) => {
291                TPropVariants::U16(cell.iter().map(|(t, value)| (*t, Prop::U16(*value))))
292            }
293            TProp::U32(cell) => {
294                TPropVariants::U32(cell.iter().map(|(t, value)| (*t, Prop::U32(*value))))
295            }
296            TProp::U64(cell) => {
297                TPropVariants::U64(cell.iter().map(|(t, value)| (*t, Prop::U64(*value))))
298            }
299            TProp::F32(cell) => {
300                TPropVariants::F32(cell.iter().map(|(t, value)| (*t, Prop::F32(*value))))
301            }
302            TProp::F64(cell) => {
303                TPropVariants::F64(cell.iter().map(|(t, value)| (*t, Prop::F64(*value))))
304            }
305            TProp::Bool(cell) => {
306                TPropVariants::Bool(cell.iter().map(|(t, value)| (*t, Prop::Bool(*value))))
307            }
308            TProp::DTime(cell) => {
309                TPropVariants::DTime(cell.iter().map(|(t, value)| (*t, Prop::DTime(*value))))
310            }
311            TProp::NDTime(cell) => {
312                TPropVariants::NDTime(cell.iter().map(|(t, value)| (*t, Prop::NDTime(*value))))
313            }
314            #[cfg(feature = "arrow")]
315            TProp::Array(cell) => TPropVariants::Array(
316                cell.iter()
317                    .map(|(t, value)| (*t, Prop::Array(value.clone()))),
318            ),
319            TProp::List(cell) => TPropVariants::List(
320                cell.iter()
321                    .map(|(t, value)| (*t, Prop::List(value.clone()))),
322            ),
323            TProp::Map(cell) => {
324                TPropVariants::Map(cell.iter().map(|(t, value)| (*t, Prop::Map(value.clone()))))
325            }
326            TProp::Decimal(cell) => TPropVariants::Decimal(
327                cell.iter()
328                    .map(|(t, value)| (*t, Prop::Decimal(value.clone()))),
329            ),
330        }
331    }
332
333    fn iter_window(
334        self,
335        r: Range<EventTime>,
336    ) -> impl DoubleEndedIterator<Item = (EventTime, Prop)> + Send + Sync + 'a {
337        match self {
338            TProp::Empty => TPropVariants::Empty(iter::empty()),
339            TProp::Str(cell) => TPropVariants::Str(
340                cell.iter_window(r)
341                    .map(|(t, value)| (*t, Prop::Str(value.clone()))),
342            ),
343            TProp::I32(cell) => TPropVariants::I32(
344                cell.iter_window(r)
345                    .map(|(t, value)| (*t, Prop::I32(*value))),
346            ),
347            TProp::I64(cell) => TPropVariants::I64(
348                cell.iter_window(r)
349                    .map(|(t, value)| (*t, Prop::I64(*value))),
350            ),
351            TProp::U8(cell) => {
352                TPropVariants::U8(cell.iter_window(r).map(|(t, value)| (*t, Prop::U8(*value))))
353            }
354            TProp::U16(cell) => TPropVariants::U16(
355                cell.iter_window(r)
356                    .map(|(t, value)| (*t, Prop::U16(*value))),
357            ),
358            TProp::U32(cell) => TPropVariants::U32(
359                cell.iter_window(r)
360                    .map(|(t, value)| (*t, Prop::U32(*value))),
361            ),
362            TProp::U64(cell) => TPropVariants::U64(
363                cell.iter_window(r)
364                    .map(|(t, value)| (*t, Prop::U64(*value))),
365            ),
366            TProp::F32(cell) => TPropVariants::F32(
367                cell.iter_window(r)
368                    .map(|(t, value)| (*t, Prop::F32(*value))),
369            ),
370            TProp::F64(cell) => TPropVariants::F64(
371                cell.iter_window(r)
372                    .map(|(t, value)| (*t, Prop::F64(*value))),
373            ),
374            TProp::Bool(cell) => TPropVariants::Bool(
375                cell.iter_window(r)
376                    .map(|(t, value)| (*t, Prop::Bool(*value))),
377            ),
378            TProp::DTime(cell) => TPropVariants::DTime(
379                cell.iter_window(r)
380                    .map(|(t, value)| (*t, Prop::DTime(*value))),
381            ),
382            TProp::NDTime(cell) => TPropVariants::NDTime(
383                cell.iter_window(r)
384                    .map(|(t, value)| (*t, Prop::NDTime(*value))),
385            ),
386            #[cfg(feature = "arrow")]
387            TProp::Array(cell) => TPropVariants::Array(
388                cell.iter_window(r)
389                    .map(|(t, value)| (*t, Prop::Array(value.clone()))),
390            ),
391            TProp::List(cell) => TPropVariants::List(
392                cell.iter_window(r)
393                    .map(|(t, value)| (*t, Prop::List(value.clone()))),
394            ),
395            TProp::Map(cell) => TPropVariants::Map(
396                cell.iter_window(r)
397                    .map(|(t, value)| (*t, Prop::Map(value.clone()))),
398            ),
399            TProp::Decimal(cell) => TPropVariants::Decimal(
400                cell.iter_window(r)
401                    .map(|(t, value)| (*t, Prop::Decimal(value.clone()))),
402            ),
403        }
404    }
405
406    fn at(&self, ti: &EventTime) -> Option<Prop> {
407        match self {
408            TProp::Empty => None,
409            TProp::Str(cell) => cell.at(ti).map(|v| Prop::Str(v.clone())),
410            TProp::I32(cell) => cell.at(ti).map(|v| Prop::I32(*v)),
411            TProp::I64(cell) => cell.at(ti).map(|v| Prop::I64(*v)),
412            TProp::U32(cell) => cell.at(ti).map(|v| Prop::U32(*v)),
413            TProp::U8(cell) => cell.at(ti).map(|v| Prop::U8(*v)),
414            TProp::U16(cell) => cell.at(ti).map(|v| Prop::U16(*v)),
415            TProp::U64(cell) => cell.at(ti).map(|v| Prop::U64(*v)),
416            TProp::F32(cell) => cell.at(ti).map(|v| Prop::F32(*v)),
417            TProp::F64(cell) => cell.at(ti).map(|v| Prop::F64(*v)),
418            TProp::Bool(cell) => cell.at(ti).map(|v| Prop::Bool(*v)),
419            TProp::DTime(cell) => cell.at(ti).map(|v| Prop::DTime(*v)),
420            TProp::NDTime(cell) => cell.at(ti).map(|v| Prop::NDTime(*v)),
421            #[cfg(feature = "arrow")]
422            TProp::Array(cell) => cell.at(ti).map(|v| Prop::Array(v.clone())),
423            TProp::List(cell) => cell.at(ti).map(|v| Prop::List(v.clone())),
424            TProp::Map(cell) => cell.at(ti).map(|v| Prop::Map(v.clone())),
425            TProp::Decimal(cell) => cell.at(ti).map(|v| Prop::Decimal(v.clone())),
426        }
427    }
428}
429
430#[cfg(test)]
431mod tprop_tests {
432    use crate::storage::lazy_vec::LazyVec;
433
434    use super::*;
435
436    #[test]
437    fn t_prop_cell() {
438        let col = TPropColumn::Bool(LazyVec::from(0, true));
439        assert_eq!(col.get(0), Some(Prop::Bool(true)));
440
441        let t_prop = TPropCell::new(&TCell::TCell1(EventTime(0, 0), Some(0)), Some(&col));
442
443        let actual = t_prop.iter().collect::<Vec<_>>();
444
445        assert_eq!(actual, vec![(EventTime(0, 0), Prop::Bool(true))]);
446    }
447
448    #[test]
449    fn set_new_value_for_tprop_initialized_as_empty() {
450        let mut tprop = TProp::Empty;
451        tprop.set(1.into(), Prop::I32(10)).unwrap();
452
453        assert_eq!(tprop.iter_t().collect::<Vec<_>>(), vec![(1, Prop::I32(10))]);
454    }
455
456    #[test]
457    fn every_new_update_to_the_same_prop_is_recorded_as_history() {
458        let mut tprop = TProp::from(1.into(), "Pometry".into());
459        tprop.set(2.into(), "Pometry Inc.".into()).unwrap();
460
461        assert_eq!(
462            tprop.iter_t().collect::<Vec<_>>(),
463            vec![(1, "Pometry".into()), (2, "Pometry Inc.".into())]
464        );
465    }
466
467    #[test]
468    fn new_update_with_the_same_time_to_a_prop_is_ignored() {
469        let mut tprop = TProp::from(1.into(), "Pometry".into());
470        tprop.set(1.into(), "Pometry Inc.".into()).unwrap();
471
472        assert_eq!(
473            tprop.iter_t().collect::<Vec<_>>(),
474            vec![(1, "Pometry Inc.".into())]
475        );
476    }
477
478    #[test]
479    fn updates_to_prop_can_be_iterated() {
480        let tprop = TProp::default();
481
482        assert_eq!(tprop.iter_t().collect::<Vec<_>>(), vec![]);
483
484        let mut tprop = TProp::from(1.into(), "Pometry".into());
485        tprop.set(2.into(), "Pometry Inc.".into()).unwrap();
486
487        assert_eq!(
488            tprop.iter_t().collect::<Vec<_>>(),
489            vec![
490                (1, Prop::Str("Pometry".into())),
491                (2, Prop::Str("Pometry Inc.".into()))
492            ]
493        );
494
495        let mut tprop = TProp::from(1.into(), Prop::I32(2022));
496        tprop.set(2.into(), Prop::I32(2023)).unwrap();
497
498        assert_eq!(
499            tprop.iter_t().collect::<Vec<_>>(),
500            vec![(1, Prop::I32(2022)), (2, Prop::I32(2023))]
501        );
502
503        let mut tprop = TProp::from(1.into(), Prop::I64(2022));
504        tprop.set(2.into(), Prop::I64(2023)).unwrap();
505
506        assert_eq!(
507            tprop.iter_t().collect::<Vec<_>>(),
508            vec![(1, Prop::I64(2022)), (2, Prop::I64(2023))]
509        );
510
511        let mut tprop = TProp::from(1.into(), Prop::F32(10.0));
512        tprop.set(2.into(), Prop::F32(11.0)).unwrap();
513
514        assert_eq!(
515            tprop.iter_t().collect::<Vec<_>>(),
516            vec![(1, Prop::F32(10.0)), (2, Prop::F32(11.0))]
517        );
518
519        let mut tprop = TProp::from(1.into(), Prop::F64(10.0));
520        tprop.set(2.into(), Prop::F64(11.0)).unwrap();
521
522        assert_eq!(
523            tprop.iter_t().collect::<Vec<_>>(),
524            vec![(1, Prop::F64(10.0)), (2, Prop::F64(11.0))]
525        );
526
527        let mut tprop = TProp::from(1.into(), Prop::U32(1));
528        tprop.set(2.into(), Prop::U32(2)).unwrap();
529
530        assert_eq!(
531            tprop.iter_t().collect::<Vec<_>>(),
532            vec![(1, Prop::U32(1)), (2, Prop::U32(2))]
533        );
534
535        let mut tprop = TProp::from(1.into(), Prop::U64(1));
536        tprop.set(2.into(), Prop::U64(2)).unwrap();
537
538        assert_eq!(
539            tprop.iter_t().collect::<Vec<_>>(),
540            vec![(1, Prop::U64(1)), (2, Prop::U64(2))]
541        );
542
543        let mut tprop = TProp::from(1.into(), Prop::U8(1));
544        tprop.set(2.into(), Prop::U8(2)).unwrap();
545
546        assert_eq!(
547            tprop.iter_t().collect::<Vec<_>>(),
548            vec![(1, Prop::U8(1)), (2, Prop::U8(2))]
549        );
550
551        let mut tprop = TProp::from(1.into(), Prop::U16(1));
552        tprop.set(2.into(), Prop::U16(2)).unwrap();
553
554        assert_eq!(
555            tprop.iter_t().collect::<Vec<_>>(),
556            vec![(1, Prop::U16(1)), (2, Prop::U16(2))]
557        );
558
559        let mut tprop = TProp::from(1.into(), Prop::Bool(true));
560        tprop.set(2.into(), Prop::Bool(true)).unwrap();
561
562        assert_eq!(
563            tprop.iter_t().collect::<Vec<_>>(),
564            vec![(1, Prop::Bool(true)), (2, Prop::Bool(true))]
565        );
566    }
567
568    #[test]
569    fn updates_to_prop_can_be_window_iterated() {
570        let tprop = &TProp::default();
571
572        assert_eq!(
573            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
574            vec![]
575        );
576
577        let mut tprop = TProp::from(3.into(), Prop::Str("Pometry".into()));
578        tprop
579            .set(1.into(), Prop::Str("Pometry Inc.".into()))
580            .unwrap();
581        tprop.set(2.into(), Prop::Str("Raphtory".into())).unwrap();
582
583        let tprop = &tprop;
584        assert_eq!(
585            tprop.iter_window_t(2..3).collect::<Vec<_>>(),
586            vec![(2, Prop::Str("Raphtory".into()))]
587        );
588
589        assert_eq!(tprop.iter_window_t(4..5).collect::<Vec<_>>(), vec![]);
590
591        assert_eq!(
592            // Results are ordered by time
593            tprop.iter_window_t(1..i64::MAX).collect::<Vec<_>>(),
594            vec![
595                (1, Prop::Str("Pometry Inc.".into())),
596                (2, Prop::Str("Raphtory".into())),
597                (3, Prop::Str("Pometry".into()))
598            ]
599        );
600
601        assert_eq!(
602            tprop.iter_window_t(3..i64::MAX).collect::<Vec<_>>(),
603            vec![(3, Prop::Str("Pometry".into()))]
604        );
605
606        assert_eq!(
607            tprop.iter_window_t(2..i64::MAX).collect::<Vec<_>>(),
608            vec![
609                (2, Prop::Str("Raphtory".into())),
610                (3, Prop::Str("Pometry".into()))
611            ]
612        );
613
614        assert_eq!(tprop.iter_window_t(5..i64::MAX).collect::<Vec<_>>(), vec![]);
615
616        assert_eq!(
617            tprop.iter_window_t(i64::MIN..4).collect::<Vec<_>>(),
618            // Results are ordered by time
619            vec![
620                (1, Prop::Str("Pometry Inc.".into())),
621                (2, Prop::Str("Raphtory".into())),
622                (3, Prop::Str("Pometry".into()))
623            ]
624        );
625
626        assert_eq!(tprop.iter_window_t(i64::MIN..1).collect::<Vec<_>>(), vec![]);
627
628        let mut tprop = TProp::from(1.into(), Prop::I32(2022));
629        tprop.set(2.into(), Prop::I32(2023)).unwrap();
630
631        let tprop = &tprop;
632        assert_eq!(
633            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
634            vec![(1, Prop::I32(2022)), (2, Prop::I32(2023))]
635        );
636
637        let mut tprop = TProp::from(1.into(), Prop::I64(2022));
638        tprop.set(2.into(), Prop::I64(2023)).unwrap();
639
640        let tprop = &tprop;
641        assert_eq!(
642            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
643            vec![(1, Prop::I64(2022)), (2, Prop::I64(2023))]
644        );
645
646        let mut tprop = TProp::from(1.into(), Prop::F32(10.0));
647        tprop.set(2.into(), Prop::F32(11.0)).unwrap();
648
649        let tprop = &tprop;
650        assert_eq!(
651            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
652            vec![(1, Prop::F32(10.0)), (2, Prop::F32(11.0))]
653        );
654
655        let mut tprop = TProp::from(1.into(), Prop::F64(10.0));
656        tprop.set(2.into(), Prop::F64(11.0)).unwrap();
657
658        let tprop = &tprop;
659        assert_eq!(
660            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
661            vec![(1, Prop::F64(10.0)), (2, Prop::F64(11.0))]
662        );
663
664        let mut tprop = TProp::from(1.into(), Prop::U32(1));
665        tprop.set(2.into(), Prop::U32(2)).unwrap();
666
667        let tprop = &tprop;
668        assert_eq!(
669            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
670            vec![(1, Prop::U32(1)), (2, Prop::U32(2))]
671        );
672
673        let mut tprop = TProp::from(1.into(), Prop::U64(1));
674        tprop.set(2.into(), Prop::U64(2)).unwrap();
675
676        let tprop = &tprop;
677        assert_eq!(
678            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
679            vec![(1, Prop::U64(1)), (2, Prop::U64(2))]
680        );
681
682        let mut tprop = TProp::from(1.into(), Prop::U8(1));
683        tprop.set(2.into(), Prop::U8(2)).unwrap();
684
685        let tprop = &tprop;
686        assert_eq!(
687            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
688            vec![(1, Prop::U8(1)), (2, Prop::U8(2))]
689        );
690
691        let mut tprop = TProp::from(1.into(), Prop::U16(1));
692        tprop.set(2.into(), Prop::U16(2)).unwrap();
693
694        let tprop = &tprop;
695        assert_eq!(
696            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
697            vec![(1, Prop::U16(1)), (2, Prop::U16(2))]
698        );
699
700        let mut tprop = TProp::from(1.into(), Prop::Bool(true));
701        tprop.set(2.into(), Prop::Bool(true)).unwrap();
702
703        let tprop = &tprop;
704        assert_eq!(
705            tprop.iter_window_t(i64::MIN..i64::MAX).collect::<Vec<_>>(),
706            vec![(1, Prop::Bool(true)), (2, Prop::Bool(true))]
707        );
708    }
709}