pumpkin_core/engine/cp/propagation/
store.rs

1use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::ops::Index;
4use std::ops::IndexMut;
5
6use super::Propagator;
7use super::PropagatorId;
8use crate::containers::KeyedVec;
9use crate::containers::Slot;
10use crate::engine::DebugDyn;
11
12/// A central store for propagators.
13#[derive(Default)]
14pub(crate) struct PropagatorStore {
15    propagators: KeyedVec<PropagatorId, Box<dyn Propagator>>,
16}
17
18/// A typed wrapper around a propagator id that allows retrieving concrete propagators instead of
19/// type-erased instances `Box<dyn Propagator>`.
20#[derive(Debug, PartialEq, Eq, Hash)]
21pub struct PropagatorHandle<P> {
22    id: PropagatorId,
23    propagator: PhantomData<P>,
24}
25
26impl<P> PropagatorHandle<P> {
27    /// Get the type-erased [`PropagatorId`] of the propagator.
28    pub(crate) fn propagator_id(self) -> PropagatorId {
29        self.id
30    }
31}
32
33impl<P> Clone for PropagatorHandle<P> {
34    fn clone(&self) -> Self {
35        *self
36    }
37}
38
39impl<P> Copy for PropagatorHandle<P> {}
40
41impl PropagatorStore {
42    pub(crate) fn num_propagators(&self) -> usize {
43        self.propagators.len()
44    }
45
46    pub(crate) fn iter_propagators(&self) -> impl Iterator<Item = &dyn Propagator> + '_ {
47        self.propagators.iter().map(|b| b.as_ref())
48    }
49
50    pub(crate) fn iter_propagators_mut(
51        &mut self,
52    ) -> impl Iterator<Item = &mut Box<dyn Propagator>> + '_ {
53        self.propagators.iter_mut()
54    }
55
56    pub(crate) fn new_propagator<P>(&mut self) -> NewPropagatorSlot<'_, P> {
57        NewPropagatorSlot {
58            underlying_slot: self.propagators.new_slot(),
59            propagator_type: PhantomData,
60        }
61    }
62
63    /// Get an exclusive reference to the propagator identified by the given handle.
64    ///
65    /// For more info, see [`Self::get_propagator`].
66    pub(crate) fn get_propagator_mut<P: Propagator>(
67        &mut self,
68        handle: PropagatorHandle<P>,
69    ) -> Option<&mut P> {
70        self[handle.id].downcast_mut()
71    }
72
73    /// Get the given [`PropagatorId`] as a handle if the ID points to a propagator of type `P`.
74    pub(crate) fn as_propagator_handle<P: Propagator>(
75        &self,
76        propagator_id: PropagatorId,
77    ) -> Option<PropagatorHandle<P>> {
78        if self[propagator_id].is::<P>() {
79            Some(PropagatorHandle {
80                id: propagator_id,
81                propagator: PhantomData,
82            })
83        } else {
84            None
85        }
86    }
87
88    #[cfg(test)]
89    pub(crate) fn keys(&self) -> impl Iterator<Item = PropagatorId> + '_ {
90        self.propagators.keys()
91    }
92}
93
94impl Index<PropagatorId> for PropagatorStore {
95    type Output = dyn Propagator;
96
97    fn index(&self, index: PropagatorId) -> &Self::Output {
98        self.propagators[index].as_ref()
99    }
100}
101
102impl IndexMut<PropagatorId> for PropagatorStore {
103    fn index_mut(&mut self, index: PropagatorId) -> &mut Self::Output {
104        self.propagators[index].as_mut()
105    }
106}
107
108/// Wrapper around a [`Slot`] that provides a strongly typed [`PropagatorHandle`] instead of a
109/// type-erased [`PropagatorId`].
110pub(crate) struct NewPropagatorSlot<'a, P> {
111    underlying_slot: Slot<'a, PropagatorId, Box<dyn Propagator>>,
112    propagator_type: PhantomData<P>,
113}
114
115impl<P: Propagator + 'static> NewPropagatorSlot<'_, P> {
116    /// The handle corresponding to this slot.
117    pub(crate) fn key(&self) -> PropagatorHandle<P> {
118        PropagatorHandle {
119            id: self.underlying_slot.key(),
120            propagator: PhantomData,
121        }
122    }
123
124    /// Put a propagator into the slot.
125    pub(crate) fn populate(self, propagator: P) -> PropagatorHandle<P> {
126        PropagatorHandle {
127            id: self.underlying_slot.populate(Box::new(propagator)),
128            propagator: PhantomData,
129        }
130    }
131}
132
133impl Debug for PropagatorStore {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        let propagators: Vec<_> = self
136            .propagators
137            .iter()
138            .map(|_| DebugDyn::from("Propagator"))
139            .collect();
140
141        write!(f, "{propagators:?}")
142    }
143}