solverforge_scoring/stream/
collection_extract.rs1pub trait CollectionExtract<S>: Send + Sync {
30 type Item;
32
33 fn extract<'s>(&self, s: &'s S) -> &'s [Self::Item];
35
36 fn contains(&self, _s: &S, _item: &Self::Item) -> bool {
38 true
39 }
40
41 fn change_source(&self) -> ChangeSource {
45 ChangeSource::Unknown
46 }
47}
48
49#[doc(hidden)]
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum ChangeSource {
52 Unknown,
53 Static,
54 Descriptor(usize),
55}
56
57impl ChangeSource {
58 #[inline]
59 pub fn reacts_to(self, descriptor_index: usize) -> bool {
60 match self {
61 Self::Unknown => true,
62 Self::Static => false,
63 Self::Descriptor(index) => index == descriptor_index,
64 }
65 }
66
67 #[inline]
68 pub fn owns_descriptor(self, descriptor_index: usize) -> bool {
69 matches!(self, Self::Descriptor(index) if index == descriptor_index)
70 }
71
72 #[inline]
73 pub fn is_unknown(self) -> bool {
74 matches!(self, Self::Unknown)
75 }
76
77 #[inline]
78 pub fn same_index_domain(self, other: Self) -> bool {
79 matches!((self, other), (Self::Descriptor(left), Self::Descriptor(right)) if left == right)
80 }
81
82 #[inline]
83 pub fn assert_localizes(self, descriptor_index: usize, constraint_name: &str) -> bool {
84 if self.owns_descriptor(descriptor_index) {
85 return true;
86 }
87 if self.reacts_to(descriptor_index) {
88 panic!(
89 "constraint `{constraint_name}` received descriptor {descriptor_index}, but source {self:?} cannot localize entity indexes"
90 );
91 }
92 false
93 }
94}
95
96pub trait FlattenExtract<P>: Send + Sync {
97 type Item;
98
99 fn extract<'s>(&self, parent: &'s P) -> &'s [Self::Item];
100}
101
102impl<S, A, F> CollectionExtract<S> for F
103where
104 F: for<'a> Fn(&'a S) -> &'a [A] + Send + Sync,
105{
106 type Item = A;
107
108 #[inline]
109 fn extract<'s>(&self, s: &'s S) -> &'s [A] {
110 self(s)
111 }
112}
113
114impl<P, B, F> FlattenExtract<P> for F
115where
116 F: for<'a> Fn(&'a P) -> &'a [B] + Send + Sync,
117{
118 type Item = B;
119
120 #[inline]
121 fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
122 self(parent)
123 }
124}
125
126#[derive(Clone, Copy)]
127pub struct FlattenVecExtract<F>(pub F);
128
129impl<P, B, F> FlattenExtract<P> for FlattenVecExtract<F>
130where
131 F: for<'a> Fn(&'a P) -> &'a Vec<B> + Send + Sync,
132{
133 type Item = B;
134
135 #[inline]
136 fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
137 (self.0)(parent).as_slice()
138 }
139}
140
141#[doc(hidden)]
142#[derive(Clone, Copy)]
143pub struct SourceExtract<E> {
144 extractor: E,
145 change_source: ChangeSource,
146}
147
148impl<E> SourceExtract<E> {
149 pub fn new(extractor: E, change_source: ChangeSource) -> Self {
150 Self {
151 extractor,
152 change_source,
153 }
154 }
155
156 pub fn extractor(&self) -> &E {
157 &self.extractor
158 }
159}
160
161impl<S, E> CollectionExtract<S> for SourceExtract<E>
162where
163 E: CollectionExtract<S>,
164{
165 type Item = E::Item;
166
167 #[inline]
168 fn extract<'s>(&self, s: &'s S) -> &'s [Self::Item] {
169 self.extractor.extract(s)
170 }
171
172 #[inline]
173 fn contains(&self, s: &S, item: &Self::Item) -> bool {
174 self.extractor.contains(s, item)
175 }
176
177 fn change_source(&self) -> ChangeSource {
178 self.change_source
179 }
180}
181
182pub struct VecExtract<F>(pub F);
187
188impl<S, A, F> CollectionExtract<S> for VecExtract<F>
189where
190 F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
191{
192 type Item = A;
193
194 #[inline]
195 fn extract<'s>(&self, s: &'s S) -> &'s [A] {
196 (self.0)(s).as_slice()
197 }
198}
199
200pub fn vec<S, A, F>(f: F) -> VecExtract<F>
219where
220 F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
221{
222 VecExtract(f)
223}
224
225#[doc(hidden)]
226pub fn source<E>(extractor: E, change_source: ChangeSource) -> SourceExtract<E> {
227 SourceExtract::new(extractor, change_source)
228}