use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::Index;
use std::ops::IndexMut;
use super::Propagator;
use super::PropagatorId;
use crate::containers::KeyedVec;
use crate::containers::Slot;
use crate::engine::DebugDyn;
#[derive(Default, Clone)]
pub(crate) struct PropagatorStore {
propagators: KeyedVec<PropagatorId, Box<dyn Propagator>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PropagatorHandle<P> {
id: PropagatorId,
propagator: PhantomData<P>,
}
impl<P> PropagatorHandle<P> {
pub(crate) fn new(propagator_id: PropagatorId) -> PropagatorHandle<P> {
Self {
id: propagator_id,
propagator: PhantomData,
}
}
pub(crate) fn propagator_id(self) -> PropagatorId {
self.id
}
}
impl<P> Clone for PropagatorHandle<P> {
fn clone(&self) -> Self {
*self
}
}
impl<P> Copy for PropagatorHandle<P> {}
impl PropagatorStore {
pub(crate) fn num_propagators(&self) -> usize {
self.propagators.len()
}
pub(crate) fn iter_propagators(&self) -> impl Iterator<Item = &dyn Propagator> + '_ {
self.propagators.iter().map(|b| b.as_ref())
}
pub(crate) fn iter_propagators_mut(
&mut self,
) -> impl Iterator<Item = &mut Box<dyn Propagator>> + '_ {
self.propagators.iter_mut()
}
pub(crate) fn new_propagator<P>(&mut self) -> NewPropagatorSlot<'_, P> {
NewPropagatorSlot {
underlying_slot: self.propagators.new_slot(),
propagator_type: PhantomData,
}
}
pub(crate) fn get_propagator<P: Propagator>(&self, handle: PropagatorHandle<P>) -> Option<&P> {
self[handle.id].downcast_ref()
}
pub(crate) fn get_propagator_mut<P: Propagator>(
&mut self,
handle: PropagatorHandle<P>,
) -> Option<&mut P> {
self[handle.id].downcast_mut()
}
pub(crate) fn as_propagator_handle<P: Propagator>(
&self,
propagator_id: PropagatorId,
) -> Option<PropagatorHandle<P>> {
if self[propagator_id].is::<P>() {
Some(PropagatorHandle {
id: propagator_id,
propagator: PhantomData,
})
} else {
None
}
}
}
impl Index<PropagatorId> for PropagatorStore {
type Output = dyn Propagator;
fn index(&self, index: PropagatorId) -> &Self::Output {
self.propagators[index].as_ref()
}
}
impl IndexMut<PropagatorId> for PropagatorStore {
fn index_mut(&mut self, index: PropagatorId) -> &mut Self::Output {
self.propagators[index].as_mut()
}
}
pub(crate) struct NewPropagatorSlot<'a, P> {
underlying_slot: Slot<'a, PropagatorId, Box<dyn Propagator>>,
propagator_type: PhantomData<P>,
}
impl<P: Propagator + 'static> NewPropagatorSlot<'_, P> {
pub(crate) fn key(&self) -> PropagatorHandle<P> {
PropagatorHandle {
id: self.underlying_slot.key(),
propagator: PhantomData,
}
}
pub(crate) fn populate(self, propagator: P) -> PropagatorHandle<P> {
PropagatorHandle {
id: self.underlying_slot.populate(Box::new(propagator)),
propagator: PhantomData,
}
}
}
impl Debug for PropagatorStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let propagators: Vec<_> = self
.propagators
.iter()
.map(|_| DebugDyn::from("Propagator"))
.collect();
write!(f, "{propagators:?}")
}
}