honeycomb_core/cmap/dim2/embed.rs
1//! Attribute operations implementation
2//!
3//! This module contains code used to implement operations on the embedded data associated to the
4//! map. This includes operations regarding vertices as well as (in the future) user-defined
5//! generic attributes
6
7use crate::cmap::{CMap2, VertexIdType};
8use crate::stm::{atomically, StmClosureResult, Transaction};
9use crate::{
10 attributes::{AttributeBind, AttributeStorage, AttributeUpdate, UnknownAttributeStorage},
11 geometry::{CoordsFloat, Vertex2},
12};
13
14/// **Built-in vertex-related methods**
15impl<T: CoordsFloat> CMap2<T> {
16 /// Return the current number of vertices.
17 #[must_use = "unused return value"]
18 pub fn n_vertices(&self) -> usize {
19 self.vertices.n_attributes()
20 }
21
22 #[allow(clippy::missing_errors_doc)]
23 /// Return the vertex associated to a given identifier.
24 ///
25 /// # Return / Errors
26 ///
27 /// This method is meant to be called in a context where the returned `Result` is used to
28 /// validate the transaction passed as argument. Errors should not be processed manually,
29 /// only processed via the `?` operator.
30 ///
31 /// This method return a `Option` taking the following values:
32 /// - `Some(v: Vertex2)` if there is a vertex associated to this ID,
33 /// - `None` otherwise.
34 ///
35 /// # Panics
36 ///
37 /// The method may panic if:
38 /// - the index lands out of bounds,
39 /// - the index cannot be converted to `usize`.
40 pub fn read_vertex(
41 &self,
42 trans: &mut Transaction,
43 vertex_id: VertexIdType,
44 ) -> StmClosureResult<Option<Vertex2<T>>> {
45 self.vertices.read(trans, vertex_id)
46 }
47
48 #[allow(clippy::missing_errors_doc)]
49 /// Replace the vertex associated to a given identifier and return its old value.
50 ///
51 /// # Arguments
52 ///
53 /// - `vertex_id: VertexIdentifier` -- Identifier of the vertex to replace.
54 /// - `vertex: impl Into<Vertex2>` -- New [`Vertex2`] value.
55 ///
56 /// # Return / Errors
57 ///
58 /// This method is meant to be called in a context where the returned `Result` is used to
59 /// validate the transaction passed as argument. Errors should not be processed manually,
60 /// only processed via the `?` operator.
61 ///
62 /// The result contains an `Option` taking the following values:
63 /// - `Some(v: Vertex2)` if there was an old value,
64 /// - `None` otherwise.
65 ///
66 /// # Panics
67 ///
68 /// The method may panic if:
69 /// - the index lands out of bounds,
70 /// - the index cannot be converted to `usize`.
71 pub fn write_vertex(
72 &self,
73 trans: &mut Transaction,
74 vertex_id: VertexIdType,
75 vertex: impl Into<Vertex2<T>>,
76 ) -> StmClosureResult<Option<Vertex2<T>>> {
77 self.vertices.write(trans, vertex_id, vertex.into())
78 }
79
80 #[allow(clippy::missing_errors_doc)]
81 /// Remove the vertex associated to a given identifier and return it.
82 ///
83 /// # Return / Errors
84 ///
85 /// This method is meant to be called in a context where the returned `Result` is used to
86 /// validate the transaction passed as argument. Errors should not be processed manually,
87 // /// only processed via the `?` operator.
88 ///
89 /// The result contains an `Option` taking the following values:
90 /// - `Some(v: Vertex2)` if there was a value,
91 /// - `None` otherwise.
92 ///
93 /// # Panics
94 ///
95 /// The method may panic if:
96 /// - the index lands out of bounds,
97 /// - the index cannot be converted to `usize`.
98 pub fn remove_vertex(
99 &self,
100 trans: &mut Transaction,
101 vertex_id: VertexIdType,
102 ) -> StmClosureResult<Option<Vertex2<T>>> {
103 self.vertices.remove(trans, vertex_id)
104 }
105
106 #[must_use = "unused return value"]
107 /// Read the vertex associated to a given identifier.
108 ///
109 /// This variant is equivalent to `read_vertex`, but internally uses a transaction that will be
110 /// retried until validated.
111 pub fn force_read_vertex(&self, vertex_id: VertexIdType) -> Option<Vertex2<T>> {
112 atomically(|t| self.vertices.read(t, vertex_id))
113 }
114
115 /// Replace the vertex associated to a given identifier and return its old value.
116 ///
117 /// This variant is equivalent to `write_vertex`, but internally uses a transaction that will be
118 /// retried until validated.
119 pub fn force_write_vertex(
120 &self,
121 vertex_id: VertexIdType,
122 vertex: impl Into<Vertex2<T>>,
123 ) -> Option<Vertex2<T>> {
124 let tmp = vertex.into();
125 atomically(|t| self.vertices.write(t, vertex_id, tmp))
126 }
127
128 #[allow(clippy::must_use_candidate)]
129 /// Remove the vertex associated to a given identifier and return it.
130 ///
131 /// This variant is equivalent to `remove_vertex`, but internally uses a transaction that will
132 /// be retried until validated.
133 pub fn force_remove_vertex(&self, vertex_id: VertexIdType) -> Option<Vertex2<T>> {
134 atomically(|t| self.vertices.remove(t, vertex_id))
135 }
136}
137
138/// **Generic attribute-related methods**
139impl<T: CoordsFloat> CMap2<T> {
140 #[allow(clippy::missing_errors_doc)]
141 /// Return the attribute `A` value associated to a given identifier.
142 ///
143 /// The kind of cell `A` binds to is automatically deduced using its `AttributeBind`
144 /// implementation.
145 ///
146 /// # Return / Errors
147 ///
148 /// This method is meant to be called in a context where the returned `Result` is used to
149 /// validate the transaction passed as argument. Errors should not be processed manually,
150 /// only processed via the `?` operator.
151 ///
152 /// This method return a `Option` taking the following values:
153 /// - `Some(a: A)` if there is a value associated to this ID,
154 /// - `None` otherwise, or if there is no storage for this kind of attribute in the map.
155 ///
156 /// # Panics
157 ///
158 /// The method may panic if:
159 /// - the index lands out of bounds,
160 /// - the index cannot be converted to `usize`.
161 pub fn read_attribute<A: AttributeBind + AttributeUpdate>(
162 &self,
163 trans: &mut Transaction,
164 id: A::IdentifierType,
165 ) -> StmClosureResult<Option<A>> {
166 self.attributes.read_attribute::<A>(trans, id)
167 }
168
169 #[allow(clippy::missing_errors_doc)]
170 /// Replace the attribute `A` value associated to a given identifier and return its old value.
171 ///
172 /// # Arguments
173 ///
174 /// - `index: A::IdentifierType` -- Identifier of the cell's value to replace.
175 /// - `val: A` -- Attribute value.
176 ///
177 /// # Return / Errors
178 ///
179 /// This method is meant to be called in a context where the returned `Result` is used to
180 /// validate the transaction passed as argument. Errors should not be processed manually,
181 /// only processed via the `?` operator.
182 ///
183 /// The result contains an `Option` taking the following values:
184 /// - `Some(a: A)` if there was an old value,
185 /// - `None` otherwise, or if there is no storage for this kind of attribute in the map.
186 ///
187 /// # Panics
188 ///
189 /// The method may panic if:
190 /// - the index lands out of bounds,
191 /// - the index cannot be converted to `usize`.
192 pub fn write_attribute<A: AttributeBind + AttributeUpdate>(
193 &self,
194 trans: &mut Transaction,
195 id: A::IdentifierType,
196 val: A,
197 ) -> StmClosureResult<Option<A>> {
198 self.attributes.write_attribute::<A>(trans, id, val)
199 }
200
201 #[allow(clippy::missing_errors_doc)]
202 /// Remove the attribute `A` value associated to a given identifier and return it.
203 ///
204 /// # Return / Errors
205 ///
206 /// This method is meant to be called in a context where the returned `Result` is used to
207 /// validate the transaction passed as argument. Errors should not be processed manually,
208 /// only processed via the `?` operator.
209 ///
210 /// The result contains an `Option` taking the following values:
211 /// - `Some(a: A)` if there was a value,
212 /// - `None` otherwise, or if there is no storage for this kind of attribute in the map.
213 ///
214 /// # Panics
215 ///
216 /// The method may panic if:
217 /// - the index lands out of bounds,
218 /// - the index cannot be converted to `usize`.
219 pub fn remove_attribute<A: AttributeBind + AttributeUpdate>(
220 &self,
221 trans: &mut Transaction,
222 id: A::IdentifierType,
223 ) -> StmClosureResult<Option<A>> {
224 self.attributes.remove_attribute::<A>(trans, id)
225 }
226
227 /// Return the attribute `A` value associated to a given identifier.
228 ///
229 /// This variant is equivalent to `read_attribute`, but internally uses a transaction that will be
230 /// retried until validated.
231 #[allow(clippy::needless_pass_by_value)]
232 pub fn force_read_attribute<A: AttributeBind + AttributeUpdate>(
233 &self,
234 id: A::IdentifierType,
235 ) -> Option<A> {
236 atomically(|t| self.attributes.read_attribute::<A>(t, id.clone()))
237 }
238
239 /// Replace the attribute `A` value associated to a given identifier and return its old value.
240 ///
241 /// This variant is equivalent to `write_attribute`, but internally uses a transaction that will be
242 /// retried until validated.
243 #[allow(clippy::needless_pass_by_value)]
244 pub fn force_write_attribute<A: AttributeBind + AttributeUpdate>(
245 &self,
246 id: A::IdentifierType,
247 val: A,
248 ) -> Option<A> {
249 atomically(|t| self.attributes.write_attribute::<A>(t, id.clone(), val))
250 }
251
252 /// Remove the attribute `A` value associated to a given identifier and return it.
253 ///
254 /// This variant is equivalent to `remove_attribute`, but internally uses a transaction that
255 /// will be retried until validated.
256 #[allow(clippy::needless_pass_by_value)]
257 pub fn force_remove_attribute<A: AttributeBind + AttributeUpdate>(
258 &self,
259 id: A::IdentifierType,
260 ) -> Option<A> {
261 atomically(|t| self.attributes.remove_attribute::<A>(t, id.clone()))
262 }
263
264 // --- big guns
265
266 /// Remove the attribute `A`'s storage from the map.
267 ///
268 /// This method is useful when implementing routines that uses attributes to run; Those can
269 /// then be removed before the final result is returned.
270 pub fn remove_attribute_storage<A: AttributeBind + AttributeUpdate>(&mut self) {
271 self.attributes.remove_storage::<A>();
272 }
273}