raphtory_core/entities/properties/
props.rs1use crate::{
2 entities::properties::tprop::{IllegalPropType, TProp},
3 storage::{
4 lazy_vec::{IllegalSet, LazyVec},
5 timeindex::TimeIndexEntry,
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(
51 &mut self,
52 t: TimeIndexEntry,
53 prop_id: usize,
54 prop: Prop,
55 ) -> Result<(), TPropError> {
56 self.temporal_props.update(prop_id, |p| Ok(p.set(t, prop)?))
57 }
58
59 pub fn add_metadata(&mut self, prop_id: usize, prop: Prop) -> Result<(), MetadataError> {
60 Ok(self.metadata.set(prop_id, Some(prop))?)
61 }
62
63 pub fn update_metadata(&mut self, prop_id: usize, prop: Prop) -> Result<(), MetadataError> {
64 self.metadata.update(prop_id, |n| {
65 *n = Some(prop);
66 Ok(())
67 })
68 }
69
70 pub fn metadata(&self, prop_id: usize) -> Option<&Prop> {
71 let prop = self.metadata.get(prop_id)?;
72 prop.as_ref()
73 }
74
75 pub fn temporal_prop(&self, prop_id: usize) -> Option<&TProp> {
76 self.temporal_props.get(prop_id)
77 }
78
79 pub fn metadata_ids(&self) -> impl Iterator<Item = usize> + '_ {
80 self.metadata.filled_ids()
81 }
82
83 pub fn temporal_prop_ids(&self) -> impl Iterator<Item = usize> + Send + Sync + '_ {
84 self.temporal_props.filled_ids()
85 }
86}
87
88#[cfg(test)]
89mod test {
90 use super::*;
91 use raphtory_api::core::entities::properties::meta::PropMapper;
92 use std::{sync::Arc, thread};
93
94 #[test]
95 fn test_prop_mapper_concurrent() {
96 let values = [Prop::I64(1), Prop::U16(0), Prop::Bool(true), Prop::F64(0.0)];
97 let input_len = values.len();
98
99 let mapper = Arc::new(PropMapper::default());
100 let threads: Vec<_> = values
101 .into_iter()
102 .map(move |v| {
103 let mapper = mapper.clone();
104 thread::spawn(move || mapper.get_or_create_and_validate("test", v.dtype()))
105 })
106 .flat_map(|t| t.join())
107 .collect();
108
109 assert_eq!(threads.len(), input_len); assert_eq!(threads.into_iter().flatten().count(), 1); }
112}