raphtory_api/core/entities/properties/
props.rs1use std::{ops::Deref, sync::Arc};
2
3use parking_lot::RwLock;
4use serde::{Deserialize, Serialize};
5
6use crate::core::{
7 storage::{
8 arc_str::ArcStr,
9 dict_mapper::{DictMapper, MaybeNew},
10 locked_vec::ArcReadLockedVec,
11 },
12 PropType,
13};
14
15use super::PropError;
16
17#[derive(Serialize, Deserialize, Debug)]
18pub struct Meta {
19 meta_prop_temporal: PropMapper,
20 meta_prop_constant: PropMapper,
21 meta_layer: DictMapper,
22 meta_node_type: DictMapper,
23}
24
25impl Default for Meta {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl Meta {
32 pub fn set_const_prop_meta(&mut self, meta: PropMapper) {
33 self.meta_prop_constant = meta;
34 }
35 pub fn set_temporal_prop_meta(&mut self, meta: PropMapper) {
36 self.meta_prop_temporal = meta;
37 }
38 pub fn const_prop_meta(&self) -> &PropMapper {
39 &self.meta_prop_constant
40 }
41
42 pub fn temporal_prop_meta(&self) -> &PropMapper {
43 &self.meta_prop_temporal
44 }
45
46 pub fn layer_meta(&self) -> &DictMapper {
47 &self.meta_layer
48 }
49
50 pub fn node_type_meta(&self) -> &DictMapper {
51 &self.meta_node_type
52 }
53
54 pub fn new() -> Self {
55 let meta_layer = DictMapper::default();
56 meta_layer.get_or_create_id("_default");
57 let meta_node_type = DictMapper::default();
58 meta_node_type.get_or_create_id("_default");
59 Self {
60 meta_prop_temporal: PropMapper::default(),
61 meta_prop_constant: PropMapper::default(),
62 meta_layer, meta_node_type, }
65 }
66
67 #[inline]
68 pub fn resolve_prop_id(
69 &self,
70 prop: &str,
71 dtype: PropType,
72 is_static: bool,
73 ) -> Result<MaybeNew<usize>, PropError> {
74 if is_static {
75 self.meta_prop_constant
76 .get_or_create_and_validate(prop, dtype)
77 } else {
78 self.meta_prop_temporal
79 .get_or_create_and_validate(prop, dtype)
80 }
81 }
82
83 #[inline]
84 pub fn get_prop_id(&self, name: &str, is_static: bool) -> Option<usize> {
85 if is_static {
86 self.meta_prop_constant.get_id(name)
87 } else {
88 self.meta_prop_temporal.get_id(name)
89 }
90 }
91
92 #[inline]
93 pub fn get_or_create_layer_id(&self, name: &str) -> MaybeNew<usize> {
94 self.meta_layer.get_or_create_id(name)
95 }
96
97 #[inline]
98 pub fn get_default_node_type_id(&self) -> usize {
99 0usize
100 }
101
102 #[inline]
103 pub fn get_or_create_node_type_id(&self, node_type: &str) -> MaybeNew<usize> {
104 self.meta_node_type.get_or_create_id(node_type)
105 }
106
107 #[inline]
108 pub fn get_layer_id(&self, name: &str) -> Option<usize> {
109 self.meta_layer.get_id(name)
110 }
111
112 #[inline]
113 pub fn get_node_type_id(&self, node_type: &str) -> Option<usize> {
114 self.meta_node_type.get_id(node_type)
115 }
116
117 pub fn get_layer_name_by_id(&self, id: usize) -> ArcStr {
118 self.meta_layer.get_name(id)
119 }
120
121 pub fn get_node_type_name_by_id(&self, id: usize) -> Option<ArcStr> {
122 if id == 0 {
123 None
124 } else {
125 Some(self.meta_node_type.get_name(id))
126 }
127 }
128
129 pub fn get_all_layers(&self) -> Vec<usize> {
130 self.meta_layer.get_values()
131 }
132
133 pub fn get_all_node_types(&self) -> Vec<ArcStr> {
134 self.meta_node_type
135 .get_keys()
136 .iter()
137 .filter_map(|key| {
138 if key != "_default" {
139 Some(key.clone())
140 } else {
141 None
142 }
143 })
144 .collect()
145 }
146
147 pub fn get_all_property_names(&self, is_static: bool) -> ArcReadLockedVec<ArcStr> {
148 if is_static {
149 self.meta_prop_constant.get_keys()
150 } else {
151 self.meta_prop_temporal.get_keys()
152 }
153 }
154
155 pub fn get_prop_name(&self, prop_id: usize, is_static: bool) -> ArcStr {
156 if is_static {
157 self.meta_prop_constant.get_name(prop_id)
158 } else {
159 self.meta_prop_temporal.get_name(prop_id)
160 }
161 }
162}
163
164#[derive(Default, Debug, Serialize, Deserialize)]
165pub struct PropMapper {
166 id_mapper: DictMapper,
167 dtypes: Arc<RwLock<Vec<PropType>>>,
168}
169
170impl Deref for PropMapper {
171 type Target = DictMapper;
172
173 #[inline]
174 fn deref(&self) -> &Self::Target {
175 &self.id_mapper
176 }
177}
178
179impl PropMapper {
180 pub fn deep_clone(&self) -> Self {
181 let dtypes = self.dtypes.read().clone();
182 Self {
183 id_mapper: self.id_mapper.deep_clone(),
184 dtypes: Arc::new(RwLock::new(dtypes)),
185 }
186 }
187
188 pub fn get_and_validate(
189 &self,
190 prop: &str,
191 dtype: PropType,
192 ) -> Result<Option<usize>, PropError> {
193 match self.get_id(prop) {
194 Some(id) => {
195 let existing_dtype = self
196 .get_dtype(id)
197 .expect("Existing id should always have a dtype");
198 if existing_dtype == dtype {
199 Ok(Some(id))
200 } else {
201 Err(PropError::PropertyTypeError {
202 name: prop.to_string(),
203 expected: existing_dtype,
204 actual: dtype,
205 })
206 }
207 }
208 None => Ok(None),
209 }
210 }
211 pub fn get_or_create_and_validate(
212 &self,
213 prop: &str,
214 dtype: PropType,
215 ) -> Result<MaybeNew<usize>, PropError> {
216 let wrapped_id = self.id_mapper.get_or_create_id(prop);
217 let id = wrapped_id.inner();
218 let dtype_read = self.dtypes.read_recursive();
219 if let Some(old_type) = dtype_read.get(id) {
220 if !matches!(old_type, PropType::Empty) {
221 return if *old_type == dtype {
222 Ok(wrapped_id)
223 } else {
224 Err(PropError::PropertyTypeError {
225 name: prop.to_owned(),
226 expected: *old_type,
227 actual: dtype,
228 })
229 };
230 }
231 }
232 drop(dtype_read); let mut dtype_write = self.dtypes.write();
234 match dtype_write.get(id) {
235 Some(&old_type) => {
236 if matches!(old_type, PropType::Empty) {
237 dtype_write[id] = dtype;
239 Ok(wrapped_id)
240 } else {
241 if old_type == dtype {
243 Ok(wrapped_id)
244 } else {
245 Err(PropError::PropertyTypeError {
246 name: prop.to_owned(),
247 expected: old_type,
248 actual: dtype,
249 })
250 }
251 }
252 }
253 None => {
254 dtype_write.resize(id + 1, PropType::Empty);
256 dtype_write[id] = dtype;
257 Ok(wrapped_id)
258 }
259 }
260 }
261
262 pub fn set_id_and_dtype(&self, key: impl Into<ArcStr>, id: usize, dtype: PropType) {
263 let mut dtypes = self.dtypes.write();
264 self.set_id(key, id);
265 if dtypes.len() <= id {
266 dtypes.resize(id + 1, PropType::Empty);
267 }
268 dtypes[id] = dtype;
269 }
270
271 pub fn get_dtype(&self, prop_id: usize) -> Option<PropType> {
272 self.dtypes.read_recursive().get(prop_id).copied()
273 }
274
275 pub fn dtypes(&self) -> impl Deref<Target = Vec<PropType>> + '_ {
276 self.dtypes.read_recursive()
277 }
278}