graphrecords_core/graphrecord/
attributes.rs1use 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);