raphtory_core/entities/properties/
props.rs1use crate::{
2 entities::properties::tprop::{IllegalPropType, TProp},
3 storage::{
4 lazy_vec::{IllegalSet, LazyVec},
5 timeindex::EventTime,
6 },
7};
8use raphtory_api::core::entities::properties::prop::Prop;
9use serde::{Deserialize, Serialize};
10use std::fmt::Debug;
11use thiserror::Error;
12
13#[derive(Serialize, Deserialize, Default, Debug, PartialEq)]
14pub struct Props {
15 pub(crate) metadata: LazyVec<Option<Prop>>,
17 pub(crate) temporal_props: LazyVec<TProp>,
18}
19
20#[derive(Error, Debug)]
21pub enum TPropError {
22 #[error(transparent)]
23 IllegalSet(#[from] IllegalSet<TProp>),
24 #[error(transparent)]
25 IllegalPropType(#[from] IllegalPropType),
26}
27
28#[derive(Error, Debug)]
29pub enum MetadataError {
30 #[error("Attempted to change value of metadata, old: {old}, new: {new}")]
31 IllegalUpdate { old: Prop, new: Prop },
32}
33
34impl From<IllegalSet<Option<Prop>>> for MetadataError {
35 fn from(value: IllegalSet<Option<Prop>>) -> Self {
36 let old = value.previous_value.unwrap_or(Prop::str("NONE"));
37 let new = value.new_value.unwrap_or(Prop::str("NONE"));
38 MetadataError::IllegalUpdate { old, new }
39 }
40}
41
42impl Props {
43 pub fn new() -> Self {
44 Self {
45 metadata: Default::default(),
46 temporal_props: Default::default(),
47 }
48 }
49
50 pub fn add_prop(&mut self, t: EventTime, prop_id: usize, prop: Prop) -> Result<(), TPropError> {
51 self.temporal_props.update(prop_id, |p| Ok(p.set(t, prop)?))
52 }
53
54 pub fn add_metadata(&mut self, prop_id: usize, prop: Prop) -> Result<(), MetadataError> {
55 Ok(self.metadata.set(prop_id, Some(prop))?)
56 }
57
58 pub fn update_metadata(&mut self, prop_id: usize, prop: Prop) -> Result<(), MetadataError> {
59 self.metadata.update(prop_id, |n| {
60 *n = Some(prop);
61 Ok(())
62 })
63 }
64
65 pub fn metadata(&self, prop_id: usize) -> Option<&Prop> {
66 let prop = self.metadata.get(prop_id)?;
67 prop.as_ref()
68 }
69
70 pub fn temporal_prop(&self, prop_id: usize) -> Option<&TProp> {
71 self.temporal_props.get(prop_id)
72 }
73
74 pub fn metadata_ids(&self) -> impl Iterator<Item = usize> + '_ {
75 self.metadata.filled_ids()
76 }
77
78 pub fn temporal_prop_ids(&self) -> impl Iterator<Item = usize> + Send + Sync + '_ {
79 self.temporal_props.filled_ids()
80 }
81}
82
83#[cfg(test)]
84mod test {
85 use super::*;
86 use raphtory_api::core::entities::properties::meta::PropMapper;
87 use std::{sync::Arc, thread};
88
89 #[test]
90 fn test_prop_mapper_concurrent() {
91 let values = [Prop::I64(1), Prop::U16(0), Prop::Bool(true), Prop::F64(0.0)];
92 let input_len = values.len();
93
94 let mapper = Arc::new(PropMapper::default());
95 let threads: Vec<_> = values
96 .into_iter()
97 .map(move |v| {
98 let mapper = mapper.clone();
99 thread::spawn(move || mapper.get_or_create_and_validate("test", v.dtype()))
100 })
101 .flat_map(|t| t.join())
102 .collect();
103
104 assert_eq!(threads.len(), input_len); assert_eq!(threads.into_iter().flatten().count(), 1); }
107}