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