Skip to main content

graphrecords_core/graphrecord/
attributes.rs

1use crate::{
2    GraphRecord,
3    errors::{GraphRecordError, GraphRecordResult},
4    prelude::{
5        AttributeMap, EdgeIndex, GraphRecordAttribute, GraphRecordValue, Group, NodeIndex,
6        SchemaType,
7    },
8};
9
10macro_rules! impl_attributes_mut {
11    (
12        $struct_name:ident,
13        $index_type:ty,
14        $index_field:ident,
15        $entity:literal,
16        $contains_fn:ident,
17        $groups_of_fn:ident,
18        $get_attributes_fn:ident,
19        $get_attributes_mut_fn:ident,
20        $schema_update_fn:ident,
21        $schema_validate_fn:ident,
22        $not_found_variant:ident,
23        $attribute_not_found_variant:ident
24    ) => {
25        pub struct $struct_name<'a> {
26            $index_field: &'a $index_type,
27            graphrecord: &'a mut GraphRecord,
28        }
29
30        impl<'a> $struct_name<'a> {
31            pub(crate) fn new(
32                $index_field: &'a $index_type,
33                graphrecord: &'a mut GraphRecord,
34            ) -> GraphRecordResult<Self> {
35                if !graphrecord.$contains_fn($index_field) {
36                    return Err(GraphRecordError::$not_found_variant {
37                        $index_field: $index_field.clone(),
38                    });
39                }
40
41                Ok(Self {
42                    $index_field,
43                    graphrecord,
44                })
45            }
46
47            fn get_groups(&self) -> Vec<Group> {
48                self.graphrecord
49                    .$groups_of_fn(self.$index_field)
50                    .expect(concat!($entity, " must exist."))
51                    .cloned()
52                    .collect()
53            }
54
55            fn handle_schema(
56                &mut self,
57                attributes: &AttributeMap,
58                groups: &[Group],
59            ) -> GraphRecordResult<()> {
60                let schema = &mut self.graphrecord.schema;
61
62                match schema.schema_type() {
63                    SchemaType::Inferred => {
64                        if groups.is_empty() {
65                            schema.$schema_update_fn(attributes, None, false);
66                        } else {
67                            for group in groups {
68                                schema.$schema_update_fn(attributes, Some(group), false);
69                            }
70                        }
71                    }
72                    SchemaType::Provided => {
73                        if groups.is_empty() {
74                            schema.$schema_validate_fn(self.$index_field, attributes, None)?;
75                        } else {
76                            for group in groups {
77                                schema.$schema_validate_fn(
78                                    self.$index_field,
79                                    attributes,
80                                    Some(group),
81                                )?;
82                            }
83                        }
84                    }
85                }
86
87                Ok(())
88            }
89
90            fn set_attributes(&mut self, attributes: AttributeMap) {
91                *self
92                    .graphrecord
93                    .graph
94                    .$get_attributes_mut_fn(self.$index_field)
95                    .expect(concat!($entity, " must exist.")) = attributes;
96            }
97
98            pub fn replace_attributes(
99                &mut self,
100                attributes: AttributeMap,
101            ) -> GraphRecordResult<()> {
102                let groups = self.get_groups();
103                self.handle_schema(&attributes, &groups)?;
104                self.set_attributes(attributes);
105                Ok(())
106            }
107
108            pub fn update_attribute(
109                &mut self,
110                attribute: &GraphRecordAttribute,
111                value: GraphRecordValue,
112            ) -> GraphRecordResult<()> {
113                let groups = self.get_groups();
114
115                let mut attributes = self
116                    .graphrecord
117                    .$get_attributes_fn(self.$index_field)
118                    .expect(concat!($entity, " must exist."))
119                    .clone();
120                attributes
121                    .entry(attribute.clone())
122                    .and_modify(|v| *v = value.clone())
123                    .or_insert(value);
124
125                self.handle_schema(&attributes, &groups)?;
126                self.set_attributes(attributes);
127                Ok(())
128            }
129
130            pub fn remove_attribute(
131                &mut self,
132                attribute: &GraphRecordAttribute,
133            ) -> GraphRecordResult<GraphRecordValue> {
134                let groups = self.get_groups();
135
136                let mut attributes = self
137                    .graphrecord
138                    .$get_attributes_fn(self.$index_field)
139                    .expect(concat!($entity, " must exist."))
140                    .clone();
141                let removed_value = attributes.remove(attribute);
142
143                let Some(removed_value) = removed_value else {
144                    return Err(GraphRecordError::$attribute_not_found_variant {
145                        $index_field: self.$index_field.clone(),
146                        attribute: attribute.clone(),
147                    });
148                };
149
150                self.handle_schema(&attributes, &groups)?;
151                self.set_attributes(attributes);
152                Ok(removed_value)
153            }
154        }
155    };
156}
157
158impl_attributes_mut!(
159    NodeAttributesMut,
160    NodeIndex,
161    node_index,
162    "node",
163    contains_node,
164    groups_of_node,
165    node_attributes,
166    node_attributes_mut,
167    update_node,
168    validate_node,
169    NodeNotFound,
170    NodeAttributeNotFound
171);
172
173impl_attributes_mut!(
174    EdgeAttributesMut,
175    EdgeIndex,
176    edge_index,
177    "edge",
178    contains_edge,
179    groups_of_edge,
180    edge_attributes,
181    edge_attributes_mut,
182    update_edge,
183    validate_edge,
184    EdgeNotFound,
185    EdgeAttributeNotFound
186);