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}