use super::{BoundOccupancy, Scene, StoredVolume};
use crate::{AtomSelection, CoreError, OccupancyStream, StructureHandle, VolumeHandle};
use std::sync::Arc;
impl Scene {
pub fn add_occupancy_stream(
&mut self,
structure: StructureHandle,
selection: &AtomSelection,
stream: OccupancyStream,
) -> Result<VolumeHandle, CoreError> {
let rows = selected_rows(self, structure, selection)?;
self.volume_revision = self.volume_revision.wrapping_add(1);
Ok(VolumeHandle(self.volumes.insert(StoredVolume {
value: None,
occupancy: Some(BoundOccupancy {
stream,
structure,
atom_rows: Arc::from(rows),
}),
revision: 0,
})))
}
pub fn replace_occupancy_stream(
&mut self,
handle: VolumeHandle,
structure: StructureHandle,
selection: &AtomSelection,
stream: OccupancyStream,
) -> Result<(), CoreError> {
let rows = selected_rows(self, structure, selection)?;
let stored = self
.volumes
.get_mut(handle.0)
.filter(|stored| stored.occupancy.is_some())
.ok_or(CoreError::StaleHandle)?;
stored.value = None;
stored.occupancy = Some(BoundOccupancy {
stream,
structure,
atom_rows: Arc::from(rows),
});
stored.revision = stored.revision.wrapping_add(1);
self.volume_revision = self.volume_revision.wrapping_add(1);
Ok(())
}
#[must_use]
pub fn occupancy_stream(
&self,
handle: VolumeHandle,
) -> Option<(&OccupancyStream, StructureHandle, &[u32])> {
let value = self.volumes.get(handle.0)?.occupancy.as_ref()?;
Some((&value.stream, value.structure, &value.atom_rows))
}
#[must_use]
pub fn has_occupancy_stream(&self) -> bool {
self.volumes
.iter()
.any(|(_, volume)| volume.occupancy.is_some())
}
pub fn remove_occupancy_stream(&mut self, handle: VolumeHandle) -> bool {
let Some(stored) = self.volumes.get(handle.0) else {
return false;
};
if stored.occupancy.is_none() {
return false;
}
let removed = self.volumes.remove(handle.0).is_some();
if removed {
self.volume_revision = self.volume_revision.wrapping_add(1);
}
removed
}
}
fn selected_rows(
scene: &Scene,
structure: StructureHandle,
selection: &AtomSelection,
) -> Result<Vec<u32>, CoreError> {
let atom_count = scene
.structure(structure)
.ok_or(CoreError::StaleHandle)?
.atoms
.len();
let mut rows = Vec::new();
selection.for_each(atom_count, |row| rows.push(row));
rows.sort_unstable();
rows.dedup();
Ok(rows)
}