molframe_core/topology/
entity.rs1use crate::index::EntityIndex;
15use crate::limits::CapacityError;
16use crate::optional::OptionalSymbol;
17use crate::symbol::SymbolId;
18use std::ops::Range;
19use std::sync::Arc;
20
21#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
23#[non_exhaustive]
24pub enum EntityKind {
25 Polymer,
27 NonPolymer,
29 Water,
31 Branched,
33 #[default]
35 Unknown,
36}
37
38crate::contract::closed_vocabulary!(
39 EntityKind,
40 "entity_kind",
41 [
42 (EntityKind::Polymer, "polymer"),
43 (EntityKind::NonPolymer, "non-polymer"),
44 (EntityKind::Water, "water"),
45 (EntityKind::Branched, "branched"),
46 (EntityKind::Unknown, "unknown"),
47 ]
48);
49
50#[derive(Clone, Debug, Default)]
56pub struct EntityTable {
57 kind: Arc<Vec<EntityKind>>,
58 id: Arc<Vec<OptionalSymbol>>,
59 description: Arc<Vec<OptionalSymbol>>,
60 sequence_span: Arc<Vec<Range<u32>>>,
61 sequence_pool: Arc<Vec<SymbolId>>,
62}
63
64impl EntityTable {
65 #[must_use]
67 pub fn len(&self) -> usize {
68 self.kind.len()
69 }
70
71 #[must_use]
73 pub fn is_empty(&self) -> bool {
74 self.kind.is_empty()
75 }
76
77 pub fn push(
83 &mut self,
84 id: SymbolId,
85 kind: EntityKind,
86 description: OptionalSymbol,
87 canonical_sequence: &[SymbolId],
88 ) -> Result<EntityIndex, CapacityError> {
89 self.push_with_optional_id(
90 OptionalSymbol::some(id),
91 kind,
92 description,
93 canonical_sequence,
94 )
95 }
96
97 pub fn push_without_id(
103 &mut self,
104 kind: EntityKind,
105 description: OptionalSymbol,
106 canonical_sequence: &[SymbolId],
107 ) -> Result<EntityIndex, CapacityError> {
108 self.push_with_optional_id(OptionalSymbol::NONE, kind, description, canonical_sequence)
109 }
110
111 fn push_with_optional_id(
112 &mut self,
113 id: OptionalSymbol,
114 kind: EntityKind,
115 description: OptionalSymbol,
116 canonical_sequence: &[SymbolId],
117 ) -> Result<EntityIndex, CapacityError> {
118 let error = || CapacityError::new("entity table");
119 let start = u32::try_from(self.sequence_pool.len()).map_err(|_| error())?;
120 let added = u32::try_from(canonical_sequence.len()).map_err(|_| error())?;
121 let end = start.checked_add(added).ok_or_else(error)?;
122 let position = u32::try_from(self.kind.len()).map_err(|_| error())?;
123 Arc::make_mut(&mut self.sequence_pool).extend_from_slice(canonical_sequence);
124 Arc::make_mut(&mut self.kind).push(kind);
125 Arc::make_mut(&mut self.id).push(id);
126 Arc::make_mut(&mut self.description).push(description);
127 Arc::make_mut(&mut self.sequence_span).push(start..end);
128 Ok(EntityIndex::new(position))
129 }
130
131 #[must_use]
133 pub fn kind(&self, entity: EntityIndex) -> Option<EntityKind> {
134 self.kind.get(entity.as_usize()).copied()
135 }
136
137 #[must_use]
139 pub fn id(&self, entity: EntityIndex) -> Option<SymbolId> {
140 self.id
141 .get(entity.as_usize())
142 .copied()
143 .and_then(OptionalSymbol::get)
144 }
145
146 #[must_use]
153 pub fn find_by_id(&self, id: SymbolId) -> Option<EntityIndex> {
154 self.id
155 .iter()
156 .position(|candidate| candidate.get() == Some(id))
157 .and_then(|position| u32::try_from(position).ok())
158 .map(EntityIndex::new)
159 }
160
161 #[must_use]
163 pub fn description(&self, entity: EntityIndex) -> Option<SymbolId> {
164 self.description
165 .get(entity.as_usize())
166 .copied()
167 .and_then(OptionalSymbol::get)
168 }
169
170 #[must_use]
175 pub fn canonical_sequence(&self, entity: EntityIndex) -> &[SymbolId] {
176 let Some(span) = self.sequence_span.get(entity.as_usize()) else {
177 return &[];
178 };
179
180 sequence_slice(&self.sequence_pool, span)
181 }
182
183 pub fn iter(&self) -> impl Iterator<Item = EntityIndex> + '_ {
186 self.kind
187 .iter()
188 .enumerate()
189 .filter_map(|(position, _)| u32::try_from(position).ok().map(EntityIndex::new))
190 }
191}
192
193fn sequence_slice<'a>(pool: &'a [SymbolId], span: &Range<u32>) -> &'a [SymbolId] {
194 let Ok(start) = usize::try_from(span.start) else {
195 return &[];
196 };
197 let Ok(end) = usize::try_from(span.end) else {
198 return &[];
199 };
200
201 match pool.get(start..end) {
202 Some(sequence) => sequence,
203 None => &[],
204 }
205}