61 | where
62 | Self::Facet: FromGeometry,
63 | T: AsRef<[K]>,
64 | {
65 | let keys = keys.as_ref();
66 | if keys.len() == N {
67 | self.indices.extend(keys.iter());
68 | Ok(())
69 | }
70 | else {
71 | // TODO: These numbers do not necessarily represent arity (i.e., the
72 | // number of edges of each topological structure). Use a
73 | // different error variant to express this.
74 | Err(BufferError::ArityConflict {
75 | expected: N,
76 | actual: keys.len(),
77 | })
78 | }
79 | }
80 | }
81 |
82 | impl FacetBuilder for BufferBuilder
83 | where
84 | P: Grouping + Topological,
85 | P::Vertex: Copy + Hash + Integer + Unsigned,
86 | Vec: IndexBuffer
,
87 | {
88 | type Facet = ();
89 | type Key = ();
90 |
91 | fn insert_facet(&mut self, keys: T, _: U) -> Result
92 | where
93 | Self::Facet: FromGeometry,
94 | T: AsRef<[P::Vertex]>,
95 | {
96 | let arity = keys.as_ref().len();
97 | P::try_from_slice(keys)
98 | .ok_or(BufferError::ArityConflict {
99 | expected: P::ARITY.into_interval().0,
100 | actual: arity,
101 | })
102 | .map(|polygon| self.indices.push(polygon))
103 | }
104 | }
105 |
106 | impl MeshBuilder for BufferBuilder
107 | where
108 | Self: SurfaceBuilder,
109 | R: Grouping,
110 | VertexKey: Hash,
111 | Vec: IndexBuffer,
112 | {
113 | type Builder = Self;
114 |
115 | type Vertex = G;
116 | type Facet = ();
117 |
118 | fn surface_with(&mut self, f: F) -> Result
119 | where
120 | Self::Error: From,
121 | F: FnOnce(&mut Self::Builder) -> Result,
122 | {
123 | f(self).map_err(|error| error.into())
124 | }
125 | }
126 |
127 | impl SurfaceBuilder for BufferBuilder
128 | where
129 | Self: FacetBuilder, Facet = ()>,
130 | Self::Error: From, // TODO: Why is this necessary?
131 | R: Grouping,
132 | VertexKey: Hash + NumCast,
133 | Vec: IndexBuffer,
134 | {
135 | type Builder = Self;
136 | type Key = VertexKey;
137 |
138 | type Vertex = G;
139 | type Facet = ();
140 |
141 | fn facets_with(&mut self, f: F) -> Result
142 | where
143 | Self::Error: From,
144 | F: FnOnce(&mut Self::Builder) -> Result,
145 | {
146 | f(self).map_err(|error| error.into())
147 | }
148 |
149 | fn insert_vertex(&mut self, data: T) -> Result
150 | where
151 | Self::Vertex: FromGeometry,
152 | {
153 | let key = as NumCast>::from(self.vertices.len())
154 | .ok_or(BufferError::IndexOverflow)?;
155 | self.vertices.push(data.into_geometry());
156 | Ok(key)
157 | }
158 | }
159 |
160 | impl Transact<::Input> for BufferBuilder
161 | where
162 | R: Grouping,
163 | Vec: IndexBuffer,
164 | {
165 | type Commit = MeshBuffer;
166 | type Abort = ();
167 | type Error = BufferError;
168 |
169 | fn commit(self) -> Result {
170 | let BufferBuilder { indices, vertices } = self;
171 | Ok(MeshBuffer::from_raw_buffers_unchecked(indices, vertices))
172 | }
173 |
174 | fn abort(self) -> Self::Abort {}
175 | }
176 |
--------------------------------------------------------------------------------
/plexus/src/builder.rs:
--------------------------------------------------------------------------------
1 | //! Incremental polygonal mesh construction.
2 | //!
3 | //! This module provides traits for incrementally constructing mesh data
4 | //! structures. This API allows for meshes to be constructed in a way that is
5 | //! agnostic to the specific data structure used to represent the mesh.
6 | //!
7 | //! [`Buildable`] is the primary trait of this API. It is implemented by mesh
8 | //! data structures and exposes various associated types for their associated
9 | //! data. [`Buildable`] exposes a builder type via its
10 | //! [`builder`][`Buildable::builder`] function. This builder type in turn
11 | //! provides additional builders that can be used to construct a mesh from
12 | //! _surfaces_ and _facets_.
13 | //!
14 | //! # Examples
15 | //!
16 | //! A function that generates a triangle from point geometry using builders:
17 | //!
18 | //! ```rust
19 | //! # extern crate nalgebra;
20 | //! # extern crate plexus;
21 | //! #
22 | //! use nalgebra::Point2;
23 | //! use plexus::buffer::MeshBuffer3;
24 | //! use plexus::builder::Buildable;
25 | //! use plexus::geometry::FromGeometry;
26 | //! use plexus::graph::MeshGraph;
27 | //! use plexus::prelude::*;
28 | //!
29 | //! type E2 = Point2;
30 | //!
31 | //! fn trigon(points: [T; 3]) -> Result
32 | //! where
33 | //! B: Buildable,
34 | //! B::Vertex: FromGeometry,
35 | //! {
36 | //! let mut builder = B::builder();
37 | //! builder.surface_with(|builder| {
38 | //! let [a, b, c] = points;
39 | //! let a = builder.insert_vertex(a)?;
40 | //! let b = builder.insert_vertex(b)?;
41 | //! let c = builder.insert_vertex(c)?;
42 | //! builder.facets_with(|builder| builder.insert_facet(&[a, b, c], B::Facet::default()))
43 | //! })?;
44 | //! builder.build()
45 | //! }
46 | //!
47 | //! // `MeshBuffer` and `MeshGraph` implement the `Buildable` trait.
48 | //! let graph: MeshGraph = trigon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]).unwrap();
49 | //! let buffer: MeshBuffer3 = trigon([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]).unwrap();
50 | //! ```
51 | //!
52 | //! [`Buildable::builder`]: crate::builder::Buildable::builder
53 | //! [`Buildable`]: crate::builder::Buildable
54 |
55 | // TODO: Is it useful to use a separate `FacetBuilder` type?
56 | // TODO: Keys are not opaque. Especially for `MeshBuffer`, it may be possible to
57 | // "forge" keys. This could be prevented by using a wrapper type that is
58 | // not exported, but would introduce a performance cost to map and collect
59 | // slices of keys.
60 |
61 | use std::fmt::Debug;
62 | use std::hash::Hash;
63 |
64 | use crate::geometry::FromGeometry;
65 | use crate::transact::ClosedInput;
66 |
67 | /// Polygonal mesh data structure that can be built incrementally.
68 | ///
69 | /// This trait is the primary entrypoint into the builder API. Types that
70 | /// implement this trait expose a [`MeshBuilder`] that can be used to construct
71 | /// an instance of the type from surfaces and facets.
72 | ///
73 | /// [`MeshBuilder`]: crate::builder::MeshBuilder
74 | pub trait Buildable: Sized {
75 | type Builder: MeshBuilder<
76 | Commit = Self,
77 | Error = Self::Error,
78 | Vertex = Self::Vertex,
79 | Facet = Self::Facet,
80 | >;
81 | type Error: Debug;
82 |
83 | /// Vertex data.
84 | ///
85 | /// This type represents the data associated with vertices in the mesh.
86 | /// This typically includes positional data, but no data is required and
87 | /// this type may be the unit type `()`.
88 | ///
89 | /// Each builder trait also exposes such an associated type which is
90 | /// constrained by the `Builder` type.
91 | type Vertex;
92 | /// Facet data.
93 | ///
94 | /// This type represents the data associated with facets in the mesh. No
95 | /// data is required and this type may be the unit type `()`.
96 | ///
97 | /// Each builder trait also exposes such an associated type which is
98 | /// constrained by the `Builder` type.
99 | type Facet: Default;
100 |
101 | fn builder() -> Self::Builder;
102 | }
103 |
104 | /// Incremental polygonal mesh builder.
105 | ///
106 | /// This trait exposes types that allow for mesh data structures to be
107 | /// constructed incrementally from _surfaces_ and _facets_. A _surface_ is a
108 | /// collection of vertices and facets connecting those vertices and typically
109 | /// describes a _manifold_. A _facet_ is the connectivity between vertices in a
110 | /// surface. Facets may also include associated data.
111 | ///
112 | /// Construction is hierarchical, beginning with a surface and its vertices and
113 | /// then facets. The association between a surface, its vertices, and facets is
114 | /// enforced by the API, which accepts functions that operate on increasingly
115 | /// specific builder types. The [`build`][`MeshBuilder::build`] function is used
116 | /// to complete the construction of a mesh.
117 | ///
118 | /// Builders may emit errors at any stage and errors depend on the
119 | /// implementation of the builder types (and by extension the details of the
120 | /// underlying data structure).
121 | ///
122 | /// [`MeshBuilder::build`]: crate::builder::MeshBuilder::build
123 | pub trait MeshBuilder: ClosedInput {
124 | type Builder: SurfaceBuilder;
125 |
126 | type Vertex;
127 | type Facet: Default;
128 |
129 | /// Constructs a surface.
130 | ///
131 | /// The given function is invoked with a [`SurfaceBuilder`], which can be
132 | /// used to insert vertices and construct facets.
133 | ///
134 | /// [`SurfaceBuilder`]: crate::builder::SurfaceBuilder
135 | fn surface_with(&mut self, f: F) -> Result
136 | where
137 | Self::Error: From,
138 | F: FnOnce(&mut Self::Builder) -> Result;
139 |
140 | /// Builds the mesh.
141 | ///
142 | /// The builder is consumed and a mesh with the constructed surfaces and
143 | /// facets is produced.
144 | ///
145 | /// # Errors
146 | ///
147 | /// Returns a latent error if the constructed surfaces and facets are
148 | /// incompatible with the underlying data structure. May return other
149 | /// errors depending on the details of the implementation.
150 | fn build(self) -> Result {
151 | self.commit().map_err(|(_, error)| error)
152 | }
153 | }
154 |
155 | pub trait SurfaceBuilder: ClosedInput {
156 | type Builder: FacetBuilder;
157 | /// Vertex key.
158 | ///
159 | /// Each vertex is associated with a key of this type. This key is used to
160 | /// reference a given vertex and is required to insert faces with a
161 | /// [`FacetBuilder`].
162 | ///
163 | /// [`FacetBuilder`]: crate::builder::FacetBuilder
164 | type Key: Copy + Eq + Hash;
165 |
166 | type Vertex;
167 | type Facet: Default;
168 |
169 | /// Constructs facets in the surface.
170 | ///
171 | /// The given function is invoked with a [`FacetBuilder`], which can be used
172 | /// to insert facets.
173 | ///
174 | /// [`FacetBuilder`]: crate::builder::FacetBuilder
175 | fn facets_with(&mut self, f: F) -> Result
176 | where
177 | Self::Error: From,
178 | F: FnOnce(&mut Self::Builder) -> Result;
179 |
180 | /// Inserts a vertex into the surface.
181 | ///
182 | /// Returns a key that refers to the inserted vertex. This key can be used
183 | /// to insert facets with a [`FacetBuilder`].
184 | ///
185 | /// [`FacetBuilder`]: crate::builder::FacetBuilder
186 | fn insert_vertex(&mut self, data: T) -> Result
187 | where
188 | Self::Vertex: FromGeometry;
189 | }
190 |
191 | pub trait FacetBuilder: ClosedInput
192 | where
193 | K: Eq + Hash,
194 | {
195 | /// Facet key.
196 | ///
197 | /// Each facet is associated with a key of this type.
198 | type Key: Copy + Eq + Hash;
199 |
200 | type Facet: Default;
201 |
202 | /// Inserts a facet into the associated surface.
203 | ///
204 | /// A facet is formed from connectivity between vertices represented by an
205 | /// ordered slice of vertex keys from the associated [`SurfaceBuilder`].
206 | ///
207 | /// Returns a key that refers to the inserted facet.
208 | ///
209 | /// [`SurfaceBuilder`]: crate::builder::SurfaceBuilder
210 | fn insert_facet(&mut self, keys: T, data: U) -> Result
211 | where
212 | Self::Facet: FromGeometry,
213 | T: AsRef<[K]>;
214 | }
215 |
--------------------------------------------------------------------------------
/plexus/src/constant.rs:
--------------------------------------------------------------------------------
1 | //! Morphisms between constant generics and numeric types.
2 | //!
3 | //! This module provides conversions between `typenum`'s unsigned integer types
4 | //! and `usize` constant generics. These conversions are necessary to perform
5 | //! static computations and comparisons, which cannot yet be done using constant
6 | //! generics alone at the time of writing (e.g., `{N >= 3}`).
7 | //!
8 | //! See discussion on the [Rust internals
9 | //! forum](https://internals.rust-lang.org/t/const-generics-where-restrictions/12742/7).
10 |
11 | // TODO: Move this into the `theon` crate as part of its public API.
12 |
13 | pub type ConstantOf = ::Output;
14 | pub type TypeOf = as ToType>::Output;
15 |
16 | pub struct Constant;
17 |
18 | pub trait ToConstant {
19 | type Output;
20 | }
21 |
22 | pub trait ToType {
23 | type Output;
24 | }
25 |
26 | macro_rules! impl_morphisms {
27 | (types => $($n:ident),*$(,)?) => (
28 | use typenum::Unsigned;
29 |
30 | $(
31 | impl ToConstant for typenum::$n {
32 | type Output = Constant<{ typenum::$n::USIZE }>;
33 | }
34 |
35 | impl ToType for Constant<{ typenum::$n::USIZE }> {
36 | type Output = typenum::$n;
37 | }
38 | )*
39 | );
40 | }
41 | impl_morphisms!(types =>
42 | U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19, U21,
43 | U22, U23, U24, U25, U26, U27, U28, U29, U30, U31, U32,
44 | );
45 |
--------------------------------------------------------------------------------
/plexus/src/encoding/mod.rs:
--------------------------------------------------------------------------------
1 | //! Serialization and encodings.
2 | //!
3 | //! This module provides encoding support enabled via Cargo features. Each
4 | //! enabled encoding has a corresponding sub-module. For example, when [PLY]
5 | //! support is enabled, the `ply` module is exposed. The following table
6 | //! summarizes the encodings supported by Plexus:
7 | //!
8 | //! | Feature | Default | Encoding | Read | Write |
9 | //! |----------------|---------|----------|------|-------|
10 | //! | `encoding-ply` | No | [PLY] | Yes | No |
11 | //!
12 | //! This module provides traits used by all encodings. These traits describe the
13 | //! outputs and inputs of decoders and encoders, respectively. Generally, these
14 | //! traits should **not** be used directly. Instead, prefer the conversion
15 | //! traits exposed for specific encodings, such as `FromPly` when using [PLY].
16 | //!
17 | //! [PLY]: https://en.wikipedia.org/wiki/ply_(file_format)
18 |
19 | pub mod ply;
20 |
21 | use std::fmt::Debug;
22 |
23 | pub trait VertexDecoder {
24 | type Output: IntoIterator- ;
25 | type Vertex;
26 | }
27 |
28 | pub trait FaceDecoder {
29 | type Output: IntoIterator
- ;
30 | type Index: IntoIterator
- ;
31 | type Face;
32 | }
33 |
34 | // TODO: This trait is a bit limiting. Consider implementing more specific
35 | // traits like `FromPly` directly. This could allow more specific
36 | // features to be supported, such as edge geometry for `MeshGraph`s.
37 | pub trait FromEncoding: Sized
38 | where
39 | E: FaceDecoder + VertexDecoder,
40 | {
41 | type Error: Debug;
42 |
43 | fn from_encoding(
44 | vertices: ::Output,
45 | faces: ::Output,
46 | ) -> Result;
47 | }
48 |
--------------------------------------------------------------------------------
/plexus/src/entity/borrow.rs:
--------------------------------------------------------------------------------
1 | pub trait Reborrow {
2 | type Target;
3 |
4 | fn reborrow(&self) -> &Self::Target;
5 | }
6 |
7 | pub trait ReborrowMut: Reborrow {
8 | fn reborrow_mut(&mut self) -> &mut Self::Target;
9 | }
10 |
11 | pub trait ReborrowInto<'a>: Reborrow {
12 | fn reborrow_into(self) -> &'a Self::Target;
13 | }
14 |
15 | impl Reborrow for &'_ T {
16 | type Target = T;
17 |
18 | fn reborrow(&self) -> &Self::Target {
19 | self
20 | }
21 | }
22 |
23 | impl Reborrow for &'_ mut T {
24 | type Target = T;
25 |
26 | fn reborrow(&self) -> &Self::Target {
27 | self
28 | }
29 | }
30 |
31 | impl ReborrowMut for &'_ mut T {
32 | fn reborrow_mut(&mut self) -> &mut Self::Target {
33 | self
34 | }
35 | }
36 |
37 | impl<'a, T> ReborrowInto<'a> for &'a T {
38 | fn reborrow_into(self) -> &'a Self::Target {
39 | self
40 | }
41 | }
42 |
43 | impl<'a, T> ReborrowInto<'a> for &'a mut T {
44 | fn reborrow_into(self) -> &'a Self::Target {
45 | &*self
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/plexus/src/entity/dijkstra.rs:
--------------------------------------------------------------------------------
1 | use derivative::Derivative;
2 | use std::cmp::Reverse;
3 | use std::collections::hash_map::Entry;
4 | use std::collections::{BinaryHeap, HashMap, HashSet};
5 |
6 | use crate::entity::storage::{AsStorage, Enumerate, Get};
7 | use crate::entity::traverse::Adjacency;
8 | use crate::entity::view::{Bind, Unbind};
9 | use crate::entity::EntityError;
10 | use crate::geometry::Metric;
11 |
12 | pub type MetricTree = HashMap, Q)>;
13 |
14 | #[derive(Derivative)]
15 | #[derivative(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
16 | struct KeyedMetric(
17 | #[derivative(Ord = "ignore", PartialEq = "ignore", PartialOrd = "ignore")] K,
18 | Q,
19 | )
20 | where
21 | Q: Eq + Ord;
22 |
23 | pub fn metrics_with<'a, M, T, Q, F>(
24 | from: T,
25 | to: Option,
26 | f: F,
27 | ) -> Result, EntityError>
28 | where
29 | M: 'a + AsStorage,
30 | T: Adjacency + Bind<&'a M> + Copy + Unbind<&'a M>,
31 | Q: Copy + Metric,
32 | F: Fn(T, T) -> Q,
33 | {
34 | let (storage, from) = from.unbind();
35 | let capacity = if let Some(key) = to {
36 | if !storage.as_storage().contains_key(&key) {
37 | return Err(EntityError::EntityNotFound);
38 | }
39 | 0
40 | }
41 | else {
42 | storage.as_storage().len()
43 | };
44 | let mut buffer = BinaryHeap::new();
45 | let mut breadcrumbs = HashSet::with_capacity(capacity);
46 | let mut metrics = HashMap::with_capacity(capacity);
47 |
48 | metrics.insert(from, (None, Q::zero()));
49 | buffer.push(KeyedMetric(from, Reverse(Q::zero())));
50 | while let Some(KeyedMetric(key, Reverse(metric))) = buffer.pop() {
51 | if Some(key) == to {
52 | break;
53 | }
54 | let entity = T::bind(storage, key).ok_or(EntityError::EntityNotFound)?;
55 | if breadcrumbs.insert(entity.key()) {
56 | for adjacent in entity
57 | .adjacency()
58 | .into_iter()
59 | .map(|key| T::bind(storage, key))
60 | {
61 | let adjacent = adjacent.ok_or(EntityError::EntityNotFound)?;
62 | let summand = f(entity, adjacent);
63 | if summand < Q::zero() {
64 | return Err(EntityError::Data);
65 | }
66 | let metric = metric + summand;
67 | match metrics.entry(adjacent.key()) {
68 | Entry::Occupied(entry) => {
69 | if metric < entry.get().1 {
70 | entry.into_mut().1 = metric;
71 | }
72 | }
73 | Entry::Vacant(entry) => {
74 | entry.insert((Some(entity.key()), metric));
75 | }
76 | }
77 | buffer.push(KeyedMetric(adjacent.key(), Reverse(metric)));
78 | }
79 | }
80 | }
81 | Ok(metrics)
82 | }
83 |
84 | #[cfg(test)]
85 | mod tests {
86 | use decorum::R64;
87 | use nalgebra::Point2;
88 | use theon::space::InnerSpace;
89 |
90 | use crate::entity::dijkstra::{self, MetricTree};
91 | use crate::entity::EntityError;
92 | use crate::graph::MeshGraph;
93 | use crate::prelude::*;
94 | use crate::primitive::{Tetragon, Trigon};
95 |
96 | #[test]
97 | fn decreasing_summand() {
98 | let graph = MeshGraph::>::from_raw_buffers(
99 | vec![Tetragon::new(0usize, 1, 2, 3)],
100 | vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
101 | )
102 | .unwrap();
103 | let vertex = graph.vertices().next().unwrap();
104 | assert_eq!(
105 | Err(EntityError::Data),
106 | dijkstra::metrics_with(vertex, None, |_, _| -1isize)
107 | )
108 | }
109 |
110 | #[test]
111 | fn logical_metrics() {
112 | let graph = MeshGraph::<()>::from_raw_buffers(vec![Trigon::new(0usize, 1, 2)], vec![(); 3])
113 | .unwrap();
114 | let vertex = graph.vertices().next().unwrap();
115 | let metrics = dijkstra::metrics_with(vertex, None, |_, _| 1usize).unwrap();
116 | let a = vertex.key();
117 | let b = vertex.outgoing_arc().destination_vertex().key();
118 | let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
119 | let aq = *metrics.get(&a).unwrap();
120 | let bq = *metrics.get(&b).unwrap();
121 | let cq = *metrics.get(&c).unwrap();
122 |
123 | assert_eq!(aq, (None, 0));
124 | assert_eq!(bq, (Some(a), 1));
125 | assert_eq!(cq, (Some(a), 1));
126 | }
127 |
128 | // TODO: Use approximated comparisons in assertions.
129 | #[test]
130 | fn euclidean_distance_metrics() {
131 | let graph = MeshGraph::>::from_raw_buffers(
132 | vec![Tetragon::new(0usize, 1, 2, 3)],
133 | vec![(-1.0, -1.0), (1.0, -1.0), (1.0, 1.0), (-1.0, 1.0)],
134 | )
135 | .unwrap();
136 | let vertex = graph.vertices().next().unwrap();
137 | let metrics: MetricTree<_, R64> = dijkstra::metrics_with(vertex, None, |from, to| {
138 | R64::assert((to.position() - from.position()).magnitude())
139 | })
140 | .unwrap();
141 | let a = vertex.key();
142 | let b = vertex.outgoing_arc().destination_vertex().key();
143 | let c = vertex.outgoing_arc().next_arc().destination_vertex().key();
144 | let d = vertex
145 | .outgoing_arc()
146 | .next_arc()
147 | .next_arc()
148 | .destination_vertex()
149 | .key();
150 | let aq = *metrics.get(&a).unwrap();
151 | let bq = *metrics.get(&b).unwrap();
152 | let cq = *metrics.get(&c).unwrap();
153 | let dq = *metrics.get(&d).unwrap();
154 |
155 | assert_eq!(aq, (None, R64::assert(0.0)));
156 | assert_eq!(bq, (Some(a), R64::assert(2.0)));
157 | assert_eq!(cq, (Some(b), R64::assert(4.0)));
158 | assert_eq!(dq, (Some(a), R64::assert(2.0)));
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/plexus/src/entity/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod borrow;
2 | pub mod dijkstra;
3 | pub mod storage;
4 | pub mod traverse;
5 | pub mod view;
6 |
7 | use thiserror::Error;
8 |
9 | use crate::entity::storage::{Dispatch, Key, Storage};
10 |
11 | #[derive(Debug, Eq, Error, PartialEq)]
12 | pub enum EntityError {
13 | #[error("required entity not found")]
14 | EntityNotFound,
15 | #[error("data operation failed")]
16 | Data,
17 | }
18 |
19 | pub trait Entity: Sized {
20 | type Key: Key;
21 | type Storage: Default + Dispatch + Storage;
22 | }
23 |
24 | pub trait Payload: Entity {
25 | type Data;
26 |
27 | fn get(&self) -> &Self::Data;
28 |
29 | fn get_mut(&mut self) -> &mut Self::Data;
30 | }
31 |
--------------------------------------------------------------------------------
/plexus/src/entity/storage/hash.rs:
--------------------------------------------------------------------------------
1 | use ahash::AHashMap;
2 | use std::hash::Hash;
3 | use std::marker::PhantomData;
4 |
5 | use crate::entity::storage::{
6 | AsStorage, AsStorageMut, DependentStorage, Dispatch, Dynamic, Enumerate, Get, IncrementalKeyer,
7 | IndependentStorage, InnerKey, Insert, InsertWithKey, Key, Keyer, Mode, Remove, Static,
8 | StorageTarget,
9 | };
10 | use crate::entity::{Entity, Payload};
11 |
12 | // TODO: The `Keyer` parameter `R` of `HashStorage` cannot be parameterized when
13 | // implementing the `AsStorage` and `Dispatch` traits even if the
14 | // conflicting implementations use a private local type or the `Keyer`
15 | // trait is private. Instead, this is implemented more specifically for
16 | // `IncrementalKeyer`. Perhaps this will be possible in the future.
17 | //
18 | // See https://github.com/rust-lang/rust/issues/48869
19 |
20 | pub struct HashStorage
21 | where
22 | E: Entity,
23 | R: Default,
24 | P: Mode,
25 | {
26 | inner: AHashMap::Key>, E>,
27 | keyer: R,
28 | phantom: PhantomData P>,
29 | }
30 |
31 | impl HashStorage
32 | where
33 | E: Entity,
34 | InnerKey: Eq + Hash,
35 | R: Default,
36 | P: Mode,
37 | {
38 | pub fn shrink_to_fit(&mut self) {
39 | self.inner.shrink_to_fit();
40 | }
41 | }
42 |
43 | impl AsStorage for HashStorage
44 | where
45 | E: Entity,
46 | InnerKey: Eq + Hash,
47 | {
48 | fn as_storage(&self) -> &StorageTarget {
49 | self
50 | }
51 | }
52 |
53 | impl AsStorage for HashStorage
54 | where
55 | E: Entity,
56 | E::Key: Key,
57 | {
58 | fn as_storage(&self) -> &StorageTarget {
59 | self
60 | }
61 | }
62 |
63 | impl AsStorage for HashStorage
64 | where
65 | E: Entity,
66 | InnerKey: Eq + Hash,
67 | R: 'static + Default,
68 | {
69 | fn as_storage(&self) -> &StorageTarget {
70 | self
71 | }
72 | }
73 |
74 | impl AsStorageMut for HashStorage
75 | where
76 | E: Entity,
77 | InnerKey: Eq + Hash,
78 | {
79 | fn as_storage_mut(&mut self) -> &mut StorageTarget {
80 | self
81 | }
82 | }
83 |
84 | impl AsStorageMut for HashStorage
85 | where
86 | E: Entity,
87 | E::Key: Key,
88 | {
89 | fn as_storage_mut(&mut self) -> &mut StorageTarget {
90 | self
91 | }
92 | }
93 |
94 | impl AsStorageMut for HashStorage
95 | where
96 | E: Entity,
97 | InnerKey: Eq + Hash,
98 | R: 'static + Default,
99 | {
100 | fn as_storage_mut(&mut self) -> &mut StorageTarget {
101 | self
102 | }
103 | }
104 |
105 | impl Default for HashStorage
106 | where
107 | E: Entity,
108 | R: Default,
109 | P: Mode,
110 | {
111 | fn default() -> Self {
112 | HashStorage {
113 | inner: Default::default(),
114 | keyer: Default::default(),
115 | phantom: PhantomData,
116 | }
117 | }
118 | }
119 |
120 | #[rustfmt::skip]
121 | impl Dispatch for HashStorage
122 | where
123 | E: Entity,
124 | InnerKey: Eq + Hash,
125 | {
126 | type Target<'a> = dyn 'a + DependentStorage where E: 'a;
127 | }
128 |
129 | #[rustfmt::skip]
130 | impl Dispatch for HashStorage
131 | where
132 | E: Entity,
133 | E::Key: Key,
134 | {
135 | type Target<'a> = dyn 'a + IndependentStorage where E: 'a;
136 | }
137 |
138 | #[rustfmt::skip]
139 | impl Dispatch for HashStorage
140 | where
141 | E: Entity,
142 | InnerKey: Eq + Hash,
143 | R: 'static + Default,
144 | {
145 | type Target<'a> = Self where E: 'a;
146 | }
147 |
148 | impl Enumerate for HashStorage
149 | where
150 | E: Entity,
151 | InnerKey: Eq + Hash,
152 | R: Default,
153 | P: Mode,
154 | {
155 | fn len(&self) -> usize {
156 | self.inner.len()
157 | }
158 |
159 | fn iter(&self) -> Box> {
160 | Box::new(
161 | self.inner
162 | .iter()
163 | .map(|(key, entity)| (E::Key::from_inner(*key), entity)),
164 | )
165 | }
166 |
167 | fn iter_mut(&mut self) -> Box>
168 | where
169 | E: Payload,
170 | {
171 | Box::new(
172 | self.inner
173 | .iter_mut()
174 | .map(|(key, entity)| (E::Key::from_inner(*key), entity.get_mut())),
175 | )
176 | }
177 | }
178 |
179 | impl Get for HashStorage
180 | where
181 | E: Entity,
182 | InnerKey: Eq + Hash,
183 | R: Default,
184 | P: Mode,
185 | {
186 | fn get(&self, key: &E::Key) -> Option<&E> {
187 | self.inner.get(&key.into_inner())
188 | }
189 |
190 | fn get_mut(&mut self, key: &E::Key) -> Option<&mut E> {
191 | self.inner.get_mut(&key.into_inner())
192 | }
193 | }
194 |
195 | impl Insert for HashStorage
196 | where
197 | E: Entity,
198 | InnerKey: Eq + Hash,
199 | R: Keyer,
200 | P: Mode,
201 | {
202 | fn insert(&mut self, entity: E) -> E::Key {
203 | let key = self.keyer.next();
204 | self.inner.insert(key, entity);
205 | Key::from_inner(key)
206 | }
207 | }
208 |
209 | impl InsertWithKey for HashStorage
210 | where
211 | E: Entity,
212 | InnerKey: Eq + Hash,
213 | P: Mode,
214 | {
215 | fn insert_with_key(&mut self, key: &E::Key, entity: E) -> Option {
216 | self.inner.insert(key.into_inner(), entity)
217 | }
218 | }
219 |
220 | impl