molframe_core/topology/
model.rs1use crate::index::ModelIndex;
4use crate::limits::{CapacityError, TableError};
5use std::ops::Range;
6use std::sync::Arc;
7
8#[derive(Clone, Debug, Default)]
10pub struct ModelTable {
11 first_chain: Arc<Vec<u32>>,
12 chain_count: Arc<Vec<u32>>,
13 model_num: Arc<Vec<i32>>,
14}
15
16impl ModelTable {
17 #[must_use]
19 pub fn len(&self) -> usize {
20 self.model_num.len()
21 }
22
23 #[must_use]
25 pub fn is_empty(&self) -> bool {
26 self.model_num.is_empty()
27 }
28
29 pub fn push(&mut self, model_num: i32, chains: Range<u32>) -> Result<ModelIndex, TableError> {
35 let position = u32::try_from(self.model_num.len())
36 .map_err(|_| TableError::Capacity(CapacityError::new("model table")))?;
37 let chain_count = chains
38 .end
39 .checked_sub(chains.start)
40 .ok_or(TableError::ReversedRange { table: "model" })?;
41 Arc::make_mut(&mut self.first_chain).push(chains.start);
42 Arc::make_mut(&mut self.chain_count).push(chain_count);
43 Arc::make_mut(&mut self.model_num).push(model_num);
44 Ok(ModelIndex::new(position))
45 }
46
47 #[must_use]
53 pub fn model_num(&self, model: ModelIndex) -> Option<i32> {
54 self.model_num.get(model.as_usize()).copied()
55 }
56
57 #[must_use]
59 pub fn chains(&self, model: ModelIndex) -> Option<Range<u32>> {
60 stored_range(&self.first_chain, &self.chain_count, model.as_usize())
61 }
62
63 pub fn iter(&self) -> impl Iterator<Item = ModelIndex> + '_ {
66 self.model_num
67 .iter()
68 .enumerate()
69 .filter_map(|(position, _)| u32::try_from(position).ok().map(ModelIndex::new))
70 }
71}
72
73fn stored_range(starts: &[u32], counts: &[u32], index: usize) -> Option<Range<u32>> {
74 let start = *starts.get(index)?;
75 let count = *counts.get(index)?;
76
77 Some(start..start.checked_add(count)?)
78}