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 change_source(&self) -> ChangeSource {
40 ChangeSource::Unknown
41 }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum ChangeSource {
46 Unknown,
47 Static,
48 Descriptor(usize),
49}
50
51impl ChangeSource {
52 #[inline]
53 pub fn reacts_to(self, descriptor_index: usize) -> bool {
54 match self {
55 Self::Unknown => true,
56 Self::Static => false,
57 Self::Descriptor(index) => index == descriptor_index,
58 }
59 }
60
61 #[inline]
62 pub fn owns_descriptor(self, descriptor_index: usize) -> bool {
63 matches!(self, Self::Descriptor(index) if index == descriptor_index)
64 }
65
66 #[inline]
67 pub fn is_unknown(self) -> bool {
68 matches!(self, Self::Unknown)
69 }
70
71 #[inline]
72 pub fn same_index_domain(self, other: Self) -> bool {
73 matches!((self, other), (Self::Descriptor(left), Self::Descriptor(right)) if left == right)
74 }
75
76 #[inline]
77 pub fn assert_localizes(self, descriptor_index: usize, constraint_name: &str) -> bool {
78 if self.owns_descriptor(descriptor_index) {
79 return true;
80 }
81 if self.reacts_to(descriptor_index) {
82 panic!(
83 "constraint `{constraint_name}` received descriptor {descriptor_index}, but source {self:?} cannot localize entity indexes"
84 );
85 }
86 false
87 }
88}
89
90pub trait FlattenExtract<P>: Send + Sync {
91 type Item;
92
93 fn extract<'s>(&self, parent: &'s P) -> &'s [Self::Item];
94}
95
96impl<S, A, F> CollectionExtract<S> for F
97where
98 F: for<'a> Fn(&'a S) -> &'a [A] + Send + Sync,
99{
100 type Item = A;
101
102 #[inline]
103 fn extract<'s>(&self, s: &'s S) -> &'s [A] {
104 self(s)
105 }
106}
107
108impl<P, B, F> FlattenExtract<P> for F
109where
110 F: for<'a> Fn(&'a P) -> &'a [B] + Send + Sync,
111{
112 type Item = B;
113
114 #[inline]
115 fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
116 self(parent)
117 }
118}
119
120#[derive(Clone, Copy)]
121pub struct FlattenVecExtract<F>(pub F);
122
123impl<P, B, F> FlattenExtract<P> for FlattenVecExtract<F>
124where
125 F: for<'a> Fn(&'a P) -> &'a Vec<B> + Send + Sync,
126{
127 type Item = B;
128
129 #[inline]
130 fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
131 (self.0)(parent).as_slice()
132 }
133}
134
135#[derive(Clone, Copy)]
136pub struct SourceExtract<E> {
137 extractor: E,
138 change_source: ChangeSource,
139}
140
141impl<E> SourceExtract<E> {
142 pub fn new(extractor: E, change_source: ChangeSource) -> Self {
143 Self {
144 extractor,
145 change_source,
146 }
147 }
148
149 pub fn extractor(&self) -> &E {
150 &self.extractor
151 }
152}
153
154impl<S, E> CollectionExtract<S> for SourceExtract<E>
155where
156 E: CollectionExtract<S>,
157{
158 type Item = E::Item;
159
160 #[inline]
161 fn extract<'s>(&self, s: &'s S) -> &'s [Self::Item] {
162 self.extractor.extract(s)
163 }
164
165 fn change_source(&self) -> ChangeSource {
166 self.change_source
167 }
168}
169
170pub struct VecExtract<F>(pub F);
175
176impl<S, A, F> CollectionExtract<S> for VecExtract<F>
177where
178 F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
179{
180 type Item = A;
181
182 #[inline]
183 fn extract<'s>(&self, s: &'s S) -> &'s [A] {
184 (self.0)(s).as_slice()
185 }
186}
187
188pub fn vec<S, A, F>(f: F) -> VecExtract<F>
207where
208 F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
209{
210 VecExtract(f)
211}
212
213pub fn source<E>(extractor: E, change_source: ChangeSource) -> SourceExtract<E> {
214 SourceExtract::new(extractor, change_source)
215}